diff -r f5050f1da672 -r 04becd199f91 javaextensions/datagram/serverconnection/src/datagramserverconnection.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(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); +}