javacommons/comms/ipclib/socket/src/socketconnection.cpp
branchRCL_3
changeset 14 04becd199f91
equal deleted inserted replaced
13:f5050f1da672 14:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 #include <sys/socket.h>
       
    19 
       
    20 #include <string.h>
       
    21 #include <signal.h>
       
    22 
       
    23 #include "logger.h"
       
    24 
       
    25 #include "socketconnection.h"
       
    26 
       
    27 const unsigned int INVALID_THREAD_ID = 0;
       
    28 
       
    29 namespace java
       
    30 {
       
    31 namespace comms
       
    32 {
       
    33 using java::util::ScopedLock;
       
    34 
       
    35 SocketConnection::SocketConnection(IpcListener* aListener)
       
    36         : mThreadId(INVALID_THREAD_ID), mListener(aListener), mPort(0)
       
    37 {
       
    38     init();
       
    39 }
       
    40 
       
    41 SocketConnection::SocketConnection(IpcListener* aListener, int aSocketFd)
       
    42         : mThreadId(INVALID_THREAD_ID), mSocket(aSocketFd), mListener(aListener), mPort(0)
       
    43 {
       
    44     init();
       
    45 }
       
    46 
       
    47 void SocketConnection::init()
       
    48 {
       
    49 //    JELOG2(EJavaComms);
       
    50     /*
       
    51      * The SIGPIPE signal will be received if the peer has gone away
       
    52      * and an attempt is made to write data to the peer. Ignoring this
       
    53      * signal causes the write operation to receive an EPIPE error.
       
    54      * Thus, the user is informed about what happened.
       
    55     */
       
    56 #ifndef __SYMBIAN32__
       
    57     signal(SIGPIPE, SIG_IGN);
       
    58 #endif
       
    59 }
       
    60 
       
    61 SocketConnection::~SocketConnection()
       
    62 {
       
    63 }
       
    64 
       
    65 int SocketConnection::connect(int aPort)
       
    66 {
       
    67 //    JELOG2(EJavaComms);
       
    68 
       
    69     if (mThreadId != INVALID_THREAD_ID) return 0;
       
    70     mPort = aPort;
       
    71     int rc = mSocket.open(aPort);
       
    72 
       
    73     if (!rc)
       
    74     {
       
    75         rc = pthread_create(&mThreadId, 0, SocketConnection::messageLoop, this);
       
    76         if (rc!=0)
       
    77         {
       
    78             mThreadId = INVALID_THREAD_ID;
       
    79             ELOG1(EJavaComms, "SocketConnection::start(): pthread_create failed, errno = %d", rc);
       
    80         }
       
    81     }
       
    82     else
       
    83     {
       
    84         ELOG1(EJavaComms, "SocketConnection::connect(): failed, rc = %d", rc);
       
    85     }
       
    86 
       
    87     return rc;
       
    88 }
       
    89 
       
    90 void* SocketConnection::messageLoop(void* params)
       
    91 {
       
    92     SocketConnection* me = reinterpret_cast<SocketConnection*>(params);
       
    93 
       
    94     me->mListener->onStart();
       
    95     LOG2(EJavaComms, EInfo, "Client %d connected to server %d", me->getSocket(), me->mPort);
       
    96 
       
    97     int rc = 0;
       
    98     while (!rc)
       
    99     {
       
   100         rc = me->receive();
       
   101     }
       
   102 
       
   103     me->mListener->onExit();
       
   104     LOG2(EJavaComms, EInfo, "Client %d disconnected from server %d", me->getSocket(), me->mPort);
       
   105     me->mSocket.close();
       
   106     return 0;
       
   107 }
       
   108 
       
   109 void SocketConnection::disconnect()
       
   110 {
       
   111     close();
       
   112     if (mThreadId != INVALID_THREAD_ID)
       
   113     {
       
   114 //        mSocket.shutdown(SHUT_WR); // sends EOF
       
   115         int rc = pthread_join(mThreadId, 0);
       
   116         if (rc)
       
   117         {
       
   118             ELOG2(EJavaComms,
       
   119                   "SocketConnection::disconnect(): pthread_join failed %d - %s", rc, strerror(rc));
       
   120         }
       
   121     }
       
   122 
       
   123     mSocket.close();
       
   124     mThreadId = INVALID_THREAD_ID;
       
   125 }
       
   126 
       
   127 void SocketConnection::close()
       
   128 {
       
   129     // If a process forks to children processes some things can prevent
       
   130     // EOF from being seen by a client even though a parent process calls
       
   131     // close() on a client socket if children processes do not close their
       
   132     // handle
       
   133 
       
   134     // let's use additional 'do exit' message to signal other party that
       
   135     // connection should be closed so that we don't rely on EOF only
       
   136     ipcMessage_t msg;
       
   137     msg.ipcHeader.length = 0;
       
   138     send(&msg);
       
   139 
       
   140     mSocket.shutdown(SHUT_WR); // sends EOF
       
   141 }
       
   142 
       
   143 
       
   144 // returns: 0   in ok
       
   145 //          < 0 in error
       
   146 int SocketConnection::receive()
       
   147 {
       
   148     unsigned int len = 0;
       
   149     int rc = mSocket.read((char*)&len, sizeof(len));
       
   150 
       
   151     if (!rc)
       
   152     {
       
   153         if (len < sizeof(ipcHeader_t))
       
   154         {
       
   155             return -1;
       
   156         }
       
   157 
       
   158         char* buf = new char[len];
       
   159         rc = mSocket.read(buf, len);
       
   160 
       
   161         if (!rc)
       
   162         {
       
   163             ipcMessage_t* msg = reinterpret_cast<ipcMessage_t*>(buf);
       
   164             msg->ipcHeader.sender = mSocket.getSocket();
       
   165             msg->ipcHeader.receiver = mSocket.getSocket();
       
   166             // messages are considered to be always trusted
       
   167             msg->ipcHeader.permissions = -1;
       
   168             mListener->processMessage(msg);
       
   169         }
       
   170 
       
   171         delete [] buf;
       
   172     }
       
   173 
       
   174     return rc;
       
   175 }
       
   176 
       
   177 // returns: 0   in ok
       
   178 //          < 0 in error
       
   179 int SocketConnection::send(ipcMessage_t* aMsg)
       
   180 {
       
   181     ScopedLock lock(mSendMutex);
       
   182     int len = aMsg->ipcHeader.length;
       
   183     int rc = mSocket.write((char*)&len, sizeof(len));
       
   184 
       
   185     if (!rc)
       
   186     {
       
   187         rc = mSocket.write((char*)aMsg, len);
       
   188     }
       
   189     return rc;
       
   190 }
       
   191 
       
   192 int SocketConnection::getSocket() const
       
   193 {
       
   194     return mSocket.getSocket();
       
   195 }
       
   196 
       
   197 } // namespace comms
       
   198 } // namespace java
       
   199