// OBEX.H
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#if !defined(__OBEX_H__)
#define __OBEX_H__

#include "e32std.h"
#include "f32file.h"
#include "es_sock.h"
#include "ir_sock.h"

#ifdef _UNICODE
const TInt KUidOBEXTransportModule = 0x10003d56;
#else
const TInt KUidOBEXTransportModule = 0x1000169c;
#endif

typedef TUint16 TObexHeaderMask;
const KObexHdrName			= 0x01;
const KObexHdrType			= 0x02;
const KObexHdrLength		= 0x04;
const KObexHdrTime			= 0x08;
const KObexHdrDescription	= 0x10;
const KObexHdrTarget		= 0x20;

const TUint8  KObexVersion           = 0x10;		// Version 1.0

const KObexObjectFieldSize = 127;
const KObexObjectDescriptionSize = 255;

// Flags used by Connect
// ...None in OBEX 1.0

// Flags used by SetPath
const KObexSetPathParent	= 0x01;

typedef TUint8 TObexOpcode;

class TObexPacket;
class CObexBaseObject : public CBase
//----------------------------------
// Describes objects for transfering between the applications through the OBEX transport.
// Objects consist of:-
//    * a number of headers (name, type, mod. date etc) possibly discerned from a source file
//    * a data part, represented by a file name (where possible, based on the object name header)
// In addition, OBEX allows for proprietry header extensions. Currently not supported but could
// be if required. Would be done either through generic Get/SetHeader functions in the 
// CObexBaseObject (object specific information) or in CObex (for session specific information)
// 
	{
friend class CObexClient;
friend class CObexServer;
public:
	virtual ~CObexBaseObject ();
	inline void SetHeaderMask (const TObexHeaderMask aHeaderMask);
	inline void SetNameL (const TDesC& aDesc);
	inline void SetTypeL (const TDesC8& aDesc);
	inline void SetLengthL (const TUint32 aLength);
	inline void SetTimeL (const TTime aTime);
	inline void SetDescriptionL (const TDesC& aDesc);
	inline void SetTargetL (const TDesC8& aDesc);
	inline TInt BytesSent ();
	inline TInt BytesReceived ();
	inline TObexHeaderMask HeaderMask ();
	IMPORT_C const TPtrC& Name ();
	IMPORT_C const TPtr8& Type ();
	IMPORT_C const TUint32 Length ();
	IMPORT_C const TTime Time ();
	IMPORT_C const TPtr& Description ();
	IMPORT_C const TPtr8& Target ();
	IMPORT_C void Reset ();
protected:
	CObexBaseObject ();
	void GuessTypeFromExtL (const TDesC& aExt);
	void ResetHeaders ();
	// Pure virtuals that all derived objects must implement
	virtual void GetData (TInt aPos, TDes8& aDes) =0;
	virtual void NewData (TInt aPos, TDes8& aDes) =0;
	virtual TInt DataSize () =0;
	virtual void ResetData () =0;
private:
	enum TProgress { EContinue,EComplete,EError };
	TInt InitSend (TObexOpcode aOpcode);
	TProgress PrepareNextSendPacket (TObexPacket& aPacket);
	TInt InitReceive ();
	TProgress ParseNextReceivePacket (TObexPacket& aPacket);
// Data
protected:
	TObexHeaderMask iHeaderMask;
	TObexHeaderMask iValidHeaders;
	TBufC<KObexObjectFieldSize> iName;	// For now. HBuf's might be nicer.
	TPtrC *iNamePtr;
	TBufC8<KObexObjectFieldSize> iType;
	TPtr8 *iTypePtr;
	TInt iLength;
	TTime iTime;
	TBufC<KObexObjectDescriptionSize> iDescription;
	TPtr *iDescriptionPtr;
	TBufC8<KObexObjectFieldSize> iTarget;
	TPtr8 *iTargetPtr;
private:
	// Members used while transfering the object
	TProgress iSendProgress;
	TObexOpcode iSendOpcode;
	TObexHeaderMask iSendHeaders;
	TInt iSendBytes;
	TProgress iRecvProgress;
	TInt iRecvBytes;
	};

class CObexFileObject : public CObexBaseObject
//--------------------------------------------
// Concrete OBEX object class. Uses a file to represent the data part of the object.
//
	{
public:
	static IMPORT_C CObexFileObject* NewL (const TDesC &aDataFile = TPtrC (NULL, 0));
	virtual IMPORT_C ~CObexFileObject ();
	IMPORT_C void InitFromFileL (const TDesC& aFile);
private:
	void ConstructL (const TDesC &aDataFile);
	void SetDataFileL (const TDesC& aDesc);
	const TPtrC& DataFile ();
	TParse* GetParseObject();
	TBool RenameFile(const TDesC& aDesC);
	void SetTempFilePath(const TDesC& aPath);
	void QueryTempFilePath(TDes& aPath);
	// From CObexBaseObject
	virtual void GetData (TInt aPos, TDes8& aDes);
	virtual void NewData (TInt aPos, TDes8& aDes);
	virtual TInt DataSize ();
	virtual void ResetData ();
// Data
private:
	RFs iFs;
	TParse iDataFile;
	TPtrC *iDataFilePtr;
	RFile iFile;
	TBuf<KObexObjectDescriptionSize> iTempFilePath;
	};

class CObexBufObject : public CObexBaseObject
//-------------------------------------------
// Concrete OBEX object class, uses a CBufBase to store the data part. The buffer is
// owned by the creator or the CObexBufObject -- they must delete both the 
// CObexBufObject and the buffer it uses.
//
	{
public:
	static IMPORT_C CObexBufObject* NewL (CBufBase* aDataBuf);
	virtual IMPORT_C ~CObexBufObject ();
	IMPORT_C TInt WriteToFile(const TPtrC& fileName);
	void SetDataBufL (CBufBase* aDataBuf);
	CBufBase* DataBuf ();
private:
	CObexBufObject ();
	void ConstructL (CBufBase* aDataBuf);
	// From CObexBaseObject
	virtual void GetData (TInt aPos, TDes8& aDes);
	virtual void NewData (TInt aPos, TDes8& aDes);
	virtual TInt DataSize ();
	virtual void ResetData ();
// Data
private:
	CBufBase* iBuf;
	};

class TObexProtocolInfo
//---------------------
	{
public:
	TBuf<60> iTransport;
	};

class TObexIrProtocolInfo : public TObexProtocolInfo
//-------------------------------------------------------
	{
public:
	TIrdaSockAddr iAddr;
	TBuf8<KIASClassNameMax> iClassName;
	TBuf8<KIASAttributeNameMax> iAttributeName;
	};

class MObexNotify
//---------------
// Provides the call back interface for anything using CObexTransport (ie CObex)
	{
public:
	virtual void Process (TObexPacket &aPacket) =0;
	virtual void Error (TInt aError) =0;
	virtual void TransportUp () =0;			// Call back to start the obex session
	virtual void TransportDown () =0;			//   "   "      stop       "	 "
	};

enum TObexResponse  
	{ 
	ERespContinue			= 0x10,
	ERespSuccess			= 0x20,
	ERespCreated			= 0x21,
	ERespAccepted			= 0x22,
	ERespBadRequest			= 0x40,
	ERespUnauthorized		= 0x41,
	ERespPaymentRequired	= 0x42,
	ERespForbidden			= 0x43,
	ERespNotFound			= 0x44,
	ERespMethodNotAllowed	= 0x45,
	ERespNotAcceptable		= 0x46,
	ERespTimedOut			= 0x48,
	ERespConflict			= 0x49,
	ERespInternalError		= 0x50,
	ERespNotImplemented		= 0x51,
	};

class TObexConnectInfo
	{
public:
	inline TObexConnectInfo ();
	inline TUint8 VersionMajor () const;
	inline TUint8 VersionMinor () const;
public:
	TUint8 iVersion;
	TUint8 iFlags;
	TBuf8<KObexObjectDescriptionSize> iWho;
	};

class CObexTransport;
class CObexSocketConnector;
class CObex : public CBase, protected MObexNotify
//-----------------------------------------------
// Provides the basic OBEX transport functionallity (sending and receiving files)
// Client and server provide the more specialied APIs for 
//     * initiation or response to puts & gets
//     * (possible) handling of more generalised 'objects' (prob. with data 
// buffered through a file).
//
	{
public:
	class TSetPathInfo
		{
	public:
		inline TSetPathInfo ();
		inline TBool Parent () const;
		TUint8 iFlags;
		TUint8 iConstants;
		TBuf<KObexObjectDescriptionSize> iName;
		TBool iNamePresent;
		};
	// Current obex connection state
	enum TConnectState 
		{ 
		EConnIdle,
		EConnTransport,
		EConnObex 
		};
	enum TOperation 
		{ 
		EOpConnect		= 0x00,
		EOpDisconnect	= 0x01,
		EOpPut			= 0x02,
		EOpGet			= 0x03,
		EOpSetPath		= 0x05,
		EOpAbort		= 0xFF,	// - abort must fit in one pkt so final bit is always set
		EOpAbortNoFBit	= 0x7F,
		EOpIdle			= 0xFE	// Not actually an obex operation. 
		};
	virtual ~CObex ();
	inline TBool IsConnected () const;
	inline TBool IsStrictPeer () const;
	inline const TObexConnectInfo& LocalInfo () const;
	inline TInt SetLocalWho (const TDesC8& aInfo); 
    inline const TObexConnectInfo& RemoteInfo () const;
	// Implementation of MObexNotify Interface
	virtual void Process (TObexPacket& aPacket);
	virtual void Error (TInt aError) ;
	virtual void TransportUp ();			// Call back to start the obex session
	virtual void TransportDown ();			//   "   "      stop       "	 "
protected:
	CObex ();
	virtual void ConstructL (TObexProtocolInfo& aObexProtocolInfoPtr);
	TBool PrepareConnectPacket (TObexPacket& aPacket);	// Should be members of TConnectInfo
	TBool ParseConnectPacket (TObexPacket& aPacket);	// Ditto.
	void NewConnectorL (TObexProtocolInfo& aObexProtocolInfoPtr);
	void DeleteConnector ();
	void NewTransportL ();
	void DeleteTransport ();
	void SetConnectState (TConnectState aNewState);
	inline TConnectState ConnectState () const;
	virtual void OnPacketReceive (TObexPacket& aPacket) =0;
	virtual void OnError (TInt aError) =0;
	virtual void OnTransportUp () =0;
	virtual void OnTransportDown () =0;
private: 												   
	TConnectState iConnectState;
protected:
	RSocketServ iSocketServ;
	RSocket iSocket;
	CObexSocketConnector* iConnector;
	CObexTransport* iTransport;
	TObexConnectInfo iLocalInfo;
	TObexConnectInfo iRemoteInfo;
	};

class CObexClient : public CObex
//------------------------------
// Client side functionality. Connection based.
// Supports ...
// Opening IrDA TTP sockets for the OBEX session. 
// Opening an OBEX session over a connected socket
// Standard OBEX operations.
// No support for OBEX 'command' (dropped from OBEX spec.)
//
	{
public:
	IMPORT_C ~CObexClient ();
	IMPORT_C static CObexClient* NewL (TObexProtocolInfo& aObexProtocolInfoPtr);
	IMPORT_C void Connect (TRequestStatus& aStatus);	
	IMPORT_C void Disconnect (TRequestStatus& aStatus);						
	IMPORT_C void Put (CObexBaseObject& aObject, TRequestStatus& aStatus);
	IMPORT_C void Get (CObexBaseObject& aObject, TRequestStatus& aStatus);		
	IMPORT_C void SetPath (TSetPathInfo& aPathInfo, TRequestStatus& aStatus);
	IMPORT_C void Abort ();					
private:
	CObexClient ();
	void ConstructL (TObexProtocolInfo& aObexProtocolInfoPtr);
	TBool AlreadyActive(TRequestStatus& aStatus);
	void ClientCommandL (TOperation aOp, TAny* aParam, TRequestStatus& aStatus);
	// Implementation of CObex Events
	virtual void OnPacketReceive (TObexPacket& aPacket);
	virtual void OnError (TInt aError);
	virtual void OnTransportUp ();
	virtual void OnTransportDown ();
	void SetRequest (TRequestStatus& aStatus, TOperation aOperation);
	void CompleteRequest (const TInt aCompletion);
// Data
private: 
	TRequestStatus* iPendingRequest;
	TOperation iCurrentOperation;
	CObexBaseObject* iCurrentObject;
	};

class MObexServerNotify;
class CObexServer : public CObex
//------------------------------
	{
public:
	IMPORT_C static CObexServer* NewL (TObexProtocolInfo& aObexProtocolInfoPtr);
	IMPORT_C ~CObexServer ();
	IMPORT_C TInt Start (MObexServerNotify* aOwner);
	IMPORT_C void Stop ();
	inline TBool IsStarted ();
	inline TOperation CurrentOperation () const;
private:
	CObexServer ();
	void ConstructL (TObexProtocolInfo& aObexProtocolInfoPtr);
	TInt AcceptConnection ();
	// Implementation of CObex Events
	virtual void OnPacketReceive (TObexPacket& aPacket);
	virtual void OnError (TInt aError);
	virtual void OnTransportUp ();
	virtual void OnTransportDown ();
private:
	MObexServerNotify* iOwner;
	TBool iEnabled;
	TOperation iCurrentOperation;
	CObexBaseObject* iTransObject;
	CObexBaseObject* iSpecObject;
	TBool iSpecDone;
	};

class MObexServerNotify
//---------------------
	{
friend class CObexServer;

private:
	virtual void ErrorIndication (TInt aError) =0;
	virtual void TransportUpIndication () =0;
	virtual void TransportDownIndication () =0;
	virtual TInt ObexConnectIndication  (const TObexConnectInfo& aRemoteInfo, const TDesC8& aInfo) =0;
	virtual void ObexDisconnectIndication (const TDesC8& aInfo) =0;
	virtual CObexBufObject* PutRequestIndication () =0;
	virtual TInt PutPacketIndication () =0;
	virtual void PutCompleteIndication () =0;
	virtual CObexBufObject* GetRequestIndication (CObexBaseObject *aRequiredObject) =0;
	virtual TInt GetPacketIndication () =0;
	virtual void GetCompleteIndication () =0;
	virtual TInt SetPathIndication (const CObex::TSetPathInfo& aPathInfo, const TDesC8& aInfo) =0;
	virtual void AbortIndication () =0;
	};

#include "obex.inl"

#endif // __OBEX_H__
