--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/gcfprotocols/socket/serverconnection/src/socketserverconnection.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,395 @@
+/*
+* Copyright (c) 2007-2007 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 "socketserverconnection.h"
+#include "socketserverconnectionfactory.h"
+#include "pushexception.h"
+#include "pusherrorcodes.h"
+
+#define SOCKET_ERROR (-1)
+#define INVALID_SOCKET (-1)
+#define IO_WOULDBLOCK -2
+
+using namespace java::util;
+
+SocketServerConnection::SocketServerConnection()
+{
+ LOG(ESOCKET, EInfo, "+SocketServerConnection - default constructor");
+ mListener = NULL,
+ mThreadId = 0;
+ mKeepRunning = false;
+ mListenSocket = INVALID_SOCKET;
+ mAcceptSocket = INVALID_SOCKET;
+ mPort = 0;
+ mIsNormalServerConnection = true;
+ mOpenMonitor = 0;
+ mError = 0;
+}
+OS_EXPORT SocketServerConnection::SocketServerConnection
+(const std::wstring& aUri,
+ const std::wstring& aFilter)
+ : mListener(0),
+ mThreadId(0),
+ mKeepRunning(false),
+ mListenSocket(INVALID_SOCKET),
+ mAcceptSocket(INVALID_SOCKET),
+ mUri(aUri),
+ mFilter(aFilter),
+ mPort(0)
+
+{
+ JELOG2(ESOCKET);
+ LOG(ESOCKET, EInfo, "+SocketServerConnection::SocketServerConnection");
+ // sanity check for url
+ mIsAppRunning = false;
+ mIsNormalServerConnection = false;
+ mOpenMonitor = 0;
+ mError = 0;
+
+ // create monitors only when connection comes via push plugin
+ if (0 == mOpenMonitor)
+ {
+ mOpenMonitor = Monitor::createMonitor();
+ }
+ if (aUri.find(L"socket://:") != std::wstring::npos)
+ {
+ if (aUri.length() == 10)
+ mPort = 0;
+ else
+ {
+ std::wstring port = aUri.substr(10); // "socket://:"
+ mPort = JavaCommonUtils::wstringToInt(port);
+ }
+ LOG1(ESOCKET, EInfo, "created SocketServerConnection on port %d", mPort);
+ }
+ else
+ {
+ mPort = -1;
+ LOG(ESOCKET, EInfo, "SocketServerConnection::SocketServerConnection() Invalid url");
+ }
+}
+
+OS_EXPORT SocketServerConnection::~SocketServerConnection()
+{
+ JELOG2(ESOCKET);
+ if (mOpenMonitor)
+ {
+ delete mOpenMonitor;
+ }
+}
+
+
+/* ----------------------------------------------------------------------
+
+Starting point for socket server. A new thread is created which inturn initializes the server socket and waits
+for an incoming connection.
+
+pthread_create(): This OpenC call is used to create the new thread. listenThread() is passed as the start point
+of the thread.
+
+-------------------------------------------------------------------------*/
+OS_EXPORT void SocketServerConnection::open(ConnectionListener* aListener)
+{
+ JELOG2(ESOCKET);
+ mListener = aListener;
+
+ mKeepRunning = true;
+
+ int rc = pthread_create(&mThreadId, NULL, SocketServerConnection::listenThread, this);
+ mOpenMonitor->wait(); // wait for open to return
+
+ ILOG2(ESOCKET,"after release rc = %dm mPort = %d",rc,mPort);
+ if (rc < 0 || mError < 0)
+ {
+ ELOG1(ESOCKET,"Socket server conn already exists on Port %d : Open Failed",mPort);
+ std::string errTxt("ERROR!!! Opening of SocketServer failed");
+ throw PushException(COMMON_SRV_CONN_PLUGIN_ERROR,errTxt,__FILE__, __FUNCTION__,__LINE__);
+ }
+}
+
+
+// Since server socket is non-blocking, a accept() is called in a new thread
+
+void* SocketServerConnection::listenThread(void* aParams)
+{
+ JELOG2(ESOCKET);
+
+ SocketServerConnection* pThis = reinterpret_cast<SocketServerConnection*>(aParams);
+
+ pThis->mListenSocket = pThis->open(pThis->mPort);
+ ILOG1(ESOCKET, "+SocketServerConnection::listenThread - pThis->mListenSocket = %d",pThis->mListenSocket);
+
+ if (pThis->mListenSocket < 0)
+ {
+ pThis->mError = -errno;
+ (pThis->mOpenMonitor)->notify();
+ pthread_exit(0);
+ }
+ (pThis->mOpenMonitor)->notify();
+
+
+ int fd = INVALID_SOCKET;
+
+ if (fd < 0 && pThis->mKeepRunning)
+ {
+ fd = pThis->accept();
+ }
+
+ if (!(fd<0)) // we have incoming connection
+ {
+ pThis->mAcceptSocket = fd;
+ if (pThis->mIsAppRunning == true)
+ {
+ pThis->setActivityFlag(false);
+ pthread_exit(0);
+ }
+ else
+ {
+ if (pThis->mListener)
+ {
+ pThis->mListener->msgArrived();
+ }
+ pThis->setActivityFlag(true);
+ }
+ }
+
+ pthread_exit(0);
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------
+This function is used to open a server socket connection.
+
+@param: aPort - Port on which the server will bind and start lisetening.
+
+OpenC apis used
+
+htons(), htonl() : to convert values between host and network byte order
+
+socket(): creates an endpoint for communication and returns a descriptor. We create a "STREAM" socket
+
+bind(): We bind to address INADDR_ANY, which indicates listen happens on all networking interfaces present
+
+listen(): listens for incoming connection.
+
+accept(): accepts a connection on a socket.
+
+-------------------------------------------------------------------------*/
+OS_EXPORT int SocketServerConnection::open()
+{
+ JELOG2(ESOCKET);
+
+ mIsAppRunning = true;
+
+ if (mKeepRunning) // we are listening for push connection
+ {
+ mKeepRunning = false;
+ pthread_join(mThreadId, NULL);
+ }
+ else
+ {
+ mListenSocket = open(mPort);
+ }
+ setActivityFlag(false);
+ return mListenSocket;
+}
+
+int SocketServerConnection::open(int aPort)
+{
+ JELOG2(ESOCKET);
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == INVALID_SOCKET)
+ {
+ int err = -errno;
+ return err;
+ }
+
+ 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 res = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
+ if (res != SOCKET_ERROR)
+ {
+ res = listen(fd, SOMAXCONN);
+ if (res != SOCKET_ERROR)
+ {
+ // setNonBlocking(fd);
+ return fd;
+ }
+ }
+ int err = -errno;
+ LOG(ESOCKET,EInfo,"closing ..");
+ close(fd);
+ return err;
+}
+
+OS_EXPORT int SocketServerConnection::accept()
+{
+ JELOG2(ESOCKET);
+ int sock_fd = INVALID_SOCKET;
+
+ if (mAcceptSocket != INVALID_SOCKET) // incoming push connection
+ {
+ sock_fd = mAcceptSocket;
+ mAcceptSocket = INVALID_SOCKET;
+ }
+ else
+ {
+ sock_fd = accept(mListenSocket);
+ }
+
+ return sock_fd;
+}
+
+int SocketServerConnection::accept(int fd)
+{
+ // paramter fd, is the socket descriptor returned during server socket creation.
+ struct sockaddr_in sa;
+ socklen_t saLen = sizeof(sa);
+ int res = 0;
+
+
+ LOG(ESOCKET, EInfo, "before accept");
+ res = ::accept(fd, (struct sockaddr *)&sa, &saLen);
+ LOG1(ESOCKET, EInfo, "accept returned %d",res);
+ if ((res == -1) && (errno == EWOULDBLOCK))
+ {
+ res = IO_WOULDBLOCK;
+ }
+ if (res == -1)
+ {
+ int err = -errno;
+ return err;
+ }
+ return res;
+}
+OS_EXPORT bool SocketServerConnection::isNormalServerConnection()
+{
+ return mIsNormalServerConnection;
+}
+
+OS_EXPORT void SocketServerConnection::setNormalServerConnection()
+{
+ LOG(ESOCKET,EInfo,"Push is enabled");
+ mIsNormalServerConnection = true;
+}
+
+OS_EXPORT void SocketServerConnection::close()
+{
+ JELOG2(ESOCKET);
+
+ if (mListenSocket != INVALID_SOCKET)
+ {
+ int ret = shutdown(mListenSocket,SHUT_RDWR);
+ close(mListenSocket);
+ LOG1(ESOCKET, EInfo, "shutdown of mListenSocket returned %d",ret);
+ }
+
+ if (mAcceptSocket != INVALID_SOCKET)
+ {
+ int ret = shutdown(mAcceptSocket,SHUT_RDWR);
+ close(mAcceptSocket);
+ LOG1(ESOCKET, EInfo, "shutdown of mAcceptSocket returned %d",ret);
+ }
+
+ if (mKeepRunning) // we are listening for push connection
+ {
+ mKeepRunning = false;
+ pthread_join(mThreadId, NULL);
+ }
+ // reset members
+ mListenSocket = INVALID_SOCKET;
+ mAcceptSocket = INVALID_SOCKET;
+
+ mListener = 0;
+ mThreadId = 0;
+ //mKeepRunning = false;
+
+}
+
+OS_EXPORT std::wstring SocketServerConnection::getUri() const
+{
+ return mUri;
+}
+
+OS_EXPORT std::wstring SocketServerConnection::getFilter() const
+{
+ return mFilter;
+}
+
+OS_EXPORT void SocketServerConnection::setFilter(const std::wstring& aFilter)
+{
+ JELOG2(ESOCKET);
+ mFilter = aFilter;
+ return;
+}
+
+OS_EXPORT int SocketServerConnection::close(int fd)
+{
+ LOG(ESOCKET, EInfo, "+SocketServerConnection::close(int fd)");
+ if (mListenSocket != INVALID_SOCKET)
+ {
+ int ret = shutdown(mListenSocket,SHUT_RDWR);
+ LOG1(ESOCKET, EInfo, "shutdown of mListenSocket returned %d",ret);
+ }
+
+ if (mAcceptSocket != INVALID_SOCKET)
+ {
+ int ret = shutdown(mAcceptSocket,SHUT_RDWR);
+ LOG1(ESOCKET, EInfo, "shutdown of mAcceptSocket returned %d",ret);
+ }
+
+ int ret = ::close(fd);
+ // reset members
+ mListenSocket = INVALID_SOCKET;
+ mAcceptSocket = INVALID_SOCKET;
+
+ LOG(ESOCKET, EInfo, "-SocketServerConnection::close(int fd)");
+ return ret;
+}
+
+void SocketServerConnection::setNonBlocking(int fd)
+{
+ // first get the flags associated with this descriptor.
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0)
+ {
+ return; // check errno
+ }
+
+ // set the non-blocking flag to make the accept() call as non-blocking.
+ flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+ if (flags < 0)
+ {
+ return; // throw exception
+ }
+
+}
+
+void SocketServerConnection::setActivityFlag(bool aFlag)
+{
+ SocketServerConnectionFactory& scf =
+ SocketServerConnectionFactory::getFactory();
+ scf.setPendingMsgFlag(mUri, aFlag);
+}
+