#if !defined(AFX_SESSION_H__DCDE5891_2351_4322_AA99_C14B49F96DC9__INCLUDED_)
#define AFX_SESSION_H__DCDE5891_2351_4322_AA99_C14B49F96DC9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Session.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CSession window

static const int CommandQueueSize = 12;

class CGosViewDoc;



#define RECV_HEADER_SIZE 4
#define CMD_HEADER_SIZE 8

struct GosLogInfo
{
	DWORD	logLength;	// length of actual log data
	DWORD	magic;		// == GVRESP_EVENTLOG
	_int64	tLogStart;	// start time when we began collecting log (not necessarily in log)
	_int64	tLogEnd;		// stop time when we stopped collecting log (probably right after last entry)
};

enum GosViewCommand
{
	GVCMD_STARTLOG = 100,
	GVCMD_STOPLOG = 101,
	GVCMD_GETLOG = 102,
	GVCMD_GETEVENTNAME = 103,
	GVCMD_STARTLOGONCE = 104,
	GVCMD_CLOSECONNECTIONS = 105,
	GVCMD_GETFREQ = 106,
	GVCMD_HEARTBEAT = 107
};


class CSession : public CWnd
{
private:
	SOCKET m_LogSocket;
	SOCKET m_CommandSocket;
	HANDLE m_hClientThread;
	bool m_fKillThread;
	char *m_pTargetName;
	CGosViewDoc *m_pDoc;
	char m_IPAddr[20];

	struct CommandPacket
	{
		unsigned long	extLength;	// length beyond the first 8 bytes
		unsigned long	command;
	};


public:
	enum EConnectState
	{
		NotConnected,
		AwaitingConnection,
		Connected,
		ReceivingLogHeader,
		ReceivingLog,
		ProcessingLog,
		SessionError
	};

	GosLogInfo m_IncomingInfo;
	char *m_pLogReceiveAddr;
	DWORD m_nLogBytesRequired;
	unsigned long *m_pIncomingLogBuffer;

	
	static const char *ConnectStateName[7];

	LONG OnAsyncLog( WPARAM wParam, LPARAM lParam );
	void SetOwningDoc( CGosViewDoc *pDoc ) { m_pDoc = pDoc; }

private:
	EConnectState m_eState;


// Construction
public:
	CSession();

	// Commands:

	void Connect( char *name );
	void Disconnect();
	bool SendCommandData( char *pData, int size )
	{
		int rc = send( m_CommandSocket, pData, size, 0 );
		if( rc == SOCKET_ERROR )
		{
			return false;
		}
		return true;
	}
	bool SendCommand( int command, int extDataSize, char *pExtData )
	{
		CommandPacket packet;
		packet.command = command;
		packet.extLength = extDataSize;
		SendCommandData( (char *)&packet, sizeof(packet) );
		if( extDataSize )
			SendCommandData( pExtData, extDataSize );
		return m_eState != SessionError;
	}
	int ReceiveData( DWORD maxSize, char *pData )
	{
		unsigned long size;
		int bytesReceived;
		bytesReceived = recv( m_CommandSocket, (char *)&size, 4, 0 );
		if( bytesReceived == SOCKET_ERROR )
		{
			return 0;
		}
		if( bytesReceived != 4 )
		{
			return 0;
		}
		unsigned long remaining = size;
		if( size > maxSize )
		{
			return 0;
		}
		while( remaining > 0 )
		{
			bytesReceived = recv( m_CommandSocket, pData, remaining, 0 );
			if( bytesReceived == SOCKET_ERROR )
			{
				return 0;
			}
			pData += bytesReceived;
			remaining -= bytesReceived;
		}
		return size;
	}
		
	const char *StateName() { return ConnectStateName[m_eState]; }
	EConnectState State() { return m_eState; }
	bool InErrorState() { return m_eState == SessionError; }

// Attributes
public:

// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CSession)
	//}}AFX_VIRTUAL

// Implementation
public:
	virtual ~CSession();

	// Generated message map functions
protected:
	//{{AFX_MSG(CSession)
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_SESSION_H__DCDE5891_2351_4322_AA99_C14B49F96DC9__INCLUDED_)
