javacommons/gcfprotocols/socket/socket/src/nativesocketconnection.cpp
changeset 21 2a9601315dfc
child 67 63b81d807542
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/gcfprotocols/socket/socket/src/nativesocketconnection.cpp	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,438 @@
+/*
+* 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:  Socket Connection Impl Class
+*
+*/
+
+
+
+
+#ifndef __SYMBIAN32__
+#include <netinet/tcp.h>  // TCP_NODELAY
+#endif
+
+#include <stdio.h>
+#include "nativesocketconnection.h"
+#include "jniarrayutils.h"
+#include "apnsettings.h"
+using namespace java;
+
+OS_EXPORT NativeSocketConnection::NativeSocketConnection(const char* aName,int aMode, const char *aHost, int aPort)
+{
+    // JELOG2(ESOCKET);
+    mName = NULL;
+    mHost = NULL;
+    mName = new char[strlen(aName)+1];
+    strcpy(mName, aName);
+    mMode = aMode;
+    mPort = aPort;
+    LOG1(ESOCKET, EInfo, "before   , aHost + %s" , aHost);
+    mHost = new char[strlen(aHost)+1];
+    strcpy(mHost, aHost);
+    LOG2(ESOCKET, EInfo, "after  mHost = %s , aHost + %s" ,mHost, aHost);
+    mSocketBuffer = NULL;
+    mLingerValue = 0;
+}
+
+
+OS_EXPORT NativeSocketConnection::~NativeSocketConnection()
+{
+    // JELOG2(ESOCKET);
+    if (mName != NULL)
+    {
+        delete[] mName;
+    }
+    if (mHost != NULL)
+    {
+        delete[] mHost;
+    }
+    if (mSocketBuffer != NULL)
+    {
+        delete[] mSocketBuffer;
+        mSocketBuffer = NULL;
+    }
+
+}
+
+OS_EXPORT int NativeSocketConnection::readBytes(JNIEnv& aJni, jbyteArray aJavaBuffer)
+{
+    JELOG2(ESOCKET);
+    if (mSocketBuffer == NULL)
+    {
+
+        /*
+        Memory is allocated to isocketBuffer only once during the first call of this readBytes() function
+        Since the value of mBufferSize will be unknown(uninitialized) during the constructor call, it is not
+        possible to do this operation inside the constructor.
+        */
+
+        mSocketBuffer = new char[mBufferSize];
+    }
+
+    // socketRead() function will actually make the OpenC call to read the data from the socket
+    mBytesRead = socketRead(mSocketBuffer, mBufferSize);
+
+    ILOG1(ESOCKET, "NativeSocketConnection::readBytes() : Num of bytes read is %d", mBytesRead);
+
+    /* Copy the data read from the native buffer to the java buffer. Copy only "bytesRead" number of bytes.
+       Because it is possible that the java request for some 'n' bytes to be read, but actually lesser bytes of data was
+       read from the socket.
+    */
+
+    if (mBytesRead > 0)
+    {
+        JNIArrayUtils::CopyToJava(aJni, mSocketBuffer, mBytesRead, aJavaBuffer, 0, mBytesRead);
+    }
+
+    return mBytesRead;
+}
+
+OS_EXPORT int NativeSocketConnection::writeBytes(JNIEnv& aJni, jbyteArray aJavaBuffer, int aOffset, int aLength)
+{
+    JELOG2(ESOCKET);
+    char *iWriteBuffer =  new char[aLength + 1];
+    int retval;
+
+    /* Copy the data to be written from java buffer to the native buffer.  */
+    JNIArrayUtils::CopyToNative(aJni, aJavaBuffer, aOffset, aLength, iWriteBuffer);
+
+    // socketWrite() function will actually make the OpenC call to read the data from the socket
+    mBytesWritten = socketWrite(iWriteBuffer, aLength);
+
+    ILOG1(ESOCKET,  "NativeSocketConnection::writeBytes() : Num of bytes written is %d", mBytesWritten);
+
+    delete[] iWriteBuffer;
+    iWriteBuffer = NULL;
+
+    if (mBytesWritten < 0)
+    {
+        retval =  - errno; // If write failed, return the errno value
+    }
+    else
+    {
+        retval = mBytesWritten;
+    }
+    return retval;
+}
+
+OS_EXPORT void NativeSocketConnection::stopReading()
+{
+    // JELOG2(ESOCKET);
+    return;
+}
+
+OS_EXPORT void NativeSocketConnection::stopWriting()
+{
+    // JELOG2(ESOCKET);
+    return;
+}
+
+
+/* ----------------------------------------------------------------------
+This function is used to open a socket connection.
+
+OpenC apis used
+
+inet_aton() : converts the Internet host address cp from the standard numbers-and- dots notation
+              into binary data and stores it in the structure
+
+socket():  creates an endpoint for communication and returns a descriptor. We create a "STREAM" socket
+
+
+connect(): initiates a connection to the socket server. This involves the three way handshake process.
+-------------------------------------------------------------------------*/
+OS_EXPORT int NativeSocketConnection::socketOpen(int aSockDesc, int aType, int aApn, int * err)
+{
+    // // JELOG2(ESOCKET);
+    struct sockaddr_in addr;
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(mPort);
+    int retval;
+
+    LOG(ESOCKET, EInfo, "NativeSocketConnection::socketOpen");
+    if (aSockDesc == -1)
+    {
+        LOG(ESOCKET, EInfo, "Opening a socket");
+        mSockDesc = socket(AF_INET, SOCK_STREAM , 0);
+        if (mSockDesc == -1)
+        {
+            LOG1(ESOCKET, EInfo, "creation of socket failed : %d", errno);
+            return -errno;
+        }
+        LOG1(ESOCKET, EInfo,"NativeSocketConnection::socketOpen() : Socket descriptor = %d",mSockDesc);
+
+        int ret  =0;
+        if (aApn != -1)
+        {
+            // remove comments if open c patch available
+            ret = ApnSettings::setDefaultApn(aType,aApn);
+        }
+        LOG1(ESOCKET, EInfo,"NativeSocketConnection::socketOpen() : Ssetdefaultapn returned = %d",ret);
+        *err = ret;
+
+        if (!inet_aton(mHost, &addr.sin_addr))
+        {
+            LOG1(ESOCKET, EInfo, "before getHostByName , mHost = %s" ,mHost);
+            struct hostent* hp = gethostbyname(mHost);
+            if (hp ==  NULL)
+            {
+                return -(h_errno);
+            }
+            addr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr;
+        }
+        LOG(ESOCKET, EInfo, "After getHostByName");
+
+
+        int rc = connect(mSockDesc, (struct sockaddr*)&addr, sizeof(addr));
+        if (rc < 0)
+        {
+            LOG1(ESOCKET, EInfo, "NativeSocketConnection::socketOpen() : socket connect failed : %d", errno);
+            retval =  -errno;
+        }
+        else
+        {
+            retval = mSockDesc;
+        }
+    }
+    else
+    {
+        LOG(ESOCKET, EInfo, "Socket already opened, setting socket descriptor");
+        mSockDesc = aSockDesc;
+        retval = 1;
+    }
+    return retval;
+}
+
+
+OS_EXPORT int NativeSocketConnection::socketRead(char *aReadBuf, int aLen)
+{
+    LOG(ESOCKET,EInfo, "NativeSocketConnection::socketRead");
+    int retValue = recv(mSockDesc, aReadBuf, aLen, 0);
+
+    if ((retValue==-1) && (errno == EAGAIN))
+    {
+        retValue = 0;
+    }
+    return retValue;
+}
+
+OS_EXPORT int NativeSocketConnection::socketWrite(char *aWriteBuf, int aLen)
+{
+    LOG1(ESOCKET, EInfo,"SOCKET WRITE BUF IS %s",aWriteBuf);
+    int retValue = send(mSockDesc, aWriteBuf, aLen, 0);
+
+    return retValue;
+}
+
+
+
+OS_EXPORT int NativeSocketConnection::getSocketOption(int aOption)
+{
+    // JELOG2(ESOCKET);
+    LOG1(ESOCKET, EInfo, "++NativeSocketConnection::getSocketOption,option = %d", aOption);
+    int level = SOL_SOCKET;
+    int optname = -1;
+    int optval = 0;
+    socklen_t optsize = sizeof(optname);
+    void * opttarget = (void *)(&optval) ;
+    int retval;
+
+    switch (aOption)
+    {
+    case 0: // DELAY
+        level = IPPROTO_TCP;
+        optname = TCP_NODELAY;
+        break;
+    case 1: // LINGER
+        return mLingerValue;
+    case 2: // KEEPALIVE
+        optname = SO_KEEPALIVE;
+        break;
+    case 3: // RCVBUF
+        optname = SO_RCVBUF;
+        break;
+    case 4: // SNDBUF
+        optname = SO_SNDBUF;
+        break;
+    }
+
+    if (getsockopt(mSockDesc, level,  optname, opttarget, &optsize) == 0)
+    {
+        retval = optval;
+    }
+    else
+    {
+        LOG1(ESOCKET, EInfo, "NativeSocketConnection::getSocketOption failed, option = %d",aOption);
+        retval = -errno;
+    }
+    LOG(ESOCKET, EInfo, "--NativeSocketConnection::getSocketOption");
+    return retval;
+}
+
+OS_EXPORT int NativeSocketConnection::setSocketOption(int aOption, int aOptval)
+{
+    // JELOG2(ESOCKET);
+    int    level = SOL_SOCKET;
+    socklen_t optsize =  sizeof(aOptval);
+    int    optname = -1;
+    void * opttarget = (void *) & aOptval ;
+    int retval;
+
+    switch (aOption)
+    {
+        // DELAY
+    case 0:
+        level = IPPROTO_TCP;
+        optname = TCP_NODELAY;
+        break;
+        // LINGER
+    case 1:
+        /* The openC api doesn't support SO_LINGER option. This is because, the native symbian doesn't support this.
+        But since, tck has few test cases related to this option, this call should return success
+        */
+        mLingerValue = aOptval;
+        return 0;
+        // KEEPALIVE
+    case 2:
+        optname = SO_KEEPALIVE;
+        break;
+        // RCVBUF
+    case 3:
+        optname = SO_RCVBUF;
+        break;
+        // SNDBUF
+    case 4:
+        optname = SO_SNDBUF;
+        break;
+    }
+    //LOG3(ESOCKET,EInfo,"IN NativeSocketConnection::setsocketoption optname is %d level is %s aOptval is %d", optname, level, aOptval);
+    if (setsockopt(mSockDesc, level,  optname, opttarget, optsize) == 0)
+    {
+        LOG(ESOCKET,EInfo, "NativeSocketConnection::setsocketoption  setsockopt returned 0");
+        retval = 0;
+    }
+    else
+    {
+        retval = -errno;
+    }
+    return retval;
+}
+
+OS_EXPORT int NativeSocketConnection::socketClose()
+{
+    // JELOG2(ESOCKET);
+    int retValue = close(mSockDesc);
+    if (retValue == -1)
+    {
+        LOG1(ESOCKET, EInfo, "NativeSocketConnection::socketClose() : socket close failed : %d", errno);
+        return -errno;
+    }
+    else
+    {
+        LOG(ESOCKET,EInfo, "NativeSocketConnection::socketClose successfull");
+        return retValue;
+    }
+}
+
+/* ----------------------------------------------------------------------
+This function is used to get remote port number to which this socket is connected.
+OpenC api used
+getpeername(): gets name of connected peer socket. This fills the peer address and port into the structure passed as an argument to it.
+-------------------------------------------------------------------------*/
+OS_EXPORT int NativeSocketConnection::getPort()
+{
+    // JELOG2(ESOCKET);
+    struct sockaddr_in addr;
+    socklen_t len = sizeof(addr);
+    int retval;
+
+    if ((getpeername(mSockDesc, (struct sockaddr*)&addr, &len)) < 0)
+    {
+        LOG1(ESOCKET, EInfo, "NativeSocketConnection::getPort() : getport failed : %d", errno);
+        retval = -errno;
+    }
+    else
+    {
+        retval = ntohs(addr.sin_port);
+    }
+    return retval;
+}
+
+
+/* ----------------------------------------------------------------------
+This function is used to get local port number to which this socket is bound.
+OpenC api used
+getsockname(): gets socket name. This fills the local address and port into the structure passed as an argument to it.
+-------------------------------------------------------------------------*/
+OS_EXPORT int NativeSocketConnection::getLocalPort()
+{
+    // JELOG2(ESOCKET);
+    struct sockaddr_in addr;
+    socklen_t len = sizeof(addr);
+    int retval;
+
+    if ((getsockname(mSockDesc, (struct sockaddr*)&addr, &len)) < 0)
+    {
+        LOG1(ESOCKET, EInfo, "NativeSocketConnection::getLocalPort() : getlocalport failed : %d", errno);
+        retval =  -errno;
+    }
+    else
+    {
+        retval = ntohs(addr.sin_port);
+    }
+    return retval;
+}
+
+
+
+OS_EXPORT int NativeSocketConnection::getLocalAddress(char * aAddress)
+{
+    // JELOG2(ESOCKET);
+    struct sockaddr_in addr;
+    socklen_t len = sizeof(addr);
+    int retval;
+
+    if (getsockname(mSockDesc, (struct sockaddr*)&addr, &len) < 0)
+    {
+        LOG1(ESOCKET, EInfo, "NativeSocketConnection::getLocalAddress() : getlocaladdress failed : %d", errno);
+        strcpy(aAddress, "error");
+        retval =  -errno;
+    }
+    else
+    {
+        strcpy(aAddress, inet_ntoa(addr.sin_addr));
+        retval = 0;
+    }
+    return retval;
+}
+
+OS_EXPORT int NativeSocketConnection::getAddress(char * aAddress)
+{
+    // JELOG2(ESOCKET);
+    struct sockaddr_in addr;
+    socklen_t len = sizeof(addr);
+    int retval;
+
+    if (getpeername(mSockDesc, (struct sockaddr*)&addr, &len) < 0)
+    {
+        strcpy(aAddress, "error");
+        retval = -errno;
+    }
+    else
+    {
+        strcpy(aAddress, inet_ntoa(addr.sin_addr));
+        retval = 0;
+    }
+    return retval;
+}