javaextensions/datagram/serverconnection/src/datagramserverconnection.cpp
changeset 21 2a9601315dfc
child 87 1627c337e51e
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     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:
       
    15  *
       
    16 */
       
    17 
       
    18 #include <sys/socket.h>
       
    19 #include <sys/select.h>
       
    20 #include <unistd.h>
       
    21 #include <errno.h>
       
    22 #include <arpa/inet.h>
       
    23 #include <netinet/in.h>
       
    24 #include <fcntl.h>
       
    25 #include <sys/stat.h>
       
    26 #include <sys/types.h>
       
    27 #include <sys/socket.h>
       
    28 #include <netinet/in.h>
       
    29 #include <wchar.h>
       
    30 #include <string.h>
       
    31 
       
    32 #include "logger.h"
       
    33 #include "connectionlistener.h"
       
    34 #include "javacommonutils.h"
       
    35 
       
    36 #include "datagramserverconnection.h"
       
    37 #include "datagramserverconnectionfactory.h"
       
    38 #include "pushexception.h"
       
    39 #include "pusherrorcodes.h"
       
    40 
       
    41 #define INVALID_SOCKET (-1)
       
    42 #define MAX_SIZE 256
       
    43 #define BUFFER_SIZE 512
       
    44 
       
    45 using namespace java::util;
       
    46 
       
    47 DatagramServerConnection::DatagramServerConnection()
       
    48 {
       
    49     LOG(ESOCKET, EInfo, "+DatagramServerConnection - default constructor");
       
    50     mListener = NULL,
       
    51                 mThreadId = 0;
       
    52     mKeepRunning = false;
       
    53     mListenDatagram = INVALID_SOCKET;
       
    54     mAcceptDatagram = INVALID_SOCKET;
       
    55     mPort = 0;
       
    56     mIsNormalServerConnection = true;
       
    57     mError = 0;
       
    58     mOpenMonitor = 0;
       
    59 }
       
    60 
       
    61 OS_EXPORT DatagramServerConnection::DatagramServerConnection(
       
    62     const std::wstring& aUri, const std::wstring& aFilter) :
       
    63         mListener(0), mThreadId(0), mKeepRunning(false), mListenDatagram(
       
    64             INVALID_SOCKET), mAcceptDatagram(INVALID_SOCKET), mUri(aUri),
       
    65         mFilter(aFilter), mPort(0)
       
    66 {
       
    67     JELOG2(ESOCKET);
       
    68 
       
    69     // sanity check for url
       
    70     ILOG1(ESOCKET,
       
    71           "++DatagramServerConnection::DatagramServerConnection() aUri = %s",
       
    72           aUri.c_str());
       
    73     mIsNormalServerConnection = false;
       
    74     mIsAppRunning = false;
       
    75     mError = 0;
       
    76     mOpenMonitor = 0;
       
    77 
       
    78     if (0 == mOpenMonitor)
       
    79     {
       
    80         mOpenMonitor = Monitor::createMonitor();
       
    81     }
       
    82 
       
    83     if (aUri.length() == 12)
       
    84         mPort = 0;
       
    85     else
       
    86     {
       
    87         std::wstring port = aUri.substr(12); // "datagram://:"
       
    88         mPort = JavaCommonUtils::wstringToInt(port);
       
    89     }
       
    90     LOG1(ESOCKET, EInfo, "created DatagramServerConnection on port %d", mPort);
       
    91 }
       
    92 
       
    93 OS_EXPORT DatagramServerConnection::~DatagramServerConnection()
       
    94 {
       
    95     if (mOpenMonitor)
       
    96     {
       
    97         delete mOpenMonitor;
       
    98     }
       
    99     JELOG2(ESOCKET);
       
   100 }
       
   101 
       
   102 OS_EXPORT void DatagramServerConnection::open(ConnectionListener* aListener)
       
   103 {
       
   104     JELOG2(ESOCKET);
       
   105     mListener = aListener;
       
   106 
       
   107     mKeepRunning = true;
       
   108     int rc = pthread_create(&mThreadId, NULL,
       
   109                             DatagramServerConnection::listenThread, this);
       
   110     mOpenMonitor->wait();
       
   111 
       
   112     ILOG2(ESOCKET,"after release in datagram rc = %dm mPort = %d",rc,mPort);
       
   113     if (rc < 0 || mError < 0)
       
   114     {
       
   115         ELOG1(ESOCKET,"ERROR!!! Datagram server conn already exists on Port %d : Open Failed",mPort);
       
   116         std::string errTxt("ERROR!!! Opening of Datagram Server failed ");
       
   117         throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR,errTxt,__FILE__,  __FUNCTION__,__LINE__);
       
   118     }
       
   119 }
       
   120 
       
   121 void* DatagramServerConnection::listenThread(void* aParams)
       
   122 {
       
   123     JELOG2(ESOCKET);
       
   124     struct sockaddr_in sender_addr;
       
   125     sender_addr.sin_family = AF_INET;
       
   126     unsigned int size = sizeof(sender_addr);
       
   127     bool match = false;
       
   128 
       
   129     DatagramServerConnection* pThis =
       
   130         reinterpret_cast<DatagramServerConnection*>(aParams);
       
   131 
       
   132     pThis->mListenDatagram = pThis->open(pThis->mPort);
       
   133 
       
   134     if (pThis->mListenDatagram < 0)
       
   135     {
       
   136         pThis->mError = -errno;
       
   137         (pThis->mOpenMonitor)->notify();
       
   138         pthread_exit(0);
       
   139     }
       
   140     (pThis->mOpenMonitor)->notify();
       
   141 
       
   142 
       
   143     int rt = -1;
       
   144     char * addr = new char[MAX_SIZE];
       
   145 
       
   146     if (rt < 0 && pThis->mKeepRunning)
       
   147     {
       
   148         char *buf = new char[BUFFER_SIZE];
       
   149         // wchar_t * sender = new wchar_t[256];
       
   150         char *  sender = new  char[256];
       
   151         while (match == false)
       
   152         {
       
   153             rt = recvfrom(pThis->mListenDatagram, buf, BUFFER_SIZE, 0,
       
   154                           (sockaddr*) &sender_addr, &size);
       
   155 
       
   156             strcpy(sender,inet_ntoa(sender_addr.sin_addr));
       
   157             ILOG2(ESOCKET, "pThis->mListenDatagram =  %d, port = %d",pThis-> mListenDatagram,pThis->mPort);
       
   158 
       
   159             // validate the filter
       
   160             /*if(strcmp((const char *)pThis->mFilter.c_str(),(const char *) NULL)== 0)
       
   161             {
       
   162                   LOG(ESOCKET,EInfo,"filter is NULL");
       
   163                     match = true;
       
   164             }
       
   165             else
       
   166             {
       
   167                 if( strcmp((const char *)"*",(const char *)pThis->mFilter.c_str()) == 0)
       
   168                 {
       
   169                     LOG(ESOCKET,EInfo,"filter = '*'");
       
   170                     match = true;
       
   171                 }
       
   172                 if( strcmp((const char *)"?",(const char *)pThis->mFilter.c_str()) == 0)
       
   173                 {
       
   174                     LOG(ESOCKET,EInfo,"filter = '?'");
       
   175                     match = true;
       
   176                 }
       
   177             }*/
       
   178 
       
   179 
       
   180             match = true;
       
   181         }
       
   182     }
       
   183 
       
   184     if (!(rt < 0)) // we have incoming connection
       
   185     {
       
   186         pThis->mAcceptDatagram = pThis->mListenDatagram;
       
   187         if (pThis->mIsAppRunning == true)
       
   188         {
       
   189             pThis->setActivityFlag(false);
       
   190             pthread_exit(0);
       
   191         }
       
   192         else
       
   193         {
       
   194             if (pThis->mListener)
       
   195             {
       
   196                 pThis->mListener->msgArrived();
       
   197             }
       
   198             pThis->setActivityFlag(true);
       
   199         }
       
   200     }
       
   201     return 0;
       
   202 }
       
   203 
       
   204 OS_EXPORT int DatagramServerConnection::open()
       
   205 {
       
   206     JELOG2(ESOCKET);
       
   207 
       
   208     mIsAppRunning = true;
       
   209 
       
   210     if (mKeepRunning) // we are listening for push connection
       
   211     {
       
   212         mKeepRunning = false;
       
   213         pthread_join(mThreadId, NULL);
       
   214     }
       
   215     else
       
   216     {
       
   217         mListenDatagram = open(mPort);
       
   218     }
       
   219     LOG2(ESOCKET,EInfo, "mListenDatagram =  %d, mPort = %d", mListenDatagram, mPort);
       
   220     setActivityFlag(false);
       
   221     return mListenDatagram;
       
   222 }
       
   223 
       
   224 int DatagramServerConnection::open(int aPort)
       
   225 {
       
   226     JELOG2(ESOCKET);
       
   227 
       
   228     struct sockaddr_in addr;
       
   229     addr.sin_family = AF_INET;
       
   230     addr.sin_port = htons((unsigned short) aPort);
       
   231     addr.sin_addr.s_addr = htonl(INADDR_ANY);
       
   232 
       
   233     int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
       
   234     if (fd == INVALID_SOCKET)
       
   235     {
       
   236         return -1;
       
   237     }
       
   238 
       
   239     addr.sin_addr.s_addr = htonl(INADDR_ANY);
       
   240 
       
   241     int res = bind(fd, (struct sockaddr*) &addr, sizeof(addr));
       
   242 
       
   243     // when server is opened on dynamic port, append the port to the url
       
   244     /*if(mPort == 0)
       
   245     {
       
   246             mPort = addr.sin_port;
       
   247             LOG1(ESOCKET, EInfo, "dynamic port : %d", mPort);
       
   248             std::wstring portString = JavaCommonUtils::intToWstring(mPort);
       
   249             mUri.append(portString);
       
   250             LOG1(ESOCKET, EInfo, "after appending mUri with dynamic port : %s", mUri);
       
   251     }*/
       
   252     LOG3(ESOCKET,EInfo, "server datgram sd =  %dm bind returns %d, mPort = %d ", fd, res, mPort);
       
   253     if (res != -1)
       
   254     {
       
   255         return fd;
       
   256     }
       
   257     LOG1(ESOCKET,EInfo, "-errno : %d" , -errno);
       
   258     close(fd);
       
   259     return -1;
       
   260 }
       
   261 
       
   262 
       
   263 OS_EXPORT void DatagramServerConnection::close()
       
   264 {
       
   265     JELOG2(ESOCKET);
       
   266 
       
   267 
       
   268 
       
   269     ::close(mListenDatagram);
       
   270     ::close(mAcceptDatagram);
       
   271 
       
   272     if (mKeepRunning) // we are listening for push connection
       
   273     {
       
   274         mKeepRunning = false;
       
   275         pthread_join(mThreadId, NULL);
       
   276     }
       
   277 
       
   278     // reset members
       
   279     mListenDatagram = INVALID_SOCKET;
       
   280     mAcceptDatagram = INVALID_SOCKET;
       
   281 
       
   282     mListener = 0;
       
   283     mThreadId = 0;
       
   284     //mKeepRunning = false;
       
   285 }
       
   286 
       
   287 OS_EXPORT std::wstring DatagramServerConnection::getUri() const
       
   288 {
       
   289     LOG(ESOCKET,EInfo, "DatagramServerConnection::getUri() ");
       
   290     return mUri;
       
   291 }
       
   292 
       
   293 OS_EXPORT std::wstring DatagramServerConnection::getFilter() const
       
   294 {
       
   295     return mFilter;
       
   296 }
       
   297 
       
   298 OS_EXPORT void DatagramServerConnection::setFilter(const std::wstring& aFilter)
       
   299 {
       
   300     JELOG2(ESOCKET);
       
   301     mFilter = aFilter;
       
   302 }
       
   303 OS_EXPORT bool DatagramServerConnection::isNormalServerConnection()
       
   304 {
       
   305     return mIsNormalServerConnection;
       
   306 }
       
   307 
       
   308 OS_EXPORT void DatagramServerConnection::setNormalServerConnection()
       
   309 {
       
   310     LOG(ESOCKET,EInfo,"Push is enabled");
       
   311     mIsNormalServerConnection = true;
       
   312 }
       
   313 int DatagramServerConnection::close(int fd)
       
   314 {
       
   315     return ::close(fd);
       
   316 }
       
   317 
       
   318 
       
   319 /**
       
   320  * SetActivityFlag method  updates status whether
       
   321  * ServerConnection object has pending message(= message arrived but not yet read).
       
   322  * @param aFlag Updating logic of pending message flag:
       
   323  *                    - Set it 'true' when message arrives to the connection.
       
   324  *                    - Set it 'false' when ServerConnection::open() operation has been called.
       
   325  */
       
   326 void DatagramServerConnection::setActivityFlag(bool aFlag)
       
   327 {
       
   328     DatagramServerConnectionFactory& scf =
       
   329         DatagramServerConnectionFactory::getFactory();
       
   330     scf.setPendingMsgFlag(mUri, aFlag);
       
   331 }