/* $Id$ */
/* 
 * Copyright (C)2003-2006 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;

/* 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_) {
	if (sockReader_->IsActive())
	    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 TBuf<20> str16;
    static char str8[20];

    /* (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 = 16 };

    /* 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;

	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);

    /* 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);

    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);

    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);

    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);

    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);

    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 */


