/* $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 
 */
#ifndef __OS_SYMBIAN_H__
#define __OS_SYMBIAN_H__

#include <pj/sock.h>
#include <pj/string.h>

#include <e32base.h>
#include <e32cmn.h>
#include <e32std.h>
#include <ES_SOCK.H>
#include <in_sock.h>
#include <CHARCONV.H>
#include <utf.h>
#include <e32cons.h>

// Forward declarations
class CPjSocketReader;

#ifndef PJ_SYMBIAN_TIMER_PRIORITY
#    define PJ_SYMBIAN_TIMER_PRIORITY	EPriorityNormal
#endif

//
// PJLIB Symbian's Socket
//
class CPjSocket
{
public:
    enum
    {
	MAX_LEN = 1500,
    };

    // Construct CPjSocket
    CPjSocket(RSocket &sock)
	: sock_(sock), connected_(false), sockReader_(NULL)
    { 
    }

    // Destroy CPjSocket
    ~CPjSocket();

    // Get the internal RSocket
    RSocket& Socket()
    {
	return sock_;
    }

    // Get socket connected flag.
    bool IsConnected() const
    {
	return connected_;
    }

    // Set socket connected flag.
    void SetConnected(bool connected)
    {
	connected_ = connected;
    }

    // Get socket reader, if any.
    // May return NULL.
    CPjSocketReader *Reader()
    {
	return sockReader_;
    }

    // Create socket reader.
    CPjSocketReader *CreateReader(unsigned max_len=CPjSocket::MAX_LEN);

    // Delete socket reader when it's not wanted.
    void DestroyReader();
    
private:
    RSocket	     sock_;	    // Must not be reference, or otherwise
				    // it may point to local variable!
    bool	     connected_;
    CPjSocketReader *sockReader_;
};


//
// Socket reader, used by select() and ioqueue abstraction
//
class CPjSocketReader : public CActive
{
public:
    // Construct.
    static CPjSocketReader *NewL(CPjSocket &sock, unsigned max_len=CPjSocket::MAX_LEN);

    // Destroy;
    ~CPjSocketReader();

    // Start asynchronous read from the socket.
    void StartRecv(void (*cb)(void *key)=NULL, 
		   void *key=NULL, 
		   TDes8 *aDesc = NULL,
		   TUint flags = 0);

    // Start asynchronous read from the socket.
    void StartRecvFrom(void (*cb)(void *key)=NULL, 
		       void *key=NULL, 
		       TDes8 *aDesc = NULL,
		       TUint flags = 0,
		       TSockAddr *fromAddr = NULL);

    // Cancel asynchronous read.
    void DoCancel();

    // Implementation: called when read has completed.
    void RunL();

    // Check if there's pending data.
    bool HasData() const
    {
	return buffer_.Length() != 0;
    }

    // Append data to aDesc, up to aDesc's maximum size.
    // If socket is datagram based, buffer_ will be clared.
    void ReadData(TDes8 &aDesc, TInetAddr *addr=NULL);

private:
    CPjSocket	   &sock_;
    bool	    isDatagram_;
    TPtr8	    buffer_;
    TInetAddr	    recvAddr_;

    void	   (*readCb_)(void *key);
    void	    *key_;

    //
    // Constructor
    //
    CPjSocketReader(CPjSocket &sock);
    void ConstructL(unsigned max_len);
};



//
// Time-out Timer Active Object
//
class CPjTimeoutTimer : public CActive
{
public:
    static CPjTimeoutTimer *NewL();
    ~CPjTimeoutTimer();

    void StartTimer(TUint miliSeconds);
    bool HasTimedOut() const;

protected:
    virtual void RunL();
    virtual void DoCancel();
    virtual TInt RunError(TInt aError);

private:
    RTimer	timer_;
    pj_bool_t	hasTimedOut_;

    CPjTimeoutTimer();
    void ConstructL();
};



//
// Symbian OS helper for PJLIB
//
class PjSymbianOS
{
public:
    //
    // Get the singleton instance of PjSymbianOS
    //
    static PjSymbianOS *Instance();

    //
    // Initialize.
    //
    TInt Initialize();

    //
    // Shutdown.
    //
    void Shutdown();


    //
    // Socket helper.
    //

    // Get RSocketServ instance to be used by all sockets.
    RSocketServ &SocketServ()
    {
	return socketServ_;
    }

    // Convert TInetAddr to pj_sockaddr_in
    static inline void Addr2pj(const TInetAddr & sym_addr,
			       pj_sockaddr_in &pj_addr)
    {
	pj_bzero(&pj_addr, sizeof(pj_sockaddr_in));
	pj_addr.sin_family = PJ_AF_INET;
	pj_addr.sin_addr.s_addr = pj_htonl(sym_addr.Address());
	pj_addr.sin_port = pj_htons((pj_uint16_t) sym_addr.Port());
    }


    // Convert pj_sockaddr_in to TInetAddr
    static inline void pj2Addr(const pj_sockaddr_in &pj_addr,
			       TInetAddr & sym_addr)
    {
	sym_addr.Init(KAfInet);
	sym_addr.SetAddress((TUint32)pj_ntohl(pj_addr.sin_addr.s_addr));
	sym_addr.SetPort(pj_ntohs(pj_addr.sin_port));
    }


    //
    // Resolver helper
    //

    // Get RHostResolver instance
    RHostResolver & GetResolver()
    {
	return hostResolver_;
    }


    //
    // Unicode Converter
    //

    // Convert to Unicode
    TInt ConvertToUnicode(TDes16 &aUnicode, const TDesC8 &aForeign);

    // Convert from Unicode
    TInt ConvertFromUnicode(TDes8 &aForeign, const TDesC16 &aUnicode);

    //
    // Get console
    //
    
    // Get console
    CConsoleBase *Console()
    {
	return console_;
    }
    
    //
    // Get select() timeout timer.
    //
    CPjTimeoutTimer *SelectTimeoutTimer()
    {
	return selectTimeoutTimer_;
    }

    //
    // Wait for any active objects to run.
    //
    void WaitForActiveObjects(TInt aPriority = CActive::EPriorityStandard)
    {
	TInt aError;
	User::WaitForAnyRequest();
	CActiveScheduler::RunIfReady(aError, aPriority);
    }

private:
    bool isSocketServInitialized_;
    RSocketServ socketServ_;

    bool isResolverInitialized_;
    RHostResolver hostResolver_;

    CConsoleBase* console_;

    CPjTimeoutTimer *selectTimeoutTimer_;

private:
    PjSymbianOS();
};


#endif	/* __OS_SYMBIAN_H__ */

