[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r10734: Initial IOCP loader work. (in libevent-urz/trunk: . loaders)



Author: Urz
Date: 2007-07-05 05:53:22 -0400 (Thu, 05 Jul 2007)
New Revision: 10734

Added:
   libevent-urz/trunk/loaders/
   libevent-urz/trunk/loaders/IOCPloader.c
   libevent-urz/trunk/loaders/IOCPloader.h
Log:
Initial IOCP loader work.

Added: libevent-urz/trunk/loaders/IOCPloader.c
===================================================================
--- libevent-urz/trunk/loaders/IOCPloader.c	                        (rev 0)
+++ libevent-urz/trunk/loaders/IOCPloader.c	2007-07-05 09:53:22 UTC (rev 10734)
@@ -0,0 +1,297 @@
+// Unanswered Questions:
+// How to handle connection establishment?
+
+#include "../event.h"
+#include "IOCPloader.h"
+
+#define NO_WORKERS 2
+
+HANDLE IOCP;
+HANDLE Threads[NO_WORKERS];
+
+/*
+ * Status :
+ * This is going a lot slower than expected. Firstly, every example I have seen so far
+ * uses an IOCP but *not* overlapped I/O. For that I am totally in the dark and it raises
+ * serious questions about how it should be done. (for example, how do I get the connection struct
+ * to the ReadComplete callback?)
+ * Aside from this I have been both sick (flu :( ) and busy with other, non-Tor things.
+ * Combined this leaves this in it's current sorry state. I am starting to think that
+ * talking to someone like `Orum who knows IOCP & Overlapped I/O will be neccessary.
+ *
+ * I will still try to make my 9th July deadline but I am doubtful it is going to happen, 
+ * especially since I am going to be afk for the next couple of days (other commitments).
+ * I should be available to chat on your saturday / sunday nights if you want to talk.
+ *
+ * P.S. Sorry about not commiting for a while, I just forgot.
+ */
+
+/*
+When adding new handles to the IO Completion port, the Completion Key
+_MUST_ by a pointer to a connection (see IOCPloader.h) with all fields initialized.
+*/
+
+DWORD WINAPI IOCPLoaderMain(LPVOID nodata) {
+    SOCKET workaround;
+    int i;
+    
+    // Set up the IO Completion Port.
+    // IOCPS.cpp:155 bRet&=CreateCompletionPort();
+    // According to http://msdn2.microsoft.com/en-us/library/aa363862.aspx
+    // The first parameter to CreateIoCompletionPort can be NULL, however
+    // according to the code example I am working from, NT 3.5 is unhappy
+    // about this, hence the workaround SOCKET.
+    workaround = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+    IOCP = CreateIoCompletionPort((HANDLE)workaround, NULL, 0, 0);
+    closesocket(workaround);
+    // Create the worker threads
+    // IOCPS.cpp:171 bRet&=SetupIOWorkers();
+    // The example code uses AfxBeginThread, but this appears to be
+    // a MFC wrapper around CreateThread.
+    for(i = 0; i < NO_WORKERS; i++) {
+        Threads[i] = CreateThread(NULL, 0, &iocp_worker_thread, NULL, 0, NULL);
+    }
+    // This concludes the code modified from the Startup function()
+
+}
+
+UINT iocp_worker_thread(LPVOID pParam) {
+    // From IOWorkerThreadProc
+    LPOVERLAPPED CompletedOverlapped;
+    // See http://msdn2.microsoft.com/en-us/library/ms684342.aspx
+    DWORD CompleteSize;
+    ULONG *CompletionKey;
+    BOOL GQCSRet
+    connection *Conn;
+    UINT WSARecvRet;
+    ULONG WSARecvFlags = MSG_WAITALL;
+
+    while(1) {
+        GQCSRet = GetQueuedCompletionStatus(
+            IOCP, // The IOCP to get statuses from
+            &CompleteSize, // "... receives the number of bytes transferred 
+                            //during an I/O operation that has completed."
+            &CompletionKey,
+            // A pointer to a variable that receives the completion key value 
+            // associated with the file handle whose I/O operation has completed.
+            // In IOCPS.cpp : (LPDWORD) &lpClientContext,
+            &CompletedOverlapped
+            // A pointer to a variable that receives the address of the OVERLAPPED
+            // structure that was specified when the completed I/O operation was started.
+            INFINITE
+            // The number of milliseconds that the caller is willing to wait for a
+            // completion packet to appear at the completion port.
+            );
+        if(!GQCSRet) {
+            printf("GetQueuedCompletionStatus error %d\n", GetLastError());
+            continue;
+        }
+        
+        // The completion key is the associated sa_bufferevent.
+        Conn = (connection *) CompletionKey;
+        
+        // From ProcessIOMessage
+        
+        // http://msdn2.microsoft.com/en-us/library/ms741688.aspx
+        WSARecvRet = WSARecv(
+            Conn->sock,
+            // The socket to recieve from
+            Conn->netbuf,
+            // Pointer to an 'array' of WSABUFs.
+            1,
+            // The 'array' is of size 1
+            NULL, 
+            // This parameter would recieve the size in bytes of the
+            // read. However, because we are using overlapped, it doesn't.
+            &WSARecvFlags,
+            // Flags which control the operation of WSARecv. I belive MSG_WAITALL
+            // is the one we want.
+            &Conn->ol, 
+            // The overlapped structure for the event.
+			&ReadComplete);
+
+    }
+}
+
+void CALLBACK ReadComplete(IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags) {
+}
+
+/* 
+Note : Below code copied from the IOCP example at http://www.codeproject.com/internet/YourOwnSecureProtocol.asp
+The licence would seem to let me copy this here. This code will never appear in any compliable version of this
+file and is solely here for reference purposes, to understand IOCP.
+*/
+
+
+// /* UINT IOCPS::IOWorkerThreadProc(LPVOID pParam)
+// {
+	// IOCPS* pThis = reinterpret_cast<IOCPS*>(pParam);
+	// if ( pThis )
+	// {
+		// DWORD dwIoSize;
+		// ClientContext* lpClientContext;
+		// CIOCPBuffer *pOverlapBuff;
+		// bool bError=false;
+		// HANDLE hCompletionPort = pThis->m_hCompletionPort;
+		// LPOVERLAPPED lpOverlapped;
+
+		// while ( !bError )
+		// {
+			// pOverlapBuff=NULL;
+			// lpClientContext=NULL;
+			//Get a completed IO request.
+			// BOOL bIORet = GetQueuedCompletionStatus(
+				// hCompletionPort,
+				// &dwIoSize,
+				// (LPDWORD) &lpClientContext,
+				// &lpOverlapped, INFINITE);
+			//Simulate workload (for debugging, to find possible reordering)
+			//Sleep(20);
+
+
+
+			//If Something whent wrong..
+			// if (!bIORet)  
+			// {
+                // Snip Error Handling
+            // }
+
+
+
+			// if(bIORet && lpOverlapped && lpClientContext) 
+			// {
+            // Urz:
+            // This gets the CIOCPBuffer that contains the OVERLAPPED structure we just got returned.
+            // Not sure why they didn't just use the completion key, but meh
+            // update: That's because they were using the completion key for the Client context struct.
+            // /Urz
+				// pOverlapBuff=CONTAINING_RECORD(lpOverlapped, CIOCPBuffer, m_ol);
+				// if(pOverlapBuff!=NULL)
+					// pThis->ProcessIOMessage(pOverlapBuff, lpClientContext, dwIoSize);
+			// }	
+
+			// if(lpClientContext==NULL&&pOverlapBuff==NULL&&pThis->m_bShutDown)
+			// {
+				// TRACE("lpClientContext==NULL \r\n"); 
+				// bError=true;
+			// }
+
+
+			//pThis->ReleaseBuffer(pOverlapBuff);// from previous call
+
+		// } 
+
+	// }
+
+	// TRACE("IOWorker Died!\r\n");
+	// return 0xdead;
+// } */
+
+/* void IOCPS::ProcessIOMessage(CIOCPBuffer *pOverlapBuff, ClientContext *pContext, DWORD dwSize)
+{
+
+	if(pOverlapBuff==NULL)
+		return;
+
+	//	Sleep(rand()%50);
+	switch (pOverlapBuff->GetOperation())
+	{
+
+	case IOInitialize :
+		OnInitialize(pContext,dwSize,pOverlapBuff);
+		break;
+
+	case IORead :
+		OnRead(pContext,pOverlapBuff);
+		break;	
+
+
+	case IOReadCompleted :
+		OnReadCompleted(pContext,dwSize,pOverlapBuff);
+		break;
+
+
+	case IOWrite :
+		OnWrite(pContext,dwSize,pOverlapBuff);
+		break;
+
+	case IOWriteCompleted :
+		OnWriteCompleted(pContext,dwSize,pOverlapBuff);
+		break;
+
+	case IOZeroByteRead : //  Workaround the the WSAENOBUFS error problem..See OnZeroByteRead. 
+		OnZeroByteRead(pContext,pOverlapBuff);
+		break;
+
+	case IOZeroReadCompleted : //  Workaround the the WSAENOBUFS error problem.. 
+		OnZeroByteReadCompleted(pContext,dwSize,pOverlapBuff);
+		break;
+#if defined TRANSFERFILEFUNCTIONALITY
+	case IOTransmitFileCompleted : //  Workaround the the WSAENOBUFS error problem.. 
+		OnTransmitFileCompleted(pContext,pOverlapBuff);
+		break;
+#endif
+
+	case IOPostedPackage : 
+		OnPostedPackage(pContext,pOverlapBuff);
+		break;
+
+
+	default:
+		ReleaseBuffer(pOverlapBuff);
+		break;
+
+	} 
+} */
+
+/*
+void IOCPS::OnRead(ClientContext *pContext,CIOCPBuffer *pOverlapBuff)
+{
+	// issue a read request 
+	if(pContext&&!m_bShutDown)
+	{
+		if(pOverlapBuff==NULL)
+		{
+			// Buffer allocation / error checking
+		}
+		if(pOverlapBuff!=NULL)
+		{
+			pOverlapBuff->SetOperation(IOReadCompleted);
+			pOverlapBuff->SetupRead();
+			if(m_bReadInOrder)
+				MakeOrderdRead(pContext,pOverlapBuff);
+			else
+			{
+				DWORD dwIoSize=0;
+				ULONG			ulFlags = MSG_PARTIAL;
+				UINT nRetVal = WSARecv(pContext->m_Socket, 
+					pOverlapBuff->GetWSABuffer(),
+					1,
+					&dwIoSize, 
+					&ulFlags,
+					&pOverlapBuff->m_ol, 
+					NULL);
+				if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) 
+				{
+					if(WSAGetLastError()!=WSAENOTSOCK)
+					{
+#ifndef _DEBUG
+						// Remove Unnecessary disconnect messages in release mode.. 
+						if(WSAGetLastError()!=WSAECONNRESET&&WSAGetLastError()!=WSAECONNABORTED)
+#endif
+						{
+							CString msg;
+							msg.Format("Disconnect in Onread Possible Socket Error: %s",ErrorCode2Text(WSAGetLastError()));
+							AppendLog(msg);
+						}
+					}
+					ReleaseBuffer(pOverlapBuff);
+					TRACE(">OnRead(%x)\r\n",pContext);
+					DisconnectClient(pContext);
+					ReleaseClientContext(pContext);
+				}
+			}
+		}
+	}
+}
+*/
\ No newline at end of file

Added: libevent-urz/trunk/loaders/IOCPloader.h
===================================================================
--- libevent-urz/trunk/loaders/IOCPloader.h	                        (rev 0)
+++ libevent-urz/trunk/loaders/IOCPloader.h	2007-07-05 09:53:22 UTC (rev 10734)
@@ -0,0 +1,11 @@
+
+
+DWORD WINAPI IOCPLoaderMain(LPVOID);
+void CALLBACK ReadComplete(IN DWORD dwError, IN DWORD cbTransferred, IN LPWSAOVERLAPPED lpOverlapped, IN DWORD dwFlags);
+
+typedef struct {
+    sa_bufferevent *localbuf;
+    WSABUF *netbuf;
+    SOCKET sock;
+    OVERLAPPED *ol;
+} connection;
\ No newline at end of file