javaextensions/datagram/serverconnection/src/datagramserverconnection.cpp
branchRCL_3
changeset 19 04becd199f91
child 87 1627c337e51e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/datagram/serverconnection/src/datagramserverconnection.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,331 @@
+/*
+* 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:
+ *
+*/
+
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <unistd.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <wchar.h>
+#include <string.h>
+
+#include "logger.h"
+#include "connectionlistener.h"
+#include "javacommonutils.h"
+
+#include "datagramserverconnection.h"
+#include "datagramserverconnectionfactory.h"
+#include "pushexception.h"
+#include "pusherrorcodes.h"
+
+#define INVALID_SOCKET (-1)
+#define MAX_SIZE 256
+#define BUFFER_SIZE 512
+
+using namespace java::util;
+
+DatagramServerConnection::DatagramServerConnection()
+{
+    LOG(ESOCKET, EInfo, "+DatagramServerConnection - default constructor");
+    mListener = NULL,
+                mThreadId = 0;
+    mKeepRunning = false;
+    mListenDatagram = INVALID_SOCKET;
+    mAcceptDatagram = INVALID_SOCKET;
+    mPort = 0;
+    mIsNormalServerConnection = true;
+    mError = 0;
+    mOpenMonitor = 0;
+}
+
+OS_EXPORT DatagramServerConnection::DatagramServerConnection(
+    const std::wstring& aUri, const std::wstring& aFilter) :
+        mListener(0), mThreadId(0), mKeepRunning(false), mListenDatagram(
+            INVALID_SOCKET), mAcceptDatagram(INVALID_SOCKET), mUri(aUri),
+        mFilter(aFilter), mPort(0)
+{
+    JELOG2(ESOCKET);
+
+    // sanity check for url
+    ILOG1(ESOCKET,
+          "++DatagramServerConnection::DatagramServerConnection() aUri = %s",
+          aUri.c_str());
+    mIsNormalServerConnection = false;
+    mIsAppRunning = false;
+    mError = 0;
+    mOpenMonitor = 0;
+
+    if (0 == mOpenMonitor)
+    {
+        mOpenMonitor = Monitor::createMonitor();
+    }
+
+    if (aUri.length() == 12)
+        mPort = 0;
+    else
+    {
+        std::wstring port = aUri.substr(12); // "datagram://:"
+        mPort = JavaCommonUtils::wstringToInt(port);
+    }
+    LOG1(ESOCKET, EInfo, "created DatagramServerConnection on port %d", mPort);
+}
+
+OS_EXPORT DatagramServerConnection::~DatagramServerConnection()
+{
+    if (mOpenMonitor)
+    {
+        delete mOpenMonitor;
+    }
+    JELOG2(ESOCKET);
+}
+
+OS_EXPORT void DatagramServerConnection::open(ConnectionListener* aListener)
+{
+    JELOG2(ESOCKET);
+    mListener = aListener;
+
+    mKeepRunning = true;
+    int rc = pthread_create(&mThreadId, NULL,
+                            DatagramServerConnection::listenThread, this);
+    mOpenMonitor->wait();
+
+    ILOG2(ESOCKET,"after release in datagram rc = %dm mPort = %d",rc,mPort);
+    if (rc < 0 || mError < 0)
+    {
+        ELOG1(ESOCKET,"ERROR!!! Datagram server conn already exists on Port %d : Open Failed",mPort);
+        std::string errTxt("ERROR!!! Opening of Datagram Server failed ");
+        throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR,errTxt,__FILE__,  __FUNCTION__,__LINE__);
+    }
+}
+
+void* DatagramServerConnection::listenThread(void* aParams)
+{
+    JELOG2(ESOCKET);
+    struct sockaddr_in sender_addr;
+    sender_addr.sin_family = AF_INET;
+    unsigned int size = sizeof(sender_addr);
+    bool match = false;
+
+    DatagramServerConnection* pThis =
+        reinterpret_cast<DatagramServerConnection*>(aParams);
+
+    pThis->mListenDatagram = pThis->open(pThis->mPort);
+
+    if (pThis->mListenDatagram < 0)
+    {
+        pThis->mError = -errno;
+        (pThis->mOpenMonitor)->notify();
+        pthread_exit(0);
+    }
+    (pThis->mOpenMonitor)->notify();
+
+
+    int rt = -1;
+    char * addr = new char[MAX_SIZE];
+
+    if (rt < 0 && pThis->mKeepRunning)
+    {
+        char *buf = new char[BUFFER_SIZE];
+        // wchar_t * sender = new wchar_t[256];
+        char *  sender = new  char[256];
+        while (match == false)
+        {
+            rt = recvfrom(pThis->mListenDatagram, buf, BUFFER_SIZE, 0,
+                          (sockaddr*) &sender_addr, &size);
+
+            strcpy(sender,inet_ntoa(sender_addr.sin_addr));
+            ILOG2(ESOCKET, "pThis->mListenDatagram =  %d, port = %d",pThis-> mListenDatagram,pThis->mPort);
+
+            // validate the filter
+            /*if(strcmp((const char *)pThis->mFilter.c_str(),(const char *) NULL)== 0)
+            {
+                  LOG(ESOCKET,EInfo,"filter is NULL");
+                    match = true;
+            }
+            else
+            {
+                if( strcmp((const char *)"*",(const char *)pThis->mFilter.c_str()) == 0)
+                {
+                    LOG(ESOCKET,EInfo,"filter = '*'");
+                    match = true;
+                }
+                if( strcmp((const char *)"?",(const char *)pThis->mFilter.c_str()) == 0)
+                {
+                    LOG(ESOCKET,EInfo,"filter = '?'");
+                    match = true;
+                }
+            }*/
+
+
+            match = true;
+        }
+    }
+
+    if (!(rt < 0)) // we have incoming connection
+    {
+        pThis->mAcceptDatagram = pThis->mListenDatagram;
+        if (pThis->mIsAppRunning == true)
+        {
+            pThis->setActivityFlag(false);
+            pthread_exit(0);
+        }
+        else
+        {
+            if (pThis->mListener)
+            {
+                pThis->mListener->msgArrived();
+            }
+            pThis->setActivityFlag(true);
+        }
+    }
+    return 0;
+}
+
+OS_EXPORT int DatagramServerConnection::open()
+{
+    JELOG2(ESOCKET);
+
+    mIsAppRunning = true;
+
+    if (mKeepRunning) // we are listening for push connection
+    {
+        mKeepRunning = false;
+        pthread_join(mThreadId, NULL);
+    }
+    else
+    {
+        mListenDatagram = open(mPort);
+    }
+    LOG2(ESOCKET,EInfo, "mListenDatagram =  %d, mPort = %d", mListenDatagram, mPort);
+    setActivityFlag(false);
+    return mListenDatagram;
+}
+
+int DatagramServerConnection::open(int aPort)
+{
+    JELOG2(ESOCKET);
+
+    struct sockaddr_in addr;
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons((unsigned short) aPort);
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+    int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if (fd == INVALID_SOCKET)
+    {
+        return -1;
+    }
+
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+    int res = bind(fd, (struct sockaddr*) &addr, sizeof(addr));
+
+    // when server is opened on dynamic port, append the port to the url
+    /*if(mPort == 0)
+    {
+            mPort = addr.sin_port;
+            LOG1(ESOCKET, EInfo, "dynamic port : %d", mPort);
+            std::wstring portString = JavaCommonUtils::intToWstring(mPort);
+            mUri.append(portString);
+            LOG1(ESOCKET, EInfo, "after appending mUri with dynamic port : %s", mUri);
+    }*/
+    LOG3(ESOCKET,EInfo, "server datgram sd =  %dm bind returns %d, mPort = %d ", fd, res, mPort);
+    if (res != -1)
+    {
+        return fd;
+    }
+    LOG1(ESOCKET,EInfo, "-errno : %d" , -errno);
+    close(fd);
+    return -1;
+}
+
+
+OS_EXPORT void DatagramServerConnection::close()
+{
+    JELOG2(ESOCKET);
+
+
+
+    ::close(mListenDatagram);
+    ::close(mAcceptDatagram);
+
+    if (mKeepRunning) // we are listening for push connection
+    {
+        mKeepRunning = false;
+        pthread_join(mThreadId, NULL);
+    }
+
+    // reset members
+    mListenDatagram = INVALID_SOCKET;
+    mAcceptDatagram = INVALID_SOCKET;
+
+    mListener = 0;
+    mThreadId = 0;
+    //mKeepRunning = false;
+}
+
+OS_EXPORT std::wstring DatagramServerConnection::getUri() const
+{
+    LOG(ESOCKET,EInfo, "DatagramServerConnection::getUri() ");
+    return mUri;
+}
+
+OS_EXPORT std::wstring DatagramServerConnection::getFilter() const
+{
+    return mFilter;
+}
+
+OS_EXPORT void DatagramServerConnection::setFilter(const std::wstring& aFilter)
+{
+    JELOG2(ESOCKET);
+    mFilter = aFilter;
+}
+OS_EXPORT bool DatagramServerConnection::isNormalServerConnection()
+{
+    return mIsNormalServerConnection;
+}
+
+OS_EXPORT void DatagramServerConnection::setNormalServerConnection()
+{
+    LOG(ESOCKET,EInfo,"Push is enabled");
+    mIsNormalServerConnection = true;
+}
+int DatagramServerConnection::close(int fd)
+{
+    return ::close(fd);
+}
+
+
+/**
+ * SetActivityFlag method  updates status whether
+ * ServerConnection object has pending message(= message arrived but not yet read).
+ * @param aFlag Updating logic of pending message flag:
+ *                    - Set it 'true' when message arrives to the connection.
+ *                    - Set it 'false' when ServerConnection::open() operation has been called.
+ */
+void DatagramServerConnection::setActivityFlag(bool aFlag)
+{
+    DatagramServerConnectionFactory& scf =
+        DatagramServerConnectionFactory::getFactory();
+    scf.setPendingMsgFlag(mUri, aFlag);
+}