javacommons/gcfprotocols/socket/serverconnection/src/socketserverconnection.cpp
branchRCL_3
changeset 19 04becd199f91
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2007-2007 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:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "socketserverconnection.h"
       
    21 #include "socketserverconnectionfactory.h"
       
    22 #include "pushexception.h"
       
    23 #include "pusherrorcodes.h"
       
    24 
       
    25 #define SOCKET_ERROR   (-1)
       
    26 #define INVALID_SOCKET (-1)
       
    27 #define IO_WOULDBLOCK -2
       
    28 
       
    29 using namespace java::util;
       
    30 
       
    31 SocketServerConnection::SocketServerConnection()
       
    32 {
       
    33     LOG(ESOCKET, EInfo, "+SocketServerConnection - default constructor");
       
    34     mListener = NULL,
       
    35                 mThreadId = 0;
       
    36     mKeepRunning = false;
       
    37     mListenSocket = INVALID_SOCKET;
       
    38     mAcceptSocket = INVALID_SOCKET;
       
    39     mPort = 0;
       
    40     mIsNormalServerConnection = true;
       
    41     mOpenMonitor = 0;
       
    42     mError = 0;
       
    43 }
       
    44 OS_EXPORT SocketServerConnection::SocketServerConnection
       
    45 (const std::wstring& aUri,
       
    46  const std::wstring& aFilter)
       
    47         : mListener(0),
       
    48         mThreadId(0),
       
    49         mKeepRunning(false),
       
    50         mListenSocket(INVALID_SOCKET),
       
    51         mAcceptSocket(INVALID_SOCKET),
       
    52         mUri(aUri),
       
    53         mFilter(aFilter),
       
    54         mPort(0)
       
    55 
       
    56 {
       
    57     JELOG2(ESOCKET);
       
    58     LOG(ESOCKET, EInfo, "+SocketServerConnection::SocketServerConnection");
       
    59     // sanity check for url
       
    60     mIsAppRunning = false;
       
    61     mIsNormalServerConnection = false;
       
    62     mOpenMonitor = 0;
       
    63     mError = 0;
       
    64 
       
    65     // create monitors only when connection comes via push plugin
       
    66     if (0 == mOpenMonitor)
       
    67     {
       
    68         mOpenMonitor = Monitor::createMonitor();
       
    69     }
       
    70     if (aUri.find(L"socket://:") != std::wstring::npos)
       
    71     {
       
    72         if (aUri.length() == 10)
       
    73             mPort = 0;
       
    74         else
       
    75         {
       
    76             std::wstring port = aUri.substr(10); // "socket://:"
       
    77             mPort = JavaCommonUtils::wstringToInt(port);
       
    78         }
       
    79         LOG1(ESOCKET, EInfo, "created SocketServerConnection on port %d", mPort);
       
    80     }
       
    81     else
       
    82     {
       
    83         mPort = -1;
       
    84         LOG(ESOCKET, EInfo, "SocketServerConnection::SocketServerConnection() Invalid url");
       
    85     }
       
    86 }
       
    87 
       
    88 OS_EXPORT SocketServerConnection::~SocketServerConnection()
       
    89 {
       
    90     JELOG2(ESOCKET);
       
    91     if (mOpenMonitor)
       
    92     {
       
    93         delete mOpenMonitor;
       
    94     }
       
    95 }
       
    96 
       
    97 
       
    98 /* ----------------------------------------------------------------------
       
    99 
       
   100 Starting point for socket server. A new thread is created which inturn initializes the server socket and waits
       
   101 for an incoming connection.
       
   102 
       
   103 pthread_create(): This OpenC call is used to create the new thread. listenThread() is passed as the start point
       
   104 of the thread.
       
   105 
       
   106 -------------------------------------------------------------------------*/
       
   107 OS_EXPORT void SocketServerConnection::open(ConnectionListener* aListener)
       
   108 {
       
   109     JELOG2(ESOCKET);
       
   110     mListener = aListener;
       
   111 
       
   112     mKeepRunning = true;
       
   113 
       
   114     int rc = pthread_create(&mThreadId, NULL,  SocketServerConnection::listenThread, this);
       
   115     mOpenMonitor->wait();    // wait for open to return
       
   116 
       
   117     ILOG2(ESOCKET,"after release rc = %dm mPort = %d",rc,mPort);
       
   118     if (rc < 0 || mError < 0)
       
   119     {
       
   120         ELOG1(ESOCKET,"Socket server conn already exists on Port %d : Open Failed",mPort);
       
   121         std::string errTxt("ERROR!!! Opening of SocketServer failed");
       
   122         throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR,errTxt,__FILE__,  __FUNCTION__,__LINE__);
       
   123     }
       
   124 }
       
   125 
       
   126 
       
   127 // Since server socket is non-blocking, a accept() is called in a new thread
       
   128 
       
   129 void* SocketServerConnection::listenThread(void* aParams)
       
   130 {
       
   131     JELOG2(ESOCKET);
       
   132 
       
   133     SocketServerConnection* pThis = reinterpret_cast<SocketServerConnection*>(aParams);
       
   134 
       
   135     pThis->mListenSocket  = pThis->open(pThis->mPort);
       
   136     ILOG1(ESOCKET,  "+SocketServerConnection::listenThread - pThis->mListenSocket = %d",pThis->mListenSocket);
       
   137 
       
   138     if (pThis->mListenSocket < 0)
       
   139     {
       
   140         pThis->mError = -errno;
       
   141         (pThis->mOpenMonitor)->notify();
       
   142         pthread_exit(0);
       
   143     }
       
   144     (pThis->mOpenMonitor)->notify();
       
   145 
       
   146 
       
   147     int fd = INVALID_SOCKET;
       
   148 
       
   149     if (fd < 0 && pThis->mKeepRunning)
       
   150     {
       
   151         fd = pThis->accept();
       
   152     }
       
   153 
       
   154     if (!(fd<0))  // we have incoming connection
       
   155     {
       
   156         pThis->mAcceptSocket = fd;
       
   157         if (pThis->mIsAppRunning == true)
       
   158         {
       
   159             pThis->setActivityFlag(false);
       
   160             pthread_exit(0);
       
   161         }
       
   162         else
       
   163         {
       
   164             if (pThis->mListener)
       
   165             {
       
   166                 pThis->mListener->msgArrived();
       
   167             }
       
   168             pThis->setActivityFlag(true);
       
   169         }
       
   170     }
       
   171 
       
   172     pthread_exit(0);
       
   173     return 0;
       
   174 }
       
   175 
       
   176 
       
   177 /* ----------------------------------------------------------------------
       
   178 This function is used to open a server socket connection.
       
   179 
       
   180 @param:  aPort - Port on which the server will bind and start lisetening.
       
   181 
       
   182 OpenC apis used
       
   183 
       
   184 htons(), htonl() : to convert values between host and network byte order
       
   185 
       
   186 socket():  creates an endpoint for communication and returns a descriptor. We create a "STREAM" socket
       
   187 
       
   188 bind(): We bind to address INADDR_ANY, which indicates listen happens on all networking interfaces present
       
   189 
       
   190 listen(): listens for incoming connection.
       
   191 
       
   192 accept(): accepts a connection on a socket.
       
   193 
       
   194 -------------------------------------------------------------------------*/
       
   195 OS_EXPORT int SocketServerConnection::open()
       
   196 {
       
   197     JELOG2(ESOCKET);
       
   198 
       
   199     mIsAppRunning = true;
       
   200 
       
   201     if (mKeepRunning) // we are listening for push connection
       
   202     {
       
   203         mKeepRunning = false;
       
   204         pthread_join(mThreadId, NULL);
       
   205     }
       
   206     else
       
   207     {
       
   208         mListenSocket = open(mPort);
       
   209     }
       
   210     setActivityFlag(false);
       
   211     return mListenSocket;
       
   212 }
       
   213 
       
   214 int SocketServerConnection::open(int aPort)
       
   215 {
       
   216     JELOG2(ESOCKET);
       
   217     int fd  = socket(AF_INET, SOCK_STREAM, 0);
       
   218     if (fd == INVALID_SOCKET)
       
   219     {
       
   220         int err = -errno;
       
   221         return err;
       
   222     }
       
   223 
       
   224     struct sockaddr_in addr;
       
   225     addr.sin_family      = AF_INET;
       
   226     addr.sin_port        = htons((unsigned short)aPort);
       
   227     addr.sin_addr.s_addr = htonl(INADDR_ANY);
       
   228 
       
   229     int res = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
       
   230     if (res != SOCKET_ERROR)
       
   231     {
       
   232         res = listen(fd, SOMAXCONN);
       
   233         if (res != SOCKET_ERROR)
       
   234         {
       
   235             // setNonBlocking(fd);
       
   236             return fd;
       
   237         }
       
   238     }
       
   239     int err = -errno;
       
   240     LOG(ESOCKET,EInfo,"closing ..");
       
   241     close(fd);
       
   242     return err;
       
   243 }
       
   244 
       
   245 OS_EXPORT int SocketServerConnection::accept()
       
   246 {
       
   247     JELOG2(ESOCKET);
       
   248     int sock_fd = INVALID_SOCKET;
       
   249 
       
   250     if (mAcceptSocket != INVALID_SOCKET) // incoming push connection
       
   251     {
       
   252         sock_fd = mAcceptSocket;
       
   253         mAcceptSocket = INVALID_SOCKET;
       
   254     }
       
   255     else
       
   256     {
       
   257         sock_fd = accept(mListenSocket);
       
   258     }
       
   259 
       
   260     return sock_fd;
       
   261 }
       
   262 
       
   263 int SocketServerConnection::accept(int fd)
       
   264 {
       
   265     // paramter fd, is the socket descriptor returned during server socket creation.
       
   266     struct sockaddr_in sa;
       
   267     socklen_t saLen = sizeof(sa);
       
   268     int res = 0;
       
   269 
       
   270 
       
   271     LOG(ESOCKET, EInfo, "before accept");
       
   272     res = ::accept(fd, (struct sockaddr *)&sa, &saLen);
       
   273     LOG1(ESOCKET, EInfo, "accept returned %d",res);
       
   274     if ((res == -1) && (errno == EWOULDBLOCK))
       
   275     {
       
   276         res = IO_WOULDBLOCK;
       
   277     }
       
   278     if (res == -1)
       
   279     {
       
   280         int err = -errno;
       
   281         return err;
       
   282     }
       
   283     return res;
       
   284 }
       
   285 OS_EXPORT bool SocketServerConnection::isNormalServerConnection()
       
   286 {
       
   287     return mIsNormalServerConnection;
       
   288 }
       
   289 
       
   290 OS_EXPORT void SocketServerConnection::setNormalServerConnection()
       
   291 {
       
   292     LOG(ESOCKET,EInfo,"Push is enabled");
       
   293     mIsNormalServerConnection = true;
       
   294 }
       
   295 
       
   296 OS_EXPORT void SocketServerConnection::close()
       
   297 {
       
   298     JELOG2(ESOCKET);
       
   299 
       
   300     if (mListenSocket != INVALID_SOCKET)
       
   301     {
       
   302         int ret = shutdown(mListenSocket,SHUT_RDWR);
       
   303         close(mListenSocket);
       
   304         LOG1(ESOCKET, EInfo, "shutdown of mListenSocket returned %d",ret);
       
   305     }
       
   306 
       
   307     if (mAcceptSocket != INVALID_SOCKET)
       
   308     {
       
   309         int ret = shutdown(mAcceptSocket,SHUT_RDWR);
       
   310         close(mAcceptSocket);
       
   311         LOG1(ESOCKET, EInfo, "shutdown of mAcceptSocket returned %d",ret);
       
   312     }
       
   313 
       
   314     if (mKeepRunning) // we are listening for push connection
       
   315     {
       
   316         mKeepRunning = false;
       
   317         pthread_join(mThreadId, NULL);
       
   318     }
       
   319     // reset members
       
   320     mListenSocket = INVALID_SOCKET;
       
   321     mAcceptSocket = INVALID_SOCKET;
       
   322 
       
   323     mListener = 0;
       
   324     mThreadId = 0;
       
   325     //mKeepRunning = false;
       
   326 
       
   327 }
       
   328 
       
   329 OS_EXPORT std::wstring SocketServerConnection::getUri() const
       
   330 {
       
   331     return mUri;
       
   332 }
       
   333 
       
   334 OS_EXPORT std::wstring SocketServerConnection::getFilter() const
       
   335 {
       
   336     return mFilter;
       
   337 }
       
   338 
       
   339 OS_EXPORT void SocketServerConnection::setFilter(const std::wstring& aFilter)
       
   340 {
       
   341     JELOG2(ESOCKET);
       
   342     mFilter = aFilter;
       
   343     return;
       
   344 }
       
   345 
       
   346 OS_EXPORT int SocketServerConnection::close(int fd)
       
   347 {
       
   348     LOG(ESOCKET, EInfo, "+SocketServerConnection::close(int fd)");
       
   349     if (mListenSocket != INVALID_SOCKET)
       
   350     {
       
   351         int ret = shutdown(mListenSocket,SHUT_RDWR);
       
   352         LOG1(ESOCKET, EInfo, "shutdown of mListenSocket returned %d",ret);
       
   353     }
       
   354 
       
   355     if (mAcceptSocket != INVALID_SOCKET)
       
   356     {
       
   357         int ret = shutdown(mAcceptSocket,SHUT_RDWR);
       
   358         LOG1(ESOCKET, EInfo, "shutdown of mAcceptSocket returned %d",ret);
       
   359     }
       
   360 
       
   361     int ret = ::close(fd);
       
   362     // reset members
       
   363     mListenSocket = INVALID_SOCKET;
       
   364     mAcceptSocket = INVALID_SOCKET;
       
   365 
       
   366     LOG(ESOCKET, EInfo, "-SocketServerConnection::close(int fd)");
       
   367     return ret;
       
   368 }
       
   369 
       
   370 void SocketServerConnection::setNonBlocking(int fd)
       
   371 {
       
   372     // first get the flags associated with this descriptor.
       
   373     int flags = fcntl(fd, F_GETFL, 0);
       
   374     if (flags < 0)
       
   375     {
       
   376         return; // check errno
       
   377     }
       
   378 
       
   379     // set the non-blocking flag to make the accept() call as non-blocking.
       
   380     flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
       
   381 
       
   382     if (flags < 0)
       
   383     {
       
   384         return; // throw exception
       
   385     }
       
   386 
       
   387 }
       
   388 
       
   389 void SocketServerConnection::setActivityFlag(bool aFlag)
       
   390 {
       
   391     SocketServerConnectionFactory& scf =
       
   392         SocketServerConnectionFactory::getFactory();
       
   393     scf.setPendingMsgFlag(mUri, aFlag);
       
   394 }
       
   395