[or-cvs] r10734: Initial IOCP loader work. (in libevent-urz/trunk: . loaders)
Urz at seul.org
Urz at seul.org
Thu Jul 5 09:53:22 UTC 2007
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
More information about the tor-commits
mailing list