/* $Id$ */
/* 
 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#include <pj/sock.h>
#include <pj/addr_resolv.h>
#include <pj/assert.h>
#include <pj/errno.h>
#include <pj/os.h>
#include <pj/string.h>
#include <pj/unicode.h>

#include "os_symbian.h"


/*
 * Address families.
 */
const pj_uint16_t PJ_AF_UNSPEC	= KAFUnspec;
const pj_uint16_t PJ_AF_UNIX	= 0xFFFF;
const pj_uint16_t PJ_AF_INET	= KAfInet;
const pj_uint16_t PJ_AF_INET6	= KAfInet6;
const pj_uint16_t PJ_AF_PACKET	= 0xFFFF;
const pj_uint16_t PJ_AF_IRDA	= 0xFFFF;

/*
 * Socket types conversion.
 * The values here are indexed based on pj_sock_type
 */
const pj_uint16_t PJ_SOCK_STREAM= KSockStream;
const pj_uint16_t PJ_SOCK_DGRAM	= KSockDatagram;
const pj_uint16_t PJ_SOCK_RAW	= 0xFFFF;
const pj_uint16_t PJ_SOCK_RDM	= 0xFFFF;

/* setsockop() is not really supported. */
const pj_uint16_t PJ_SOL_SOCKET	= 0xFFFF;
const pj_uint16_t PJ_SOL_IP	= 0xFFFF;
const pj_uint16_t PJ_SOL_TCP	= 0xFFFF;
const pj_uint16_t PJ_SOL_UDP	= 0xFFFF;
const pj_uint16_t PJ_SOL_IPV6	= 0xFFFF;

/* TOS */
const pj_uint16_t PJ_IP_TOS		= 0;
const pj_uint16_t PJ_IPTOS_LOWDELAY	= 0;
const pj_uint16_t PJ_IPTOS_THROUGHPUT	= 0;
const pj_uint16_t PJ_IPTOS_RELIABILITY	= 0;
const pj_uint16_t PJ_IPTOS_MINCOST	= 0;

/* ioctl() is also not supported. */
const pj_uint16_t PJ_SO_TYPE    = 0xFFFF;
const pj_uint16_t PJ_SO_RCVBUF  = 0xFFFF;
const pj_uint16_t PJ_SO_SNDBUF  = 0xFFFF;

/* IP multicast is also not supported. */
const pj_uint16_t PJ_IP_MULTICAST_IF    = 0xFFFF;
const pj_uint16_t PJ_IP_MULTICAST_TTL   = 0xFFFF;
const pj_uint16_t PJ_IP_MULTICAST_LOOP  = 0xFFFF;
const pj_uint16_t PJ_IP_ADD_MEMBERSHIP  = 0xFFFF;
const pj_uint16_t PJ_IP_DROP_MEMBERSHIP = 0xFFFF;

/* Flags */
const int PJ_MSG_OOB	     = 0;
const int PJ_MSG_PEEK	     = KSockReadPeek;
const int PJ_MSG_DONTROUTE   = 0;

/////////////////////////////////////////////////////////////////////////////
//
// CPjSocket implementation.
// (declaration is in os_symbian.h)
//

CPjSocket::~CPjSocket()
{
    DestroyReader();
    sock_.Close();
}


// Create socket reader.
CPjSocketReader *CPjSocket::CreateReader(unsigned max_len)
{
    pj_assert(sockReader_ == NULL);
    return sockReader_ = CPjSocketReader::NewL(*this, max_len);
}

// Delete socket reader when it's not wanted.
void CPjSocket::DestroyReader() 
{
    if (sockReader_) {
	sockReader_->Cancel();
	delete sockReader_;
	sockReader_ = NULL;
    }
}


/////////////////////////////////////////////////////////////////////////////
//
// CPjSocketReader implementation
// (declaration in os_symbian.h)
//


CPjSocketReader::CPjSocketReader(CPjSocket &sock)
: CActive(EPriorityStandard), 
  sock_(sock), buffer_(NULL, 0), readCb_(NULL), key_(NULL)
{
}


void CPjSocketReader::ConstructL(unsigned max_len)
{
    TProtocolDesc aProtocol;
    TInt err;

    err = sock_.Socket().Info(aProtocol);
    User::LeaveIfError(err);

    isDatagram_ = (aProtocol.iSockType == KSockDatagram);

    TUint8 *ptr = new TUint8[max_len];
    buffer_.Set(ptr, 0, (TInt)max_len);
    CActiveScheduler::Add(this);
}

CPjSocketReader *CPjSocketReader::NewL(CPjSocket &sock, unsigned max_len)
{
    CPjSocketReader *self = new (ELeave) CPjSocketReader(sock);
    CleanupStack::PushL(self);
    self->ConstructL(max_len);
    CleanupStack::Pop(self);

    return self;
}


CPjSocketReader::~CPjSocketReader()
{
    const TUint8 *data = buffer_.Ptr();
    delete [] data;
}

void CPjSocketReader::StartRecv(void (*cb)(void *key), 
			        void *key, 
			        TDes8 *aDesc,
			        TUint flags)
{
    StartRecvFrom(cb, key, aDesc, flags, NULL);
}

void CPjSocketReader::StartRecvFrom(void (*cb)(void *key), 
				    void *key, 
				    TDes8 *aDesc,
				    TUint flags,
				    TSockAddr *fromAddr)
{
    readCb_ = cb;
    key_ = key;

    if (aDesc == NULL) aDesc = &buffer_;
    if (fromAddr == NULL) fromAddr = &recvAddr_;

    sock_.Socket().RecvFrom(*aDesc, *fromAddr, flags, iStatus);
    SetActive();
}

void CPjSocketReader::DoCancel()
{
    sock_.Socket().CancelRecv();
}

void CPjSocketReader::RunL()
{
    void (*old_cb)(void *key) = readCb_;
    void *old_key = key_;

    readCb_ = NULL;
    key_ = NULL;

    if (old_cb) {
	(*old_cb)(old_key);
    }
}

// Append data to aDesc, up to aDesc's maximum size.
// If socket is datagram based, buffer_ will be clared.
void CPjSocketReader::ReadData(TDes8 &aDesc, TInetAddr *addr)
{
    if (isDatagram_)
	aDesc.Zero();

    if (buffer_.Length() == 0)
	return;

    TInt size_to_copy = aDesc.MaxLength() - aDesc.Length();
    if (size_to_copy > buffer_.Length())
	size_to_copy = buffer_.Length();

    aDesc.Append(buffer_.Ptr(), size_to_copy);

    if (isDatagram_)
	buffer_.Zero();
    else
	buffer_.Delete(0, size_to_copy);

    if (addr)
	*addr = recvAddr_;
}



/////////////////////////////////////////////////////////////////////////////
//
// PJLIB's sock.h implementation
//

/*
 * Convert 16-bit value from network byte order to host byte order.
 */
PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
{
#if PJ_IS_LITTLE_ENDIAN
    return pj_swap16(netshort);
#else
    return netshort;
#endif
}

/*
 * Convert 16-bit value from host byte order to network byte order.
 */
PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
{
#if PJ_IS_LITTLE_ENDIAN
    return pj_swap16(hostshort);
#else
    return hostshort;
#endif
}

/*
 * Convert 32-bit value from network byte order to host byte order.
 */
PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
{
#if PJ_IS_LITTLE_ENDIAN
    return pj_swap32(netlong);
#else
    return netlong;
#endif
}

/*
 * Convert 32-bit value from host byte order to network byte order.
 */
PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
{
#if PJ_IS_LITTLE_ENDIAN
    return pj_swap32(hostlong);
#else
    return netlong;
#endif
}

/*
 * Convert an Internet host address given in network byte order
 * to string in standard numbers and dots notation.
 */
PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
{
	static char str8[PJ_INET_ADDRSTRLEN];
    TBuf<PJ_INET_ADDRSTRLEN> str16(0);

    /* (Symbian IP address is in host byte order) */
    TInetAddr temp_addr((TUint32)pj_ntohl(inaddr.s_addr), (TUint)0);
    temp_addr.Output(str16);
 
    return pj_unicode_to_ansi((const wchar_t*)str16.PtrZ(), str16.Length(),
			      str8, sizeof(str8));
}

/*
 * This function converts the Internet host address cp from the standard
 * numbers-and-dots notation into binary data and stores it in the structure
 * that inp points to. 
 */
PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
{
    enum { MAXIPLEN = PJ_INET_ADDRSTRLEN };

    /* Initialize output with PJ_INADDR_NONE.
     * Some apps relies on this instead of the return value
     * (and anyway the return value is quite confusing!)
     */
    inp->s_addr = PJ_INADDR_NONE;

    /* Caution:
     *	this function might be called with cp->slen >= 16
     *  (i.e. when called with hostname to check if it's an IP addr).
     */
    PJ_ASSERT_RETURN(cp && cp->slen && inp, 0);
    if (cp->slen >= 16) {
	return 0;
    }

    char tempaddr8[MAXIPLEN];
    pj_memcpy(tempaddr8, cp->ptr, cp->slen);
    tempaddr8[cp->slen] = '\0';

    wchar_t tempaddr16[MAXIPLEN];
    pj_ansi_to_unicode(tempaddr8, pj_ansi_strlen(tempaddr8),
		       tempaddr16, sizeof(tempaddr16));

    TBuf<MAXIPLEN> ip_addr((const TText*)tempaddr16);

    TInetAddr addr;
    addr.Init(KAfInet);
    if (addr.Input(ip_addr) == KErrNone) {
	/* Success (Symbian IP address is in host byte order) */
	inp->s_addr = pj_htonl(addr.Address());
	return 1;
    } else {
	/* Error */
	return 0;
    }
}

/*
 * Convert text to IPv4/IPv6 address.
 */
PJ_DEF(pj_status_t) pj_inet_pton(int af, const pj_str_t *src, void *dst)
{
    char tempaddr[PJ_INET6_ADDRSTRLEN];

    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL);
    PJ_ASSERT_RETURN(src && src->slen && dst, PJ_EINVAL);

    /* Initialize output with PJ_IN_ADDR_NONE for IPv4 (to be 
     * compatible with pj_inet_aton()
     */
    if (af==PJ_AF_INET) {
	((pj_in_addr*)dst)->s_addr = PJ_INADDR_NONE;
    }

    /* Caution:
     *	this function might be called with cp->slen >= 46
     *  (i.e. when called with hostname to check if it's an IP addr).
     */
    if (src->slen >= PJ_INET6_ADDRSTRLEN) {
	return PJ_ENAMETOOLONG;
    }

    pj_memcpy(tempaddr, src->ptr, src->slen);
    tempaddr[src->slen] = '\0';


    wchar_t tempaddr16[PJ_INET6_ADDRSTRLEN];
    pj_ansi_to_unicode(tempaddr, pj_ansi_strlen(tempaddr),
		       tempaddr16, sizeof(tempaddr16));

    TBuf<PJ_INET6_ADDRSTRLEN> ip_addr((const TText*)tempaddr16);

    TInetAddr addr;
    addr.Init(KAfInet6);
    if (addr.Input(ip_addr) == KErrNone) {
	if (af==PJ_AF_INET) {
	    /* Success (Symbian IP address is in host byte order) */
	    pj_uint32_t ip = pj_htonl(addr.Address());
	    pj_memcpy(dst, &ip, 4);
	} else if (af==PJ_AF_INET6) {
	    const TIp6Addr & ip6 = addr.Ip6Address();
	    pj_memcpy(dst, ip6.u.iAddr8, 16);
	} else {
	    pj_assert(!"Unexpected!");
	    return PJ_EBUG;
	}
	return PJ_SUCCESS;
    } else {
	/* Error */
	return PJ_EINVAL;
    }
}

/*
 * Convert IPv4/IPv6 address to text.
 */
PJ_DEF(pj_status_t) pj_inet_ntop(int af, const void *src,
				 char *dst, int size)

{
    PJ_ASSERT_RETURN(src && dst && size, PJ_EINVAL);

    *dst = '\0';

    if (af==PJ_AF_INET) {

	TBuf<PJ_INET_ADDRSTRLEN> str16;
	pj_in_addr inaddr;

	if (size < PJ_INET_ADDRSTRLEN)
	    return PJ_ETOOSMALL;

	pj_memcpy(&inaddr, src, 4);

	/* Symbian IP address is in host byte order */
	TInetAddr temp_addr((TUint32)pj_ntohl(inaddr.s_addr), (TUint)0);
	temp_addr.Output(str16);
 
	pj_unicode_to_ansi((const wchar_t*)str16.PtrZ(), str16.Length(),
			   dst, size);
	return PJ_SUCCESS;

    } else if (af==PJ_AF_INET6) {
	TBuf<PJ_INET6_ADDRSTRLEN> str16;

	if (size < PJ_INET6_ADDRSTRLEN)
	    return PJ_ETOOSMALL;

	TIp6Addr ip6;
	pj_memcpy(ip6.u.iAddr8, src, 16);

	TInetAddr temp_addr(ip6, (TUint)0);
	temp_addr.Output(str16);
 
	pj_unicode_to_ansi((const wchar_t*)str16.PtrZ(), str16.Length(),
			   dst, size);
	return PJ_SUCCESS;

    } else {
	pj_assert(!"Unsupport address family");
	return PJ_EINVAL;
    }

}

/*
 * Get hostname.
 */
PJ_DEF(const pj_str_t*) pj_gethostname(void)
{
    static char buf[PJ_MAX_HOSTNAME];
    static pj_str_t hostname;

    PJ_CHECK_STACK();

    if (hostname.ptr == NULL) {
	RHostResolver &resv = PjSymbianOS::Instance()->GetResolver(PJ_AF_INET);
	TRequestStatus reqStatus;
	THostName tmpName;

	// Return empty hostname if access point is marked as down by app.
	PJ_SYMBIAN_CHECK_CONNECTION2(&hostname);

	resv.GetHostName(tmpName, reqStatus);
	User::WaitForRequest(reqStatus);

	hostname.ptr = pj_unicode_to_ansi((const wchar_t*)tmpName.Ptr(), tmpName.Length(),
					  buf, sizeof(buf));
	hostname.slen = tmpName.Length();
    }
    return &hostname;
}

/*
 * Create new socket/endpoint for communication and returns a descriptor.
 */
PJ_DEF(pj_status_t) pj_sock_socket(int af, 
				   int type, 
				   int proto,
				   pj_sock_t *p_sock)
{
    TInt rc;

    PJ_CHECK_STACK();

    /* Sanity checks. */
    PJ_ASSERT_RETURN(p_sock!=NULL, PJ_EINVAL);

    // Return failure if access point is marked as down by app.
    PJ_SYMBIAN_CHECK_CONNECTION();
    
    /* Set proto if none is specified. */
    if (proto == 0) {
	if (type == pj_SOCK_STREAM())
	    proto = KProtocolInetTcp;
	else if (type == pj_SOCK_DGRAM())
	    proto = KProtocolInetUdp;
    }

    /* Create Symbian RSocket */
    RSocket rSock;
    if (PjSymbianOS::Instance()->Connection())
    	rc = rSock.Open(PjSymbianOS::Instance()->SocketServ(), 
    			af, type, proto,
    			*PjSymbianOS::Instance()->Connection());
    else
    	rc = rSock.Open(PjSymbianOS::Instance()->SocketServ(), 
    			af, type, proto);
        
    if (rc != KErrNone)
	return PJ_RETURN_OS_ERROR(rc);


    /* Wrap Symbian RSocket into PJLIB's CPjSocket, and return to caller */
    CPjSocket *pjSock = new CPjSocket(af, rSock);
    *p_sock = (pj_sock_t)pjSock;

    return PJ_SUCCESS;
}


/*
 * Bind socket.
 */
PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock, 
				  const pj_sockaddr_t *addr,
				  int len)
{
    pj_status_t status;
    TInt rc;

    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(sock != 0, PJ_EINVAL);
    PJ_ASSERT_RETURN(addr && len>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL);

    // Convert PJLIB's pj_sockaddr into Symbian's TInetAddr
    TInetAddr inetAddr;
    status = PjSymbianOS::pj2Addr(*(pj_sockaddr*)addr, len, inetAddr);
    if (status != PJ_SUCCESS)
    	return status;

    // Get the RSocket instance
    RSocket &rSock = ((CPjSocket*)sock)->Socket();

    // Bind
    rc = rSock.Bind(inetAddr);

    return (rc==KErrNone) ? PJ_SUCCESS : PJ_RETURN_OS_ERROR(rc);
}


/*
 * Bind socket.
 */
PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock, 
				     pj_uint32_t addr32,
				     pj_uint16_t port)
{
    pj_sockaddr_in addr;

    PJ_CHECK_STACK();

    pj_bzero(&addr, sizeof(addr));
    addr.sin_family = PJ_AF_INET;
    addr.sin_addr.s_addr = pj_htonl(addr32);
    addr.sin_port = pj_htons(port);

    return pj_sock_bind(sock, &addr, sizeof(pj_sockaddr_in));
}


/*
 * Close socket.
 */
PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock)
{
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(sock != 0, PJ_EINVAL);

    CPjSocket *pjSock = (CPjSocket*)sock;

    // This will close the socket.
    delete pjSock;

    return PJ_SUCCESS;
}

/*
 * Get remote's name.
 */
PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock,
					 pj_sockaddr_t *addr,
					 int *namelen)
{
    PJ_CHECK_STACK();
    
    PJ_ASSERT_RETURN(sock && addr && namelen && 
		     *namelen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL);

    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    // Socket must be connected.
    PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP);

    TInetAddr inetAddr;
    rSock.RemoteName(inetAddr);

    return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)addr, namelen);
}

/*
 * Get socket name.
 */
PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock,
					 pj_sockaddr_t *addr,
					 int *namelen)
{
    PJ_CHECK_STACK();
    
    PJ_ASSERT_RETURN(sock && addr && namelen && 
		     *namelen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL);

    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    TInetAddr inetAddr;
    rSock.LocalName(inetAddr);

    return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)addr, namelen);
}

/*
 * Send data
 */
PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
				 const void *buf,
				 pj_ssize_t *len,
				 unsigned flags)
{
    PJ_CHECK_STACK();
    PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);

    // Return failure if access point is marked as down by app.
    PJ_SYMBIAN_CHECK_CONNECTION();
    
    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    // send() should only be called to connected socket
    PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP);

    TPtrC8 data((const TUint8*)buf, (TInt)*len);
    TRequestStatus reqStatus;
    TSockXfrLength sentLen;

    rSock.Send(data, flags, reqStatus, sentLen);
    User::WaitForRequest(reqStatus);

    if (reqStatus.Int()==KErrNone) {
	//*len = (TInt) sentLen.Length();
	return PJ_SUCCESS;
    } else
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
}


/*
 * Send data.
 */
PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
				   const void *buf,
				   pj_ssize_t *len,
				   unsigned flags,
				   const pj_sockaddr_t *to,
				   int tolen)
{
    pj_status_t status;
    
    PJ_CHECK_STACK();
    PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);

    // Return failure if access point is marked as down by app.
    PJ_SYMBIAN_CHECK_CONNECTION();
    
    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    // Only supports AF_INET for now
    PJ_ASSERT_RETURN(tolen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL);

    TInetAddr inetAddr;
    status = PjSymbianOS::pj2Addr(*(pj_sockaddr*)to, tolen, inetAddr);
    if (status != PJ_SUCCESS)
    	return status;

    TPtrC8 data((const TUint8*)buf, (TInt)*len);
    TRequestStatus reqStatus;
    TSockXfrLength sentLen;

    rSock.SendTo(data, inetAddr, flags, reqStatus, sentLen);
    User::WaitForRequest(reqStatus);

    if (reqStatus.Int()==KErrNone) {
	//For some reason TSockXfrLength is not returning correctly!
	//*len = (TInt) sentLen.Length();
	return PJ_SUCCESS;
    } else 
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
}

/*
 * Receive data.
 */
PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
				 void *buf,
				 pj_ssize_t *len,
				 unsigned flags)
{
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL);
    PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);

    // Return failure if access point is marked as down by app.
    PJ_SYMBIAN_CHECK_CONNECTION();

    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    if (pjSock->Reader()) {
	CPjSocketReader *reader = pjSock->Reader();

	while (reader->IsActive() && !reader->HasData()) {
	    User::WaitForAnyRequest();
	}

	if (reader->HasData()) {
	    TPtr8 data((TUint8*)buf, (TInt)*len);
	    TInetAddr inetAddr;

	    reader->ReadData(data, &inetAddr);

	    *len = data.Length();
	    return PJ_SUCCESS;
	}
    }

    TRequestStatus reqStatus;
    TSockXfrLength recvLen;
    TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len);

    rSock.Recv(data, flags, reqStatus, recvLen);
    User::WaitForRequest(reqStatus);

    if (reqStatus == KErrNone) {
	//*len = (TInt)recvLen.Length();
	*len = data.Length();
	return PJ_SUCCESS;
    } else {
	*len = -1;
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
    }
}

/*
 * Receive data.
 */
PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
				     void *buf,
				     pj_ssize_t *len,
				     unsigned flags,
				     pj_sockaddr_t *from,
				     int *fromlen)
{
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(sock && buf && len && from && fromlen, PJ_EINVAL);
    PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL);
    PJ_ASSERT_RETURN(*fromlen >= (int)sizeof(pj_sockaddr_in), PJ_EINVAL);

    // Return failure if access point is marked as down by app.
    PJ_SYMBIAN_CHECK_CONNECTION();

    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    if (pjSock->Reader()) {
	CPjSocketReader *reader = pjSock->Reader();

	while (reader->IsActive() && !reader->HasData()) {
	    User::WaitForAnyRequest();
	}

	if (reader->HasData()) {
	    TPtr8 data((TUint8*)buf, (TInt)*len);
	    TInetAddr inetAddr;

	    reader->ReadData(data, &inetAddr);

	    *len = data.Length();

	    if (from && fromlen) {
		return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)from, 
					    fromlen);
	    } else {
	    	return PJ_SUCCESS;
	    }
	}
    }

    TInetAddr inetAddr;
    TRequestStatus reqStatus;
    TSockXfrLength recvLen;
    TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len);

    rSock.RecvFrom(data, inetAddr, flags, reqStatus, recvLen);
    User::WaitForRequest(reqStatus);

    if (reqStatus == KErrNone) {
	//*len = (TInt)recvLen.Length();
	*len = data.Length();
	return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)from, fromlen);
    } else {
	*len = -1;
	*fromlen = -1;
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
    }
}

/*
 * Get socket option.
 */
PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock,
					pj_uint16_t level,
					pj_uint16_t optname,
					void *optval,
					int *optlen)
{
    // Not supported for now.
    PJ_UNUSED_ARG(sock);
    PJ_UNUSED_ARG(level);
    PJ_UNUSED_ARG(optname);
    PJ_UNUSED_ARG(optval);
    PJ_UNUSED_ARG(optlen);
    return PJ_EINVALIDOP;
}

/*
 * Set socket option.
 */
PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
					pj_uint16_t level,
					pj_uint16_t optname,
					const void *optval,
					int optlen)
{
    // Not supported for now.
    PJ_UNUSED_ARG(sock);
    PJ_UNUSED_ARG(level);
    PJ_UNUSED_ARG(optname);
    PJ_UNUSED_ARG(optval);
    PJ_UNUSED_ARG(optlen);
    return PJ_EINVALIDOP;
}

/*
 * Connect socket.
 */
PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
				     const pj_sockaddr_t *addr,
				     int namelen)
{
    pj_status_t status;
    
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(sock && addr && namelen, PJ_EINVAL);
    PJ_ASSERT_RETURN(((pj_sockaddr*)addr)->addr.sa_family == PJ_AF_INET, 
		     PJ_EINVAL);

    // Return failure if access point is marked as down by app.
    PJ_SYMBIAN_CHECK_CONNECTION();
    
    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    TInetAddr inetAddr;
    TRequestStatus reqStatus;

    status = PjSymbianOS::pj2Addr(*(pj_sockaddr*)addr, namelen, inetAddr);
    if (status != PJ_SUCCESS)
    	return status;

    rSock.Connect(inetAddr, reqStatus);
    User::WaitForRequest(reqStatus);

    if (reqStatus == KErrNone) {
	pjSock->SetConnected(true);
	return PJ_SUCCESS;
    } else {
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
    }
}


/*
 * Shutdown socket.
 */
#if PJ_HAS_TCP
PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock,
				      int how)
{
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(sock, PJ_EINVAL);

    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    RSocket::TShutdown aHow;
    if (how == PJ_SD_RECEIVE)
	aHow = RSocket::EStopInput;
    else if (how == PJ_SHUT_WR)
	aHow = RSocket::EStopOutput;
    else
	aHow = RSocket::ENormal;

    TRequestStatus reqStatus;

    rSock.Shutdown(aHow, reqStatus);
    User::WaitForRequest(reqStatus);

    if (reqStatus == KErrNone) {
	return PJ_SUCCESS;
    } else {
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
    }
}

/*
 * Start listening to incoming connections.
 */
PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock,
				    int backlog)
{
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(sock && backlog, PJ_EINVAL);

    CPjSocket *pjSock = (CPjSocket*)sock;
    RSocket &rSock = pjSock->Socket();

    TInt rc = rSock.Listen((TUint)backlog);

    if (rc == KErrNone) {
	return PJ_SUCCESS;
    } else {
	return PJ_RETURN_OS_ERROR(rc);
    }
}

/*
 * Accept incoming connections
 */
PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
				    pj_sock_t *newsock,
				    pj_sockaddr_t *addr,
				    int *addrlen)
{
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(serverfd && newsock, PJ_EINVAL);

    CPjSocket *pjSock = (CPjSocket*)serverfd;
    RSocket &rSock = pjSock->Socket();

    // Create a 'blank' socket
    RSocket newSock;
    newSock.Open(PjSymbianOS::Instance()->SocketServ());

    // Call Accept()
    TRequestStatus reqStatus;

    rSock.Accept(newSock, reqStatus);
    User::WaitForRequest(reqStatus);

    if (reqStatus != KErrNone) {
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
    }

    // Create PJ socket
    CPjSocket *newPjSock = new CPjSocket(pjSock->GetAf(), newSock);
    newPjSock->SetConnected(true);

    *newsock = (pj_sock_t) newPjSock;

    if (addr && addrlen) {
	return pj_sock_getpeername(*newsock, addr, addrlen);
    }

    return PJ_SUCCESS;
}
#endif	/* PJ_HAS_TCP */


