javacommons/comms/ipclib/socket/src/serversocketconnection.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 #include <signal.h>
       
    20 #include <errno.h>
       
    21 #include <string.h>
       
    22 
       
    23 #include "logger.h"
       
    24 
       
    25 #include "serversocketconnection.h"
       
    26 #include "socketconnection.h"
       
    27 
       
    28 const unsigned int INVALID_THREAD_ID = 0;
       
    29 
       
    30 namespace java
       
    31 {
       
    32 namespace comms
       
    33 {
       
    34 using java::util::ScopedLock;
       
    35 
       
    36 ServerSocketConnection::ServerSocketConnection(IpcListener* aListener)
       
    37         : mThreadId(INVALID_THREAD_ID), mListener(aListener), mKeepRunning(0), mPort(0)
       
    38 {
       
    39     /*
       
    40      * The SIGPIPE signal will be received if the peer has gone away
       
    41      * and an attempt is made to write data to the peer. Ignoring this
       
    42      * signal causes the write operation to receive an EPIPE error.
       
    43      * Thus, the user is informed about what happened.
       
    44     */
       
    45 #ifndef __SYMBIAN32__
       
    46     signal(SIGPIPE, SIG_IGN);
       
    47 #endif
       
    48 }
       
    49 
       
    50 ServerSocketConnection::~ServerSocketConnection()
       
    51 {
       
    52 }
       
    53 
       
    54 int ServerSocketConnection::start(int aPort)
       
    55 {
       
    56     if (mThreadId != INVALID_THREAD_ID) return 0;
       
    57     mPort = aPort;
       
    58     int rc = mListenSocket.open(aPort);
       
    59 
       
    60     if (!rc)
       
    61     {
       
    62         mKeepRunning = 1;
       
    63         rc = pthread_create(&mThreadId, 0, ServerSocketConnection::messageLoop, this);
       
    64         if (rc!=0)
       
    65         {
       
    66             mThreadId = INVALID_THREAD_ID;
       
    67             ELOG1(EJavaComms, "ServerSocketConnection::start(): pthread_create failed, errno = %d", rc);
       
    68         }
       
    69     }
       
    70 
       
    71     return rc;
       
    72 }
       
    73 
       
    74 void* ServerSocketConnection::messageLoop(void* params)
       
    75 {
       
    76     ServerSocketConnection* me = reinterpret_cast<ServerSocketConnection*>(params);
       
    77     me->mListener->onStart();
       
    78     LOG1(EJavaComms, EInfo, "Server started on %d", me->mPort);
       
    79     me->select();
       
    80     me->removeConnections();
       
    81     LOG1(EJavaComms, EInfo, "Server stopped on %d", me->mPort);
       
    82     me->mListener->onExit();
       
    83     return 0;
       
    84 }
       
    85 
       
    86 
       
    87 void ServerSocketConnection::stop()
       
    88 {
       
    89     mKeepRunning = 0;
       
    90 
       
    91     if (mThreadId != INVALID_THREAD_ID)
       
    92     {
       
    93         // kick select out from wait
       
    94         Socket s;
       
    95         s.open(mPort);
       
    96         s.close();
       
    97 
       
    98         int rc = pthread_join(mThreadId, 0);
       
    99         if (rc)
       
   100         {
       
   101             ELOG1(EJavaComms, "ServerSocketConnection::stop(): pthread_join failed, errno = %d", rc);
       
   102         }
       
   103     }
       
   104 
       
   105     mListenSocket.close();
       
   106     removeConnections();
       
   107     mThreadId = INVALID_THREAD_ID;
       
   108     mPort = 0;
       
   109 }
       
   110 
       
   111 int ServerSocketConnection::select()
       
   112 {
       
   113     while (mKeepRunning)
       
   114     {
       
   115         fd_set socks;
       
   116         int maxfd = 0;
       
   117 
       
   118         createSelectSet(socks, maxfd);
       
   119 
       
   120         timeval tv;
       
   121         tv.tv_sec  = 600;
       
   122         tv.tv_usec = 0;
       
   123 
       
   124         int rc = ::select(maxfd + 1, &socks, 0, 0, &tv);
       
   125 
       
   126         if (rc == 0)
       
   127         {
       
   128 //            LOG(EJavaComms, EInfo, "select() timed out!");
       
   129             continue;
       
   130         }
       
   131         else if (rc < 0 && errno != EINTR)
       
   132         {
       
   133             ELOG1(EJavaComms, "Error in select(): %s", strerror(errno));
       
   134             break;
       
   135         }
       
   136         else if (rc > 0)
       
   137         {
       
   138             rc = handleNewConnection(socks);
       
   139             if (rc<0) break; // bail out if accept fails
       
   140             handleRead(socks);
       
   141         }
       
   142     }
       
   143     return 0;
       
   144 }
       
   145 
       
   146 int ServerSocketConnection::handleNewConnection(fd_set& aSet)
       
   147 {
       
   148     int peersock = 0;
       
   149     if (FD_ISSET(mListenSocket.getSocket(), &aSet))
       
   150     {
       
   151         peersock = mListenSocket.accept();
       
   152         if (peersock < 0)
       
   153         {
       
   154             ELOG1(EJavaComms, "Error in accept(): %s", strerror(errno));
       
   155         }
       
   156         else
       
   157         {
       
   158             ScopedLock lock(mSocketsMutex);
       
   159             SocketConnection* con = new SocketConnection(mListener, peersock);
       
   160             mSockets.push_back(con);
       
   161             LOG3(EJavaComms, EInfo, "Server %d - client %d connected - clients %d",
       
   162                  mPort, con->getSocket(), mSockets.size());
       
   163         }
       
   164     }
       
   165     return peersock;
       
   166 }
       
   167 
       
   168 
       
   169 void ServerSocketConnection::handleRead(fd_set& aSet)
       
   170 {
       
   171     ScopedLock lock(mSocketsMutex);
       
   172 
       
   173     for (connections_t::iterator it = mSockets.begin(); it != mSockets.end();)
       
   174     {
       
   175         if (FD_ISSET((*it)->getSocket(), &aSet))
       
   176         {
       
   177             int rc = (*it)->receive();
       
   178 
       
   179             if (!rc)
       
   180             {
       
   181                 ++it;
       
   182             }
       
   183             else
       
   184             {
       
   185                 LOG3(EJavaComms, EInfo, "Server %d - client %d disconnected - clients %d",
       
   186                      mPort, (*it)->getSocket(), mSockets.size()-1);
       
   187                 (*it)->disconnect();
       
   188                 delete(*it);
       
   189                 it = mSockets.erase(it);
       
   190             }
       
   191         }
       
   192         else
       
   193         {
       
   194             ++it;
       
   195         }
       
   196     }
       
   197 }
       
   198 
       
   199 void ServerSocketConnection::createSelectSet(fd_set& aSet, int& aMaxFd)
       
   200 {
       
   201     ScopedLock lock(mSocketsMutex);
       
   202 
       
   203     FD_ZERO(&aSet);
       
   204     aMaxFd = mListenSocket.getSocket();
       
   205 
       
   206     // add listen socket
       
   207     FD_SET(mListenSocket.getSocket() ,&aSet);
       
   208 
       
   209     // add read sockets
       
   210     for (connections_t::iterator it = mSockets.begin(); it != mSockets.end(); ++it)
       
   211     {
       
   212         int sock_fd = (*it)->getSocket();
       
   213         FD_SET(sock_fd, &aSet);
       
   214 
       
   215         aMaxFd = (aMaxFd < sock_fd)?sock_fd:aMaxFd;
       
   216     }
       
   217 }
       
   218 
       
   219 int ServerSocketConnection::send(ipcMessage_t* aMsg)
       
   220 {
       
   221     ScopedLock lock(mSocketsMutex);
       
   222 
       
   223     int rc = EINVAL;
       
   224     for (connections_t::iterator it = mSockets.begin(); it != mSockets.end(); ++it)
       
   225     {
       
   226         if (aMsg->ipcHeader.receiver == (*it)->getSocket())
       
   227         {
       
   228             rc = (*it)->send(aMsg);
       
   229             break;
       
   230         }
       
   231     }
       
   232     return rc;
       
   233 }
       
   234 
       
   235 void ServerSocketConnection::removeConnections()
       
   236 {
       
   237     ScopedLock lock(mSocketsMutex);
       
   238 
       
   239     for (connections_t::iterator it = mSockets.begin(); it != mSockets.end();)
       
   240     {
       
   241         (*it)->disconnect();
       
   242         LOG3(EJavaComms, EInfo, "Server %d stopping - client %d disconnected - clients %d",
       
   243              mPort, (*it)->getSocket(), mSockets.size()-1);
       
   244         delete(*it);
       
   245         it = mSockets.erase(it);
       
   246     }
       
   247 }
       
   248 
       
   249 } // namespace comms
       
   250 } // namespace java
       
   251