diff -r f5050f1da672 -r 04becd199f91 javacommons/comms/ipclib/socket/src/socketconnection.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javacommons/comms/ipclib/socket/src/socketconnection.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,199 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: ?Description +* +*/ + +#include + +#include +#include + +#include "logger.h" + +#include "socketconnection.h" + +const unsigned int INVALID_THREAD_ID = 0; + +namespace java +{ +namespace comms +{ +using java::util::ScopedLock; + +SocketConnection::SocketConnection(IpcListener* aListener) + : mThreadId(INVALID_THREAD_ID), mListener(aListener), mPort(0) +{ + init(); +} + +SocketConnection::SocketConnection(IpcListener* aListener, int aSocketFd) + : mThreadId(INVALID_THREAD_ID), mSocket(aSocketFd), mListener(aListener), mPort(0) +{ + init(); +} + +void SocketConnection::init() +{ +// JELOG2(EJavaComms); + /* + * The SIGPIPE signal will be received if the peer has gone away + * and an attempt is made to write data to the peer. Ignoring this + * signal causes the write operation to receive an EPIPE error. + * Thus, the user is informed about what happened. + */ +#ifndef __SYMBIAN32__ + signal(SIGPIPE, SIG_IGN); +#endif +} + +SocketConnection::~SocketConnection() +{ +} + +int SocketConnection::connect(int aPort) +{ +// JELOG2(EJavaComms); + + if (mThreadId != INVALID_THREAD_ID) return 0; + mPort = aPort; + int rc = mSocket.open(aPort); + + if (!rc) + { + rc = pthread_create(&mThreadId, 0, SocketConnection::messageLoop, this); + if (rc!=0) + { + mThreadId = INVALID_THREAD_ID; + ELOG1(EJavaComms, "SocketConnection::start(): pthread_create failed, errno = %d", rc); + } + } + else + { + ELOG1(EJavaComms, "SocketConnection::connect(): failed, rc = %d", rc); + } + + return rc; +} + +void* SocketConnection::messageLoop(void* params) +{ + SocketConnection* me = reinterpret_cast(params); + + me->mListener->onStart(); + LOG2(EJavaComms, EInfo, "Client %d connected to server %d", me->getSocket(), me->mPort); + + int rc = 0; + while (!rc) + { + rc = me->receive(); + } + + me->mListener->onExit(); + LOG2(EJavaComms, EInfo, "Client %d disconnected from server %d", me->getSocket(), me->mPort); + me->mSocket.close(); + return 0; +} + +void SocketConnection::disconnect() +{ + close(); + if (mThreadId != INVALID_THREAD_ID) + { +// mSocket.shutdown(SHUT_WR); // sends EOF + int rc = pthread_join(mThreadId, 0); + if (rc) + { + ELOG2(EJavaComms, + "SocketConnection::disconnect(): pthread_join failed %d - %s", rc, strerror(rc)); + } + } + + mSocket.close(); + mThreadId = INVALID_THREAD_ID; +} + +void SocketConnection::close() +{ + // If a process forks to children processes some things can prevent + // EOF from being seen by a client even though a parent process calls + // close() on a client socket if children processes do not close their + // handle + + // let's use additional 'do exit' message to signal other party that + // connection should be closed so that we don't rely on EOF only + ipcMessage_t msg; + msg.ipcHeader.length = 0; + send(&msg); + + mSocket.shutdown(SHUT_WR); // sends EOF +} + + +// returns: 0 in ok +// < 0 in error +int SocketConnection::receive() +{ + unsigned int len = 0; + int rc = mSocket.read((char*)&len, sizeof(len)); + + if (!rc) + { + if (len < sizeof(ipcHeader_t)) + { + return -1; + } + + char* buf = new char[len]; + rc = mSocket.read(buf, len); + + if (!rc) + { + ipcMessage_t* msg = reinterpret_cast(buf); + msg->ipcHeader.sender = mSocket.getSocket(); + msg->ipcHeader.receiver = mSocket.getSocket(); + // messages are considered to be always trusted + msg->ipcHeader.permissions = -1; + mListener->processMessage(msg); + } + + delete [] buf; + } + + return rc; +} + +// returns: 0 in ok +// < 0 in error +int SocketConnection::send(ipcMessage_t* aMsg) +{ + ScopedLock lock(mSendMutex); + int len = aMsg->ipcHeader.length; + int rc = mSocket.write((char*)&len, sizeof(len)); + + if (!rc) + { + rc = mSocket.write((char*)aMsg, len); + } + return rc; +} + +int SocketConnection::getSocket() const +{ + return mSocket.getSocket(); +} + +} // namespace comms +} // namespace java +