/////////////////////////////////////////////////////////////////////////// // // // Copyright (c) 1996, 1997 Microsoft Corporation // // // Module Name: // recv.c // // Abstract: // // // Author: // // P Porzuczek // // Environment: // // Revision History: // // ////////////////////////////////////////////////////////////////////////////// #include #include #include #include "slip.h" #include "main.h" #include "recv.h" ////////////////////////////////////////////////////////////////////////////// // // Init 802.3 header template // Header802_3 h802_3Template = { {0x01, 0x00, 0x5e, 0, 0, 0} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} , {0x08, 0x00} }; #if DBG UCHAR MyBuffer [1600] = {0}; UCHAR TestBuffer [] = { 0xC0, 0xC0, 0x00, 0xC7, 0xD3, 0x97, 0x00, 0x00, 0x5E, 0x56, 0x23, 0x11, 0x07, 0x00, 0x00, 0x00, 0x2C, 0x01, 0x00, 0x00, 0xAA, 0x58, 0x00, 0x00, 0x3D, 0xC5, 0x00, 0x00, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0xDC, 0xA2, 0x3B, 0x82, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0xE9, 0xCE, 0xFA, 0x7D, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x44, 0x33, 0x22, 0x11, 0x53, 0x60, 0xBB, 0x03, 0xC0 }; ////////////////////////////////////////////////////////////////////////////// VOID DumpData ( PUCHAR pData, ULONG ulSize ) ////////////////////////////////////////////////////////////////////////////// { ULONG ulCount; ULONG ul; UCHAR uc; DbgPrint("Dump - Data: %x, Size: %x\n", pData, ulSize); while (ulSize) { ulCount = 16 < ulSize ? 16 : ulSize; for (ul = 0; ul < ulCount; ul++) { uc = *pData; DbgPrint("%02X ", uc); ulSize -= 1; pData += 1; } DbgPrint("\n"); } if(TestDebugFlag & TEST_DBG_ASSERT) { DEBUG_BREAKPOINT(); } } /////////////////////////////////////////////////////////////////////////////////////// VOID DumpNabStream ( PNAB_STREAM pNabStream ) /////////////////////////////////////////////////////////////////////////////////////// { TEST_DEBUG (TEST_DBG_NAB, ("pszBuffer......: %08X\n", pNabStream->pszBuffer)); TEST_DEBUG (TEST_DBG_NAB, ("ulcbSize.......: %08X\n", pNabStream->ulcbSize)); TEST_DEBUG (TEST_DBG_NAB, ("ulOffset.......: %08X\n", pNabStream->ulOffset)); TEST_DEBUG (TEST_DBG_NAB, ("ulMpegCrc......: %08X\n", pNabStream->ulMpegCrc)); TEST_DEBUG (TEST_DBG_NAB, ("ulCrcBytesIndex: %08X\n", pNabStream->ulCrcBytesIndex)); TEST_DEBUG (TEST_DBG_NAB, ("ulLastCrcBytes.: %08X\n", pNabStream->ulLastCrcBytes)); TEST_DEBUG (TEST_DBG_NAB, ("ulIPStreamIndex: %08X\n", pNabStream->ulIPStreamIndex)); return; } ULONG Checksum ( char * psz, ULONG ulSize ) ////////////////////////////////////////////////////////////////////////////// { ULONG Checksum = 0; ULONG uli = 0; if(ulSize < 0x41d && ulSize) { for ( uli=0; uli <= ulSize-2; uli += 2) { Checksum += ((ULONG) (psz[uli]) << 8) + (ULONG) (psz[uli+1]); } Checksum = (Checksum >> 16) + (Checksum & 0xffff); Checksum += (Checksum >> 16); Checksum = ~Checksum; } return Checksum; } ULONG ulNumPacketsSent = 0; ULONG ulIndicateEvery = 10; ULONG ulIndicated = 0; #endif //DBG /////////////////////////////////////////////////////////////////////////////////////// VOID ResetNabStream ( PSLIP_FILTER pFilter, PNAB_STREAM pNabStream, PHW_STREAM_REQUEST_BLOCK pSrb, PVOID pBuffer, ULONG ulBufSize ) /////////////////////////////////////////////////////////////////////////////////////// { if (pNabStream->ulOffset > sizeof (Header802_3)) { pFilter->Stats.ulTotalSlipFramesIncomplete += 1; pFilter->Stats.ulTotalSlipBytesDropped += pNabStream->ulOffset - sizeof (Header802_3); } // // Reset the NAB_STREAM structure for this group ID // pNabStream->pSrb = pSrb; pNabStream->pszBuffer = pBuffer; pNabStream->ulcbSize = ulBufSize; pNabStream->ulOffset = 0; pNabStream->ulMpegCrc = 0xFFFFFFFF; pNabStream->ulCrcBytesIndex = 0l; pNabStream->ulLastCrcBytes = 0l; if(pBuffer) { // Copy the 802.3 header template into the frame. We will replace // the destination address and protocol on receive. // RtlCopyMemory (pNabStream->pszBuffer, &h802_3Template, sizeof (Header802_3)); // //$$PFP update buffer offset // pNabStream->ulOffset = sizeof (Header802_3); } return; } /////////////////////////////////////////////////////////////////////////////////////// VOID CancelNabStreamSrb ( PSLIP_FILTER pFilter, PHW_STREAM_REQUEST_BLOCK pSrb ) /////////////////////////////////////////////////////////////////////////////////////// { PLIST_ENTRY pFlink = NULL; PLIST_ENTRY pQueue = NULL; BOOLEAN bFound = FALSE; PNAB_STREAM pNSTemp = NULL; pQueue = &pFilter->StreamContxList; if ( !IsListEmpty (pQueue)) { pFlink = pQueue->Flink; while ((pFlink != pQueue ) && !bFound) { pNSTemp = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage); if (pSrb && pSrb == pNSTemp->pSrb) { pNSTemp->pSrb->Status = STATUS_CANCELLED; StreamClassStreamNotification (StreamRequestComplete, pNSTemp->pSrb->StreamObject, pNSTemp->pSrb); TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNSTemp->pSrb)); pNSTemp->pSrb = NULL; bFound = TRUE; } pFlink = pFlink->Flink; } if (bFound) { vDestroyNabStreamContext (pFilter, pNSTemp, TRUE); } } } /////////////////////////////////////////////////////////////////////////////////////// VOID DeleteNabStreamQueue ( PSLIP_FILTER pFilter ) /////////////////////////////////////////////////////////////////////////////////////// { PLIST_ENTRY pFlink = NULL; PLIST_ENTRY pQueue = NULL; PNAB_STREAM pNSTemp = NULL; pQueue = &pFilter->StreamContxList; while ( !IsListEmpty (pQueue)) { pFlink = RemoveHeadList (pQueue); pNSTemp = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage); if(pNSTemp && pNSTemp->pSrb) { pNSTemp->pSrb->Status = STATUS_CANCELLED; StreamClassStreamNotification (StreamRequestComplete, pNSTemp->pSrb->StreamObject, pNSTemp->pSrb); TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNSTemp->pSrb)); pNSTemp->pSrb = NULL; vDestroyNabStreamContext (pFilter, pNSTemp, TRUE); } } return; } ////////////////////////////////////////////////////////////////////////////// ULONG CalculateCrc ( PUCHAR pPacket, ULONG ulSize ) ////////////////////////////////////////////////////////////////////////////// { ULONG ul = 0; ULONG ulLastCrcBytes = 0; ULONG ulMpegCrc = 0xFFFFFFFF; PUCHAR ptr = NULL; PCL pcl = (PCL)&ulLastCrcBytes; for (ptr = pPacket, ul = 0; ul < ulSize; ul++, ptr++) { //if (ul > 3) //{ //MpegCrcUpdate (&ulMpegCrc, 1, &pcl->c.uc[3]); MpegCrcUpdate (&ulMpegCrc, 1, ptr); //} //pcl->l.ul = (ULONG)(pcl->l.ul) << 8; //pcl->c.uc[0] = *ptr; TEST_DEBUG( TEST_DBG_CRC, ("SLIP: char: %02X ul: %d MpegCrc: %08X\n", *ptr, ul, ulMpegCrc)); } return ulMpegCrc; } ////////////////////////////////////////////////////////////////////////////// VOID vNabtsUpdateCrc ( PNAB_STREAM pNabStream, UCHAR ucToCopy ) ////////////////////////////////////////////////////////////////////////////// { PCL pcl = (PCL)&pNabStream->ulLastCrcBytes; if (pNabStream->ulCrcBytesIndex++ > 3) { MpegCrcUpdate (&pNabStream->ulMpegCrc, 1, &pcl->c.uc[3]); } pcl->l.ul = (ULONG)(pcl->l.ul) << 8; pcl->c.uc[0] = ucToCopy; #ifdef DUMP_CRC TEST_DEBUG( TEST_DBG_CRC, ("SLIP: char: %02X ulLastCrcBytes: %08X MpegCrc: %08X ulCrcBytesIndex: %d\n", ucToCopy, pNabStream->ulLastCrcBytes, pNabStream->ulMpegCrc, pNabStream->ulCrcBytesIndex)); #endif // DUMP_CRC } ////////////////////////////////////////////////////////////////////////////// VOID ComputeIPChecksum ( PHeaderIP pIPHeader ) ////////////////////////////////////////////////////////////////////////////// { ULONG Checksum; PUCHAR NextChar; pIPHeader->ucChecksumHigh = pIPHeader->ucChecksumLow = 0; Checksum = 0; for ( NextChar = (PUCHAR) pIPHeader ; (NextChar - (PUCHAR) pIPHeader) <= (sizeof(HeaderIP) - 2) ; NextChar += 2) { Checksum += ((ULONG) (NextChar[0]) << 8) + (ULONG) (NextChar[1]); } Checksum = (Checksum >> 16) + (Checksum & 0xffff); Checksum += (Checksum >> 16); Checksum = ~Checksum; pIPHeader->ucChecksumHigh = (UCHAR) ((Checksum >> 8) & 0xff); pIPHeader->ucChecksumLow = (UCHAR) (Checksum & 0xff); } ////////////////////////////////////////////////////////////////////////////// // // Looks in the user's StreamContxList for a matching // Nabts Group ID. // It uses it if it finds one - otherwise we allocate one. // NTSTATUS ntFindNabtsStream( PSLIP_FILTER pFilter, PNABTSFEC_BUFFER pNabData, PNAB_STREAM *ppNabStream ) ////////////////////////////////////////////////////////////////////////////// { NTSTATUS status = STATUS_SUCCESS; PLIST_ENTRY pFlink; PNAB_STREAM pNabStream = NULL; // // Check to see if the groupid is within the valid range. // if(pNabData->groupID > NABTSIP_GROUP_ID_RANGE_HI ) { status = STATUS_INVALID_PARAMETER; ASSERT(status == STATUS_INVALID_PARAMETER); *ppNabStream = NULL; return status; } // // Go through the list one stream context at a time. // for (pFlink = pFilter->StreamContxList.Flink; pFlink != &pFilter->StreamContxList; pFlink = pFlink->Flink) { PNAB_STREAM pNSTemp; pNSTemp = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage); if(pNSTemp->groupID == pNabData->groupID) { pNabStream = pNSTemp; // // Mark the stream as having been used. This flag is checked // in vCheckNabStreamLife. // pNabStream->fUsed = TRUE; break; } } // // if we did not find a stream then create one. // if (pNabStream == NULL) { status = ntCreateNabStreamContext(pFilter, pNabData->groupID, &pNabStream); if(status == STATUS_SUCCESS) { #if DBG TEST_DEBUG( TEST_DBG_NAB, ("SLIP Creating new NAB_STREAM for data...Group ID: %08X\n", pNabStream->groupID)); #ifdef TEST_DBG_NAB DumpNabStream (pNabStream); #endif #endif //DBG } } else { TEST_DEBUG( TEST_DBG_NAB, ("SLIP Using existing NAB_STREAM for data. Group ID: %08X\n", pNabStream->groupID)); #ifdef TEST_DBG_NAB DumpNabStream (pNabStream); #endif } *ppNabStream = pNabStream; return status; } /////////////////////////////////////////////////////////////////////////////////////// NTSTATUS GetOutputSrbForStream ( PSLIP_FILTER pFilter, PNAB_STREAM pNabStream ) /////////////////////////////////////////////////////////////////////////////////////// { NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; PKSSTREAM_HEADER pStreamHdr = NULL; PHW_STREAM_REQUEST_BLOCK pSrbIPv4 = NULL; if (QueueRemove( &pSrbIPv4, &pFilter->IpV4StreamDataSpinLock, &pFilter->IpV4StreamDataQueue)) { // // Save the SRB References. // pNabStream->pSrb = pSrbIPv4; pStreamHdr = pSrbIPv4->CommandData.DataBufferArray; TEST_DEBUG (TEST_DBG_WRITE_DATA, ("SLIP: OUTPUT SRB...FrameExtent: %d DataUsed: %d Data: %08X\n", pStreamHdr->FrameExtent, pStreamHdr->DataUsed, pStreamHdr->Data )); status = STATUS_SUCCESS; } return status; } ////////////////////////////////////////////////////////////////////////////// void UpdateMACHeader ( PHeader802_3 pMAC, PHeaderIP pIP ) ////////////////////////////////////////////////////////////////////////////// { ASSERT (pMAC); ASSERT (pIP); // // Now we copy the low order 23 bits of the IP destination addresss to the 802.3 Header // if (pMAC && pIP) { pMAC->DestAddress [3] = pIP->ipaddrDst.ucHighLSB & 0x7F; pMAC->DestAddress [4] = pIP->ipaddrDst.ucLowMSB & 0xFF; pMAC->DestAddress [5] = pIP->ipaddrDst.ucLowLSB & 0xFF; } } ////////////////////////////////////////////////////////////////////////////// void vRebuildIPPacketHeader ( PNAB_STREAM pNabStream ) ////////////////////////////////////////////////////////////////////////////// { PNAB_HEADER_CACHE pPacketHeader; PNAB_HEADER_CACHE pSavedHeader = &pNabStream->NabHeader[pNabStream->ulIPStreamIndex]; PUCHAR psz; // // Copy the uncompressed packet header to the buffer. // RtlCopyMemory((pNabStream->pszBuffer + sizeof(Header802_3)), ((PUCHAR)&pNabStream->NabHeader[pNabStream->ulIPStreamIndex]), sizeof(HeaderIP) + sizeof(HeaderUDP)); // // Copy the compressed header items into the uncompressed packet header. // pPacketHeader = (PNAB_HEADER_CACHE)pNabStream->pszBuffer + sizeof(Header802_3); // // Copy IP Packet ID. // psz = (PUCHAR)pNabStream->NabCState[pNabStream->ulIPStreamIndex].usrgCompressedHeader; RtlCopyMemory(&pPacketHeader->ipHeader.ucIDHigh, psz, IP_ID_SIZE); // // Copy UDP Check Sum. // psz = (PUCHAR)(pNabStream->NabCState[pNabStream->ulIPStreamIndex].usrgCompressedHeader + 2); RtlCopyMemory(&pPacketHeader->udpHeader.ucChecksumHigh, psz, UDP_CHKSUM_SIZE); } ////////////////////////////////////////////////////////////////////////////// __inline VOID CopyNabToPacketNew( UCHAR uchToCopy, PNAB_STREAM pNabStream, PSLIP_FILTER pFilter ) ////////////////////////////////////////////////////////////////////////////// { if (pNabStream->ulOffset >= pNabStream->ulcbSize) { // // The packet is too big. Resync the SLIP stream. // pNabStream->ulFrameState = NABTS_FS_SYNC; pFilter->Stats.ulTotalSlipFramesTooBig += 1; } else { ULONG ulIPStream = pNabStream->ulIPStreamIndex; if(pNabStream->NabCState[ulIPStream].usCompressionState == NABTS_CS_UNCOMPRESSED) { // // Copy the byte to the actual Packet buffer. // pNabStream->pszBuffer[pNabStream->ulOffset] = uchToCopy; // // Update the MpegCrc check. // vNabtsUpdateCrc (pNabStream, uchToCopy); // // If we are collecting the IP Header data then copy it to // a buffer so that we can use it later for uncompression. // if(pNabStream->ulOffset < sizeof (Header802_3) + sizeof(HeaderIP) + sizeof(HeaderUDP)) { PUCHAR psz = (PUCHAR)&pNabStream->NabHeader[pNabStream->ulIPStreamIndex].ipHeader; *(psz + pNabStream->ulOffset - sizeof (Header802_3)) = uchToCopy; } // // Increment the data pointer. // pNabStream->ulOffset++; } else if(pNabStream->NabCState[ulIPStream].usCompressionState == NABTS_CS_COMPRESSED) { if(pNabStream->NabCState[ulIPStream].uscbHeaderOffset < pNabStream->NabCState[ulIPStream].uscbRequiredSize) { PUCHAR psz = (PUCHAR)pNabStream->NabCState[ulIPStream].usrgCompressedHeader; *(psz + pNabStream->NabCState[ulIPStream].uscbHeaderOffset++) = uchToCopy; // // Update the MpegCrc check. // vNabtsUpdateCrc (pNabStream, uchToCopy); if(pNabStream->NabCState[ulIPStream].uscbHeaderOffset == pNabStream->NabCState[ulIPStream].uscbRequiredSize) { ASSERT(pNabStream->ulOffset == sizeof(Header802_3)); // // Use the saved IP Packet header and the compressed IP Header // to rebuil the IP Header to send up. // vRebuildIPPacketHeader( pNabStream ); // // Set the buffer offset past the end of the IP/UDP headers // We should start coping data now. // pNabStream->ulOffset += (sizeof(HeaderIP) + sizeof(HeaderUDP)); } } else { // // We already have the header rebuilt. Now copy the payload. // pNabStream->pszBuffer[pNabStream->ulOffset++] = uchToCopy; // // Update the MpegCrc check. // vNabtsUpdateCrc (pNabStream, uchToCopy); } } else { DbgBreakPoint(); } } } ////////////////////////////////////////////////////////////////////////////// __inline VOID CopyNabToPacketOld( UCHAR uchToCopy, PNAB_STREAM pNabStream, PSLIP_FILTER pFilter ) ////////////////////////////////////////////////////////////////////////////// { if (pNabStream->ulOffset >= pNabStream->ulcbSize) { // // The packet is too big. Resync the SLIP stream. // pNabStream->ulFrameState = NABTS_FS_SYNC; pFilter->Stats.ulTotalSlipFramesTooBig += 1; } else { // Copy the byte. // pNabStream->pszBuffer[pNabStream->ulOffset++] = uchToCopy; } } ////////////////////////////////////////////////////////////////////////////// __inline VOID CopyNabToPacket( UCHAR uchToCopy, PNAB_STREAM pNabStream, PSLIP_FILTER pFilter ) ////////////////////////////////////////////////////////////////////////////// { if(pNabStream->ulProtoID == PROTO_ID) { CopyNabToPacketNew(uchToCopy, pNabStream, pFilter); } else { CopyNabToPacketOld(uchToCopy, pNabStream, pFilter); } } ////////////////////////////////////////////////////////////////////////////// NTSTATUS ntNabtsRecv( PSLIP_FILTER pFilter, PNABTSFEC_BUFFER pNabData ) ////////////////////////////////////////////////////////////////////////////// { NTSTATUS status = STATUS_SUCCESS; PNAB_STREAM pNabStream = NULL; PUCHAR pszNabIn = NULL; PKSSTREAM_HEADER pStreamHdr = NULL; LARGE_INTEGER liCurrentTime = {0}; LARGE_INTEGER liTimeToLive = {0}; LARGE_INTEGER liStatusInterval = {0}; KIRQL Irql = {0}; ULONG ulIPStream = 0; ULONG ulNabIn = 0; TEST_DEBUG( TEST_DBG_RECV, ("\nEntering - ntNabtsRecv\n")); // // Get the current system time. // KeQuerySystemTime(&liCurrentTime); // // See if it is time the check for dead GroupIDs and Streams. // Get a lock so no one else is modifying the Stream list while we are looking. // KeAcquireSpinLock(&pFilter->StreamUserSpinLock, &Irql); liTimeToLive.QuadPart = NAB_STREAM_LIFE; if( (LONGLONG)(liCurrentTime.QuadPart - pFilter->liLastTimeChecked.QuadPart) > liTimeToLive.QuadPart) { vCheckNabStreamLife( pFilter ); pFilter->liLastTimeChecked = liCurrentTime; } // // Find the Stream Context. // status = ntFindNabtsStream( pFilter, pNabData, &pNabStream ); if(status != STATUS_SUCCESS) { ASSERT( status == STATUS_SUCCESS); pFilter->Stats.ulTotalSlipBuffersDropped += 1; KeReleaseSpinLock(&pFilter->StreamUserSpinLock, Irql); goto ret; } KeReleaseSpinLock(&pFilter->StreamUserSpinLock, Irql); liStatusInterval.QuadPart = NAB_STATUS_INTERVAL; if( (LONGLONG)(liCurrentTime.QuadPart - pFilter->liLastTimeStatsDumped.QuadPart) > liStatusInterval.QuadPart) { pFilter->liLastTimeStatsDumped = liCurrentTime; TEST_DEBUG (TEST_DBG_INFO, (" ")); TEST_DEBUG (TEST_DBG_INFO, ("SLIP: ulTotalDataSRBWrites: %d\n.", pFilter->Stats.ulTotalDataSRBWrites)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalBadPinSRBWrites: %d\n.", pFilter->Stats.ulTotalBadPinSRBWrites)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalDataSRBReads: %d\n.", pFilter->Stats.ulTotalDataSRBReads)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalBadPinSRBReads: %d\n.", pFilter->Stats.ulTotalBadPinSRBReads)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBuffersReceived: %d\n.", pFilter->Stats.ulTotalSlipBuffersReceived)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBuffersDropped: %d\n.", pFilter->Stats.ulTotalSlipBuffersDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipZeroLengthBuffers: %d\n.", pFilter->Stats.ulTotalSlipZeroLengthBuffers)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBytesReceived: %d\n.", pFilter->Stats.ulTotalSlipBytesReceived)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipBytesDropped: %d\n.", pFilter->Stats.ulTotalSlipBytesDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesReceived: %d\n.", pFilter->Stats.ulTotalSlipFramesReceived)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipOldProtoFramesStarted: %d\n.", pFilter->Stats.ulTotalSlipOldProtoFramesStarted)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipNewProtoFramesStarted: %d\n.", pFilter->Stats.ulTotalSlipNewProtoFramesStarted)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesIncomplete: %d\n.", pFilter->Stats.ulTotalSlipFramesIncomplete)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesBadCRC: %d\n.", pFilter->Stats.ulTotalSlipFramesBadCRC)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesTooBig: %d\n.", pFilter->Stats.ulTotalSlipFramesTooBig)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalSlipFramesTooSmall: %d\n.", pFilter->Stats.ulTotalSlipFramesTooSmall)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsFound: %d\n.", pFilter->Stats.ulTotalIPPacketsFound)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPBytesFound: %d\n.", pFilter->Stats.ulTotalIPBytesFound)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsSent: %d\n.", pFilter->Stats.ulTotalIPPacketsSent)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPBytesSent: %d\n.", pFilter->Stats.ulTotalIPBytesSent)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsTooBig: %d\n.", pFilter->Stats.ulTotalIPPacketsTooBig)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsTooSmall: %d\n.", pFilter->Stats.ulTotalIPPacketsTooSmall)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPPacketsDropped: %d\n.", pFilter->Stats.ulTotalIPPacketsDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalIPBytesDropped: %d\n.", pFilter->Stats.ulTotalIPBytesDropped)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalNabStreamsCreated: %d\n.", pFilter->Stats.ulTotalNabStreamsCreated)); TEST_DEBUG (TEST_DBG_INFO, (" ulTotalNabStreamsTimedOut: %d\n.", pFilter->Stats.ulTotalNabStreamsTimedOut)); TEST_DEBUG (TEST_DBG_INFO, (" ")); } // // Set the last time used for this stream. // pNabStream->liLastTimeUsed = liCurrentTime; // // Get a pointer to the input buffer. We copy data from this pointer to // the output buffer // pszNabIn = (LPSTR) pNabData->data; // Validate the data size and that the start+end of the buffer are accessible ASSERT(pNabData->dataSize <= sizeof(pNabData->data) ); // What is really needed here is something like "MmIsValidAddress()", but for WDM drivers // These assert just look at the start & end addresses of the buffer w/o regard to values. // ASSERT( (*(pszNabIn) + 1 > 0) ); // ASSERT( (*(pszNabIn+pNabData->dataSize-1) + 1 > 0) ); for (ulNabIn = pNabData->dataSize; ulNabIn; ulNabIn--, pszNabIn++) { switch (pNabStream->ulFrameState) { case NABTS_FS_SYNC: switch (*pszNabIn) { case FRAME_END: // // We found the start of frame sync. Look for the // protocol character. // TEST_DEBUG( TEST_DBG_RECV, ("SLIP Found Possible Start of Frame... pszNabIn %08X ulNabIn: %08X\n", pszNabIn, ulNabIn)); pNabStream->ulFrameState = NABTS_FS_SYNC_PROTO; ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); break; } break; case NABTS_FS_SYNC_PROTO: switch (*pszNabIn) { case PROTO_ID: case PROTO_ID_OLD: TEST_DEBUG( TEST_DBG_RECV, ("SLIP Found Start of Protocol...Building Packet.... pszNabIn %08X ulNabIn: %08X\n", pszNabIn, ulNabIn)); // Record the stream type. // pNabStream->ulProtoID = *pszNabIn; // This is our protocol. Setup NAB_STREAM with an output // data buffer from the output SRB Queue // TEST_DEBUG( TEST_DBG_RECV, ("SLIP Setting Up Output buffer\n")); ResetNabStream( pFilter, pNabStream, NULL, pNabStream->rgBuf, sizeof(pNabStream->rgBuf)); // Copy the 802.3 header template into the frame. We will replace // the destination address and protocol on receive. // RtlCopyMemory (pNabStream->pszBuffer, &h802_3Template, sizeof (Header802_3)); // Update buffer offset // pNabStream->ulOffset = sizeof (Header802_3); if(pNabStream->ulProtoID == PROTO_ID) { // // Set the state to check the IP compression. // pFilter->Stats.ulTotalSlipNewProtoFramesStarted += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP Protocol ID is Compressed\n")); pNabStream->ulFrameState = NABTS_FS_COMPRESSION; } else { // // Start collecting data. // pFilter->Stats.ulTotalSlipOldProtoFramesStarted += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP Protocol ID is not Compressed\n")); pNabStream->ulFrameState = NABTS_FS_COLLECT; } // Update the MpegCrc check. // vNabtsUpdateCrc( pNabStream, *pszNabIn); break; case FRAME_END: TEST_DEBUG( TEST_DBG_RECV, ("SLIP State is FRAME_END....going to FS_SYNC_PROTO\n")); pNabStream->ulFrameState = NABTS_FS_SYNC_PROTO; break; default: TEST_DEBUG( TEST_DBG_RECV, ("SLIP Protocol Not Found...ReSyncing... pszNabIn %08X ulNabIn: %08X\n", pszNabIn, ulNabIn)); pNabStream->ulFrameState = NABTS_FS_SYNC; break; } break; case NABTS_FS_COMPRESSION: { TEST_DEBUG( TEST_DBG_RECV, ("SLIP State is NABTS_FS_COMPRESSION\n")); // // Get the index to the IP Compression Stream. // ulIPStream = IP_STREAM_INDEX(*pszNabIn); // // Check to see if this IP Packet has a compressed header. // if(!PACKET_COMPRESSED(*pszNabIn)) { pNabStream->NabCState[ulIPStream].usCompressionState = NABTS_CS_UNCOMPRESSED; } else if (PACKET_COMPRESSED (*pszNabIn)) { pNabStream->NabCState[ulIPStream].usCompressionState = NABTS_CS_COMPRESSED; pNabStream->NabCState[ulIPStream].uscbRequiredSize = NORMAL_COMPRESSED_HEADER; } // // Retain the IP Stream Index. // pNabStream->ulIPStreamIndex = ulIPStream; // // Set the stats Last Used Time for this stream. // pNabStream->NabCState[pNabStream->ulIPStreamIndex].liLastUsed = liCurrentTime; // // Set the IP Header Data Length to zero. // pNabStream->NabCState[pNabStream->ulIPStreamIndex].uscbHeaderOffset = 0; // // Start collecting data. // pNabStream->ulFrameState = NABTS_FS_COLLECT; // // Update the MpegCrc check. // vNabtsUpdateCrc (pNabStream, *pszNabIn); break; } case NABTS_FS_COLLECT: switch (*pszNabIn) { case FRAME_ESCAPE: // // We want to escape the next character. // TEST_DEBUG( TEST_DBG_RECV, ("SLIP NABTS_FS_COLLECT_ESCAPE\n")); pNabStream->ulFrameState = NABTS_FS_COLLECT_ESCAPE; break; case FRAME_END: if (pNabStream->ulOffset >= sizeof(HeaderIP)) { PHeaderIP pHeaderIp = (PHeaderIP)(PUCHAR)(pNabStream->pszBuffer + sizeof(Header802_3)); PUSHORT pusIpLen = (PUSHORT)&pHeaderIp->ucTotalLenHigh; TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset)); TEST_DEBUG( TEST_DBG_RECV, ("SLIP ulProtoID %d ulMpegCrc: %08X ulLastCrcBytes: %08X IpLen: %d\n", pNabStream->ulProtoID, pNabStream->ulMpegCrc, pNabStream->ulLastCrcBytes, *pusIpLen)); // If header compression is being used, we must // calculate the IP and UDP lengths and regenerate // the packet checksums. // if (pNabStream->ulProtoID == PROTO_ID) { PHeaderUDP pHeaderUDP = (PHeaderUDP)(PUCHAR)(pNabStream->pszBuffer + sizeof(Header802_3) + sizeof(HeaderIP)); PUSHORT pusUdpLen = (PUSHORT)&pHeaderUDP->ucMsgLenHigh; TEST_DEBUG( TEST_DBG_CRC, ("SLIP: GroupID: %d Stream CRC: %08X Calculated CRC: %08X", pNabStream->groupID, pNabStream->ulLastCrcBytes, pNabStream->ulMpegCrc)); // All PROTO_ID packets have an MpegCrc on the end. It is not // part of the IP packet and needs to be stripped off. // pNabStream->ulOffset -= 4; if (pNabStream->NabCState[pNabStream->ulIPStreamIndex].usCompressionState == NABTS_CS_COMPRESSED) { // We use the ulOffset less the MAC Header and IP Header // sizes for the UDP Packet length. // // Note! Fragmented UDP datagrams cannot be compressed // *pusUdpLen = htons ((USHORT)(pNabStream->ulOffset - sizeof(Header802_3) - sizeof(HeaderIP))); // We use the ulOffset less the MAC Header size for the // IP Packet length. // *pusIpLen = htons ((USHORT)(pNabStream->ulOffset - sizeof(Header802_3))); // Recalculate the IP header Checksum // ComputeIPChecksum (pHeaderIp); } // If the CRC was bad then invalidate // the IP Checksum // if (pNabStream->ulMpegCrc != pNabStream->ulLastCrcBytes) { TEST_DEBUG (TEST_DBG_CRC, (" FAILED*****\n")); pFilter->Stats.ulTotalSlipFramesBadCRC += 1; pHeaderIp->ucChecksumHigh = ~(pHeaderIp->ucChecksumHigh); pHeaderIp->ucChecksumLow = 0xff; } else { TEST_DEBUG (TEST_DBG_CRC, (" PASSED\n")); } } else if (pNabStream->ulProtoID != PROTO_ID_OLD) { TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found....Bad PROTO_ID... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset)); ASSERT( (pNabStream->ulProtoID == PROTO_ID_OLD) || (pNabStream->ulProtoID == PROTO_ID) ); ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; } if (NabtsNtoHs(*pusIpLen) <= NABTSIP_MAX_LOOKAHEAD) { // Update the MAC address // UpdateMACHeader( (PHeader802_3)(pNabStream->pszBuffer), pHeaderIp ); // Get an SRB for outputting the data. // status = GetOutputSrbForStream(pFilter, pNabStream ); if(status != STATUS_SUCCESS) { ASSERT(status == STATUS_SUCCESS); pFilter->Stats.ulTotalIPPacketsDropped += 1; ResetNabStream( pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; } ASSERT(pNabStream->pSrb); if (!pNabStream->pSrb) { pFilter->Stats.ulTotalIPPacketsDropped += 1; ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; } // Get the StreamHdr. // pStreamHdr = (PKSSTREAM_HEADER) pNabStream->pSrb->CommandData.DataBufferArray; ASSERT( pStreamHdr); if (!pStreamHdr) { pFilter->Stats.ulTotalIPPacketsDropped += 1; ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; goto ret; } // If we had a discontinuity, we flag it. // if (pFilter->bDiscontinuity) { pStreamHdr->OptionsFlags |= KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY; pFilter->bDiscontinuity = FALSE; } // Copy the data from the rgBuf to the Srb. // RtlCopyMemory (pStreamHdr->Data, pNabStream->pszBuffer, pNabStream->ulOffset ); // Update the datasize field of the Output SRB // pStreamHdr->DataUsed = pNabStream->ulOffset; // Complete the output SRB // pFilter->Stats.ulTotalIPPacketsSent += 1; pNabStream->ulOffset = 0; StreamClassStreamNotification( StreamRequestComplete, pNabStream->pSrb->StreamObject, pNabStream->pSrb ); TEST_DEBUG (TEST_DBG_SRB, ("SLIP: Completed SRB....Ptr %08X Size %d\n", pStreamHdr->Data, pStreamHdr->DataUsed)); TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNabStream->pSrb)); } else { // The packet is too big. Resync the SLIP stream. // pFilter->Stats.ulTotalIPPacketsDropped += 1; pFilter->Stats.ulTotalIPPacketsTooBig += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found....Packet Too BIG... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset)); } } else { // The packet is too small. Resync the SLIP stream. // pFilter->Stats.ulTotalIPPacketsDropped += 1; pFilter->Stats.ulTotalIPPacketsTooSmall += 1; TEST_DEBUG( TEST_DBG_RECV, ("SLIP End of Packet Found....Packet Too SMALL... pszNabIn %08X ulNabIn: %08X ulOffset: %d\n", pszNabIn, ulNabIn, pNabStream->ulOffset)); } // Reset state for new packet. // ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; break; default: // Just copy the byte to the NDIS packet. // CopyNabToPacket( *pszNabIn, pNabStream, pFilter); break; } break; case NABTS_FS_COLLECT_ESCAPE: pNabStream->ulFrameState = NABTS_FS_COLLECT; switch (*pszNabIn) { case TRANS_FRAME_ESCAPE: // // Special way to insert a FRAME_ESCAPE // character as part of the data. // TEST_DEBUG( TEST_DBG_RECV, ("SLIP NABTS_FS_COLLECT_ESCAPE....TRANS_FRAME_ESCAPE\n")); CopyNabToPacket( (UCHAR) FRAME_ESCAPE, pNabStream, pFilter); break; case TRANS_FRAME_END: // // Special way to insert a FRAME_END // character as part of the data. // TEST_DEBUG( TEST_DBG_RECV, ("SLIP NABTS_FS_COLLECT_ESCAPE.....TRANS_FRAME_END\n")); CopyNabToPacket( (UCHAR) FRAME_END, pNabStream, pFilter); break; default: // Any other character that follows FRAME_ESCAPE // is just inserted into the packet. // CopyNabToPacket( *pszNabIn, pNabStream, pFilter); break; } break; default: // // We should never be in an unknown state. // TEST_DEBUG( TEST_DBG_RECV, ("SLIP UNKNOWN STATE.....ReSyncing\n")); ASSERT( pNabStream->ulFrameState); ResetNabStream (pFilter, pNabStream, NULL, NULL, 0); pNabStream->ulFrameState = NABTS_FS_SYNC; break; } } ret: TEST_DEBUG( TEST_DBG_RECV, ("SLIP Completed ntNabtsRecv\n")); return status; } ////////////////////////////////////////////////////////////////////////////// // // Create a NAB Stream Context. // NTSTATUS ntCreateNabStreamContext( PSLIP_FILTER pFilter, ULONG groupID, PNAB_STREAM *ppNabStream ) ////////////////////////////////////////////////////////////////////////////// { NTSTATUS status = STATUS_SUCCESS; PNAB_STREAM pNabStream = NULL; TEST_DEBUG (TEST_DBG_NAB, ("******************************** Creating NAB STREAM for group ID %d\n", groupID)); // // Initialize output paramter // *ppNabStream = NULL; // // Allocate a Nab Stream structure. // status = ntAllocateNabStreamContext (&pNabStream); if(status == STATUS_SUCCESS) { pNabStream->ulType = (ULONG)NAB_STREAM_SIGNATURE; pNabStream->ulSize = sizeof (NAB_STREAM); pNabStream->ulFrameState = NABTS_FS_SYNC; pNabStream->ulMpegCrc = 0xFFFFFFFF; pNabStream->fUsed = TRUE; pNabStream->groupID = groupID; // // Add the new Stream Context to the User's Stream Context List. // InsertTailList (&pFilter->StreamContxList, &pNabStream->Linkage); *ppNabStream = pNabStream; } return status; } ////////////////////////////////////////////////////////////////////////////// NTSTATUS ntAllocateNabStreamContext( PNAB_STREAM *ppNabStream ) ////////////////////////////////////////////////////////////////////////////// { NTSTATUS status = STATUS_SUCCESS; PNAB_STREAM pNabStream = NULL; pNabStream = ExAllocatePool (NonPagedPool, sizeof(NAB_STREAM)); if (pNabStream == NULL) { *ppNabStream = NULL; return (STATUS_NO_MEMORY); } RtlZeroMemory (pNabStream, sizeof(NAB_STREAM)); *ppNabStream = pNabStream; return status; } ////////////////////////////////////////////////////////////////////////////// VOID vDestroyNabStreamContext( PSLIP_FILTER pFilter, PNAB_STREAM pNabStream, BOOLEAN fUseSpinLock ) ////////////////////////////////////////////////////////////////////////////// { KIRQL Irql; if(fUseSpinLock) { // // Lock the user. // KeAcquireSpinLock( &pFilter->StreamUserSpinLock, &Irql); } // // Remove the stream context from the user's list. // RemoveEntryList (&pNabStream->Linkage); if(fUseSpinLock) { // // UnLock the user. // KeReleaseSpinLock( &pFilter->StreamUserSpinLock, Irql); } // // Free the stream's SRB, if any. // if (pNabStream->pSrb) { StreamClassStreamNotification (StreamRequestComplete, pNabStream->pSrb->StreamObject, pNabStream->pSrb); TEST_DEBUG (TEST_DBG_TRACE, ("SLIP: StreamRequestComplete on pSrb: %08X\n", pNabStream->pSrb)); pNabStream->pSrb = NULL; } // // Free the stream context memory. // TEST_DEBUG (TEST_DBG_NAB, ("Deleting NAB STREAM for group ID: %d... ", pNabStream->groupID)); ExFreePool (pNabStream); } ////////////////////////////////////////////////////////////////////////////// VOID vCheckNabStreamLife ( PSLIP_FILTER pFilter ) ////////////////////////////////////////////////////////////////////////////// { PNAB_STREAM pNabStream; PLIST_ENTRY pFlink; TEST_DEBUG( TEST_DBG_RECV, ("Entering - vCheckNabStreamLife - pFilter: %x\n", pFilter)); // // Go through the StreamContextList. Remove any stream context structures that have // expired their life span. // for (pFlink = pFilter->StreamContxList.Flink; pFlink != &pFilter->StreamContxList; pFlink = pFlink->Flink) { pNabStream = CONTAINING_RECORD (pFlink, NAB_STREAM, Linkage); TEST_DEBUG (TEST_DBG_NAB, ("Checking NAB STREAM life for group ID %d ... ", pNabStream->groupID)); if (pNabStream->fUsed) { TEST_DEBUG (TEST_DBG_NAB, (" USED\n")); } else { TEST_DEBUG (TEST_DBG_NAB, (" NOT USED\n")); } if(!pNabStream->fUsed) { // Point at the previous Stream; pFlink = pFlink->Blink; // // Remove the stream from the User's stream context list. // // // vDestroyNabStreamContext returns the active NDIS Packet (if any) to // the adapter's free list, remove the stream context from the user list // (if specified) and free the stream context structure memory. // vDestroyNabStreamContext( pFilter, pNabStream, FALSE); pFilter->Stats.ulTotalNabStreamsTimedOut += 1; } else { // // This flag must be set back to TRUE before the next DPC fires or // this stream will be removed. // pNabStream->fUsed = FALSE; } } TEST_DEBUG ( TEST_DBG_RECV, ("Leaving - vCheckNabStreamLife\n")); }