plugins/consoles/rcons/server/win32/ClientSocket.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/consoles/rcons/server/win32/ClientSocket.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,156 @@
+// ClientSocket.cpp
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+// 
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+#include "Misc.h"
+#include "stdafx.h"
+#include "ClientSocket.h"
+#include "DynamicBuffer.h"
+
+const int KInitialBufferLength = 1;
+const int KNotifyReadComplete = 9000;
+
+
+CClientSocket* CClientSocket::New(CWindow& aWindow, SOCKET aSocket)
+	{
+	std::auto_ptr<CClientSocket> self(new(EThrow) CClientSocket(aWindow, aSocket));
+	self->Construct();
+	return self.release();
+	}
+
+CClientSocket::CClientSocket(CWindow& aWindow, SOCKET aSocket)
+	: CSocket(aWindow, aSocket), iReadHandler(NULL), iReadBuf(NULL), iReadLength(0)
+	{
+	}
+
+void CClientSocket::Read(char* aBuf, int aLength, MSocketReadHandler& aHandler)
+	{
+	ASSERT(iReadHandler == NULL);
+	iReadBuf = aBuf;
+	iReadLength = aLength;
+	iReadHandler = &aHandler;
+	HandleRead(FALSE);
+	}
+
+void CClientSocket::Write(char* aBuf, int aLength)
+	{
+	iWriteBuf->Add(aBuf, aLength);
+	HandleWrite();
+	}
+
+CClientSocket::~CClientSocket()
+	{
+	delete iWriteBuf;
+	}
+
+void CClientSocket::Construct()
+	{
+	CSocket::Construct();
+
+	if (WSAAsyncSelect(iSocket, iWindow.Handle(), KSocketMessage, FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
+		{
+		throw KExceptionSocketSelectFailed;
+		}
+
+	iWriteBuf = CDynamicWriteBuffer::New(KInitialBufferLength);
+	}
+
+void CClientSocket::HandleRead(bool aNotifySynchronously)
+	{
+	if (iReadLength > 0)
+		{
+		int ret = recv(iSocket, iReadBuf, iReadLength, 0);
+		if (ret == SOCKET_ERROR)
+			{
+			if (WSAGetLastError() != WSAEWOULDBLOCK)
+				{
+				HandleClosure();
+				}
+			}
+		else if (ret == 0)
+			{
+			HandleClosure();
+			}
+		else
+			{
+			iReadLength -= ret;
+			ASSERT(iReadLength >= 0);
+			if (iReadLength == 0)
+				{
+				if (aNotifySynchronously)
+					{
+					NotifyReadComplete();
+					}
+				else
+					{
+					PostMessage(iWindow.Handle(), KSocketMessage, iSocket, KNotifyReadComplete);
+					}
+				}
+			else
+				{
+				iReadBuf += ret;
+				}
+			}
+		}
+	}
+
+void CClientSocket::HandleWrite()
+	{
+	if (iWriteBuf->Length() > 0)
+		{
+		int ret = send(iSocket, iWriteBuf->Buffer(), iWriteBuf->Length(), 0);
+		if (ret == SOCKET_ERROR)
+			{
+			if (WSAGetLastError() != WSAEWOULDBLOCK)
+				{
+				HandleClosure();
+				}
+			}
+		else if (ret == 0)
+			{
+			HandleClosure();
+			}
+		else
+			{
+			iWriteBuf->Remove(ret);
+			}
+		}
+	}
+
+void CClientSocket::NotifyReadComplete()
+	{
+	ASSERT(iReadHandler);
+	MSocketReadHandler* readHandler = iReadHandler;
+	iReadBuf = NULL;
+	iReadLength = 0;
+	iReadHandler = NULL;
+	readHandler->SocketReadComplete();
+	}
+
+LRESULT CClientSocket::HandleSocketMessage(LPARAM aLParam)
+	{
+	switch (WSAGETSELECTEVENT(aLParam))
+		{
+		case FD_READ:
+			HandleRead(TRUE);
+			break;
+		case FD_WRITE:
+			HandleWrite();
+			break;
+		case KNotifyReadComplete:
+			NotifyReadComplete();
+			break;
+		default:
+			ASSERT(FALSE);
+		}
+	return 0;
+	}
+