// NetObj.h : CArchive-able abstract objects
//

#ifndef __NETOBJ_H_
#define __NETOBJ_H_

//NetObject errors
#define NET_ERRNONE	       11000
#define NET_ERRMEMORY	   11001
#define NET_ERRDROP		   11002
#define NET_ERRTRANSPORT   11003
#define NET_ERRFILE		   11004
#define NET_ERRARCHIVE	   11005
#define NET_ERROBJECT	   11006

//NetArchive buffer size
#define NET_BUFSIZE        1024*4

class NetTransport;

class CNetObject : public CObject
{
	DECLARE_SERIAL(CNetObject)

	NetTransport* m_pTransport;

	static CCriticalSection m_del;

public:
	CNetObject* use()
	{
		m_del.Lock();
		InterlockedIncrement(&m_nAutoDelete);
		m_del.Unlock();
		return this;
	}

	BOOL release()
	{
		BOOL del = FALSE;

		m_del.Lock();
		if (!InterlockedDecrement(&m_nAutoDelete))
		{
			delete this;
			del = TRUE;
		}
		m_del.Unlock();

		return del;
	}


	long m_nAutoDelete;

	CNetObject() { m_nAutoDelete = 1; }
	virtual ~CNetObject() {}

	virtual void Serialize(CArchive& ar);

	NetTransport* GetTransport() { return m_pTransport; }

	CString GetTransportId();

	virtual BOOL OnSend();
	virtual void OnReceive(NetTransport* transport);
};


class CNetArchive : public CArchive
{
public:
	CNetArchive(CFile *pFile, UINT nMode, int nBufSize = NET_BUFSIZE)
		: CArchive(pFile, nMode, nBufSize)  {};

	void Clear();
};


class CNetFile : public CFile
{
	DECLARE_DYNAMIC(CNetFile)

public:
//Constructors
	CNetFile();
	virtual ~CNetFile();

//Implementation
public:

#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif
	
	//supported CFile APIs
	virtual UINT Read(void* lpBuf, UINT nCount);
	virtual void Write(const void* lpBuf, UINT nCount);
	virtual void Close();

	//unsupported CFile APIs
	virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL);
	virtual CFile* Duplicate() const;
	virtual DWORD GetPosition() const;
	virtual LONG Seek(LONG lOff, UINT nFrom);
	virtual void SetLength(DWORD dwNewLen);
	virtual DWORD GetLength() const;
	virtual void LockRange(DWORD dwPos, DWORD dwCount);
	virtual void UnlockRange(DWORD dwPos, DWORD dwCount);
	virtual void Flush();
	virtual void Abort();
};

class Sender
{
	long use_count;
	static CCriticalSection m_del;
public:
	Sender() {use_count=1;}
	virtual BOOL Send(CNetObject*) { return FALSE; }
	virtual void Delete() { delete this; }

	Sender* Use()
	{
		m_del.Lock();
		InterlockedIncrement(&use_count);
		m_del.Unlock();
		return this;
	}

	BOOL Release()
	{
		BOOL del = FALSE;

		m_del.Lock();
		if (!InterlockedDecrement(&use_count))
		{
			Delete();
			del = TRUE;
		}
		m_del.Unlock();

		return del;
	}
};

class Receiver
{
	long use_count;
	static CCriticalSection m_del;
public:
	Receiver() { use_count=1; }
	virtual ~Receiver() {}
	virtual void OnReceive(CNetObject*) {}
	virtual void OnConnect() {}
	virtual void OnDisconnect() {}
	virtual BOOL IsDisconnect(CNetObject*) { return FALSE; }

	Receiver* UseR()
	{
		m_del.Lock();
		InterlockedIncrement(&use_count);
		m_del.Unlock();
		return this;
	}

	BOOL ReleaseR()
	{
		BOOL del = FALSE;

		m_del.Lock();
		if (!InterlockedDecrement(&use_count))
		{
			delete this;
			del = TRUE;
		}
		m_del.Unlock();

		return del;
	}
};

class NetTransport : public Sender
{
public:
	BOOL m_bOldVersion;
	BOOL m_bTerminated;

	CCriticalSection m_close_sec;
	CCriticalSection m_archin_sec;
	CCriticalSection m_archout_sec;

	NetTransport();
	virtual ~NetTransport();

	virtual void Clear();
	virtual void Close(BOOL term);
	virtual void Term();
	virtual void OnError(int nType);

	virtual CString GetTransportId() { return CString(); }
	virtual BOOL GetMyAddress(CString& sAddress, UINT& rPort) { return FALSE; }
	virtual BOOL GetPeerAddress(CString& sAddress, UINT& rPort) { return FALSE; }

	BOOL IsValid() { return m_pArchiveOut && m_pArchiveIn; }

	BOOL Open(CFile* pFile);
	virtual BOOL Send(CNetObject* pNObj);
	BOOL Receive();

	Receiver* m_receiver;

protected:
	void OnArchiveError(int nCause);
	void OnFileError(int nCause);

protected:
	CNetArchive*  m_pArchiveIn;
	CNetArchive*  m_pArchiveOut;
};


#endif  //__NETOBJ_H_
