/*++ Copyright (c) 1992 Microsoft Corporation Module Name: tlser.c Abstract: This module contains the code for the serial transport layer. Author: Wesley Witt (wesw) 25-Nov-93 Environment: Win32 User --*/ #include #include #include #include "defs.h" #include "od.h" #include "dbgver.h" #include "xport.h" #include "tlser.h" #define SIZE_OF_QUEUE 100 extern CRITICAL_SECTION csExpecting; BOOL FVerbose = FALSE; HANDLE HReadThread; BOOL FDMSide = FALSE; BOOL fConnected; static OVERLAPPED OverlappedRead; static OVERLAPPED OverlappedWrite; struct { char * lpb; int cb; } RgQueue[SIZE_OF_QUEUE]; int IQueueFront = 0; int IQueueBack = 0; CRITICAL_SECTION CsQueue = {0}; CRITICAL_SECTION CsSerial = {0}; HANDLE HQueueEvent; HANDLE HCallbackThread; HANDLE TlComPort; DWORD TlBaudRate; CHAR ClientId[MAX_PATH]; REPLY RgReplys[SIZE_OF_REPLYS]; CRITICAL_SECTION CsReplys; static CRITICAL_SECTION CsNull; int IReplys; static VOID DestroyCriticalSection(CRITICAL_SECTION *); char * SzTypes(unsigned int i) { static char rgch[30]; switch (i) { case mtypeAsync: sprintf(rgch, "mtypeAsync"); break; case mtypeAsyncMulti: sprintf(rgch, "mtypeAsyncMulti"); break; case mtypeSync: sprintf(rgch, "mtypeSync"); break; case mtypeSyncMulti: sprintf(rgch, "mtypeSyncMulti"); break; case mtypeReply: sprintf(rgch, "mtypeReply"); break; case mtypeReplyMulti: sprintf(rgch, "mtypeReplyMulti"); break; case mtypeDisconnect: sprintf(rgch, "mtypeDisconnect"); break; case mtypeVersionRequest: sprintf(rgch, "mtypeVersionRequest"); break; case mtypeVersionReply: sprintf(rgch, "mtypeVersionReply"); break; case mtypeTransportIsDead: sprintf(rgch, "mtypeTransportIsDead"); break; default: sprintf(rgch, "Type %x", i); break; } return rgch; } #define TL_ERROR_LOGGING 1 #ifdef TL_ERROR_LOGGING typedef struct { DWORD ty; DWORD ec; DWORD cb; DWORD ln; DWORD td; LPDWORD ob; LPDWORD p; } ERRLOG; #define LOGIT(x,y,z,q) {el[ei].ty=x;el[ei].ec=y;el[ei].cb=z;el[ei].ln=__LINE__; \ el[ei].td=GetCurrentThreadId(); \ el[ei].ob=(LPDWORD)q; \ el[ei].p=(LPDWORD)malloc(z);memcpy(el[ei].p,q,z);ei++; \ if (ei==99) ei=0;} #define LGREAD 1 #define LGWRITE 2 ERRLOG el[100]; DWORD ei=0; #if DBG void printel( void ) { DWORD i; for (i=0; irgchData; while (TRUE) { // // Read the next packet item from the network // ZeroMemory( (LPVOID)pnlblk, bufSize ); // // read the block header // BytesRead = TlReadTransport((LPVOID)pnlblk, sizeof(NLBLK)); if (BytesRead <= 0) { Sleep( 50 ); continue; } if (BytesRead != sizeof(NLBLK)) { assert(FALSE); Sleep( 50 ); continue; } if (pnlblk->cchMessage) { // // read the data // BytesRead = TlReadTransport((LPVOID)pnlblk->rgchData, pnlblk->cchMessage); if (BytesRead <= 0) { Sleep( 50 ); continue; } if ( BytesRead != (DWORD)pnlblk->cchMessage ) { assert(FALSE); Sleep ( 50 ); continue; } cb = pnlblk->cchMessage + sizeof(NLBLK); } else { cb = sizeof(NLBLK); } // // Print a message about this packet type. // DEBUG_OUT2("READER: %s %d\n", SzTypes(pnlblk->mtypeBlk), cb); #if DBG //DebugPrint( "PACKET: %02x, %d %ld\n", pnlblk->mtypeBlk, pnlblk->cchMessage, BytesRead ); #endif if ((pnlblk->mtypeBlk == mtypeVersionReply) || (pnlblk->mtypeBlk == mtypeReply)) { EnterCriticalSection(&CsReplys); i = IReplys - 1; if (i != -1) { cb = min(pnlblk->cchMessage, RgReplys[i].cbBuffer); memcpy(RgReplys[i].lpb, pnlblk->rgchData, cb); RgReplys[i].cbRet = cb; SetEvent(RgReplys[i].hEvent); } LeaveCriticalSection(&CsReplys); continue; } if (pnlblk->mtypeBlk == mtypeReplyMulti) { EnterCriticalSection( &CsReplys ); i = IReplys - 1; if (i != -1) { cb2 = pMpacket->packetNum * MAX_INTERNAL_PACKET; cb = pnlblk->cchMessage - sizeof(MPACKET); cb = min( cb + cb2, (DWORD)RgReplys[i].cbBuffer ); if (cb > cb2) { memcpy( RgReplys[i].lpb + cb2, pMpacket->rgchData, cb - cb2 ); RgReplys[i].cbRet = cb; } if (pMpacket->packetNum + 1 == pMpacket->packetCount) { SetEvent( RgReplys[i].hEvent ); } } LeaveCriticalSection( &CsReplys ); continue; } lpb = malloc( cb ); memcpy( lpb, pnlblk, cb ); EnterCriticalSection( &CsQueue ); while ((IQueueFront + 1) % SIZE_OF_QUEUE == IQueueBack) { LeaveCriticalSection( &CsQueue ); Sleep(100); EnterCriticalSection( &CsQueue ); } RgQueue[IQueueFront].lpb = lpb; RgQueue[IQueueFront].cb = cb; IQueueFront = (IQueueFront + 1) % SIZE_OF_QUEUE; SetEvent(HQueueEvent); LeaveCriticalSection( &CsQueue ); } return 0; } DWORD CallbackThread( LPVOID lpvArg ) { LPSTR lpb; int cb; while (TRUE) { EnterCriticalSection( &CsQueue ); if (IQueueFront == IQueueBack) { ResetEvent( HQueueEvent); LeaveCriticalSection( &CsQueue ); WaitForSingleObject( HQueueEvent, INFINITE ); EnterCriticalSection( &CsQueue ); } lpb = RgQueue[IQueueBack].lpb; cb = RgQueue[IQueueBack].cb; RgQueue[IQueueBack].lpb = NULL; RgQueue[IQueueBack].cb = 0; IQueueBack = (IQueueBack + 1) % SIZE_OF_QUEUE; LeaveCriticalSection( &CsQueue ); if (!CallBack((PNLBLK) lpb, cb)) { if (!FDMSide) { return 0; } } free(lpb); } return (DWORD) -1; } static VOID DestroyCriticalSection( CRITICAL_SECTION *csItem ) { if (csItem && memcmp(csItem, &CsNull, sizeof(CsNull))) { DeleteCriticalSection(csItem); *csItem = CsNull; } }