#include "Protocol.h"

ULONG_PTR	__stdcall ServerSideProc(LPCONNECTION lpCon, UINT uMsg, UINT_PTR uParamA, ULONG_PTR uParamB)
{	
#ifdef _DEBUG
	LPSERVERDATA lpSd = (LPSERVERDATA)GetProtocolDataPtr(lpCon);
#endif
	switch(uMsg)
	{
	case MSG_CREATE:
		{
			LPRWLOCK lpRwl = &lpSd->lpServer->lpFgs->rwl;

			InitializeBuffer(&lpSd->bufMain);
			InitializeBuffer(&lpSd->bufRecv);

			lpSd->uState = SCS_SEND_DATA;
			ReaderEnter(lpRwl);
			WVFCopy(&lpSd->wvfMain, &lpSd->lpServer->lpFgs->wvfFrame);
			ReaderLeave(lpRwl);
			
			WVFHeaderPack(&lpSd->wvfMain, lpSd->bPackedHeader, 4*sizeof(INT));			
			AssignPtr(&lpSd->bufMain, lpSd->bPackedHeader, 4*sizeof(INT));
			SendBuffer(lpCon, &lpSd->bufMain, 1024);

			AllocBuffer(&lpSd->bufRecv, 1024);
			RecvBuffer(lpCon, &lpSd->bufRecv);			
		}
		break;

	case MSG_COMPLETION:
		if(uParamB == (ULONG_PTR)&lpSd->bufMain)
		{
			switch(lpSd->uState)
			{
			case SCS_SEND_HEADER:
				lpSd->uState = SCS_SEND_DATA;
				ReaderEnter(&lpSd->lpServer->lpFgs->rwl);
				WVFCopy(&lpSd->wvfMain, &lpSd->lpServer->lpFgs->wvfFrame);
				ReaderLeave(&lpSd->lpServer->lpFgs->rwl);
			
				WVFHeaderPack(&lpSd->wvfMain, lpSd->bPackedHeader, 4*sizeof(INT));			
				AssignPtr(&lpSd->bufMain, lpSd->bPackedHeader, 4*sizeof(INT));
				SendBuffer(lpCon, &lpSd->bufMain, 1024);
				break;

			case SCS_SEND_DATA:
				lpSd->uState = SCS_SEND_HEADER;

				AssignPtr(&lpSd->bufMain, lpSd->wvfMain.lpFrame, lpSd->wvfMain.uFrameSize);
				SendBuffer(lpCon, &lpSd->bufMain, 1024);
				break;
			}
		}
		else if(uParamB == (ULONG_PTR)&lpSd->bufRecv)
			RecvBuffer(lpCon, &lpSd->bufRecv);
		break;

	case MSG_DESTROY:
		WVFFree(&lpSd->wvfMain);
		FreeBuffer(&lpSd->bufRecv);
		RemoveItem(lpSd->lpServer->liClients, lpCon);
		break;
	}
	return TRUE;
}

ULONG_PTR	__stdcall ClientSideProc(LPCONNECTION lpCon, UINT uMsg, UINT_PTR uParamA, ULONG_PTR uParamB)
{
#ifdef _DEBUG
	LPCLIENTDATA lpCd = (LPCLIENTDATA)GetProtocolDataPtr(lpCon);
#endif
	switch(uMsg)
	{
	case MSG_CREATE:
		{
			InitializeBuffer(&lpCd->bufRecv);

			lpCd->uState = CCS_RECV_DATA;
			AssignPtr(&lpCd->bufRecv, lpCd->bPackedHeader, 4*sizeof(INT));
			RecvBuffer(lpCon, &lpCd->bufRecv);
		}
		break;

	case MSG_COMPLETION:
		if(uParamB == (ULONG_PTR)&lpCd->bufRecv)
		{
			switch(lpCd->uState)
			{
			case CCS_RECV_HEADER:
				//LeaveCriticalSection(&lpCon->cs);
				SendCTMessage(g_lpCtwmd, lpCd->hWndVideo, VWM_SETFRAME, 0, (LPARAM)&lpCd->wvfMain);
				//EnterCriticalSection(&lpCon->cs);

				lpCd->uState = CCS_RECV_DATA;
				AssignPtr(&lpCd->bufRecv, lpCd->bPackedHeader, 4*sizeof(INT));
				RecvBuffer(lpCon, &lpCd->bufRecv);
				break;

			case CCS_RECV_DATA:
				lpCd->uState = CCS_RECV_HEADER;
				WVFHeaderUnpack(&lpCd->wvfMain, lpCd->bPackedHeader, 4*sizeof(INT));
				WVFAlloc(&lpCd->wvfMain, lpCd->wvfMain.uFrameSize);

				AssignPtr(&lpCd->bufRecv, lpCd->wvfMain.lpFrame, lpCd->wvfMain.uFrameSize);
				RecvBuffer(lpCon, &lpCd->bufRecv);
				break;			
			}
		}		
		break;

	case MSG_DESTROY:	
		SendCTMessage(g_lpCtwmd, lpCd->hWndClient, WVM_DESTROYME, 0, 0);
		WVFFree(&lpCd->wvfMain);		
		break;
	}
	return TRUE;
}