--- /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);
+}