//============================================================================ // Copyright (c) 1995, Microsoft Corporation // // File: queue.c // // History: // Abolade Gbadegesin Aug-8-1995 Created. // // timer queue, change queue, and event message queue implementation //============================================================================ #include "pchrip.h" #pragma hdrstop //---------------------------------------------------------------------------- // Function: EnqueueSendEntry // // This function adds an entry to the end of the queue of changed routes. // It assumes the queue is already locked, and since it needs to check // the maximum queue size, it assumes the global config is locked for // reading or writing //---------------------------------------------------------------------------- DWORD EnqueueSendEntry( PLOCKED_LIST pQueue, PRIP_IP_ROUTE pRoute ) { DWORD dwErr; PLIST_ENTRY phead, ple; PSEND_QUEUE_ENTRY psqe; RIP_IP_ROUTE rir; phead = &pQueue->LL_Head; if (IsListEmpty(phead)) { psqe = NULL; } else { ple = phead->Blink; psqe = CONTAINING_RECORD(ple, SEND_QUEUE_ENTRY, SQE_Link); } if (psqe == NULL || psqe->SQE_Count >= MAX_PACKET_ENTRIES) { // // we'll need to allocate a new entry // check that the max queue size is not exceeded // if ((DWORD)ig.IG_SendQueueSize >= ig.IG_Config->GC_MaxSendQueueSize) { TRACE2( SEND, "dropping route: send queue size is %d bytes and max is %d bytes", ig.IG_SendQueueSize, ig.IG_Config->GC_MaxSendQueueSize ); return ERROR_INSUFFICIENT_BUFFER; } psqe = RIP_ALLOC(sizeof(SEND_QUEUE_ENTRY)); if (psqe == NULL) { dwErr = GetLastError(); TRACE2( ANY, "error %d allocating %d bytes for send queue entry", dwErr, sizeof(SEND_QUEUE_ENTRY) ); LOGERR0(HEAP_ALLOC_FAILED, dwErr); return dwErr; } psqe->SQE_Count = 0; InsertTailList(phead, &psqe->SQE_Link); ig.IG_SendQueueSize += sizeof(SEND_QUEUE_ENTRY); } *(psqe->SQE_Routes + psqe->SQE_Count) = *pRoute; ++psqe->SQE_Count; return NO_ERROR; } //---------------------------------------------------------------------------- // Function: DequeueSendEntry // // This function removes an entry from the head of the queue of changed routes // assuming the queue is already locked //---------------------------------------------------------------------------- DWORD DequeueSendEntry( PLOCKED_LIST pQueue, PRIP_IP_ROUTE pRoute ) { PLIST_ENTRY phead, ple; PSEND_QUEUE_ENTRY psqe; phead = &pQueue->LL_Head; if (IsListEmpty(phead)) { return ERROR_NO_MORE_ITEMS; } ple = phead->Flink; psqe = CONTAINING_RECORD(ple, SEND_QUEUE_ENTRY, SQE_Link); --psqe->SQE_Count; *pRoute = *(psqe->SQE_Routes + psqe->SQE_Count); if (psqe->SQE_Count == 0) { RemoveEntryList(&psqe->SQE_Link); RIP_FREE(psqe); ig.IG_SendQueueSize -= sizeof(SEND_QUEUE_ENTRY); if (ig.IG_SendQueueSize < 0) { ig.IG_SendQueueSize = 0; } } return NO_ERROR; } //---------------------------------------------------------------------------- // Function: FlushSendQueue // // This function removes all entries from the send-queue. It assumes // that the queue is locked. //---------------------------------------------------------------------------- DWORD FlushSendQueue( PLOCKED_LIST pQueue ) { PLIST_ENTRY ple, phead; PSEND_QUEUE_ENTRY psqe; phead = &pQueue->LL_Head; while (!IsListEmpty(phead)) { ple = RemoveHeadList(phead); psqe = CONTAINING_RECORD(ple, SEND_QUEUE_ENTRY, SQE_Link); RIP_FREE(psqe); } ig.IG_SendQueueSize = 0; return NO_ERROR; } //---------------------------------------------------------------------------- // Function: EnqueueRecvEntry // // assumes that recv queue is locked and that global config is locked // for reading or writing //---------------------------------------------------------------------------- DWORD EnqueueRecvEntry( PLOCKED_LIST pQueue, DWORD dwCommand, PBYTE pRoutes ) { DWORD dwErr; PLIST_ENTRY phead; PRECV_QUEUE_ENTRY prqe; // // check that the max queue size is not exceeded // if ((DWORD)ig.IG_RecvQueueSize >= ig.IG_Config->GC_MaxRecvQueueSize) { TRACE2( RECEIVE, "dropping route: recv queue size is %d bytes and max is %d bytes", ig.IG_RecvQueueSize, ig.IG_Config->GC_MaxRecvQueueSize ); return ERROR_INSUFFICIENT_BUFFER; } phead = &pQueue->LL_Head; prqe = RIP_ALLOC(sizeof(RECV_QUEUE_ENTRY)); if (prqe == NULL) { dwErr = GetLastError(); TRACE2( ANY, "error %d allocating %d bytes for receive queue entry", dwErr, sizeof(RECV_QUEUE_ENTRY) ); LOGERR0(HEAP_ALLOC_FAILED, dwErr); return dwErr; } prqe->RQE_Routes = pRoutes; prqe->RQE_Command = dwCommand; InsertTailList(phead, &prqe->RQE_Link); ig.IG_RecvQueueSize += sizeof(RECV_QUEUE_ENTRY); return NO_ERROR; } //---------------------------------------------------------------------------- // Function: DequeueRecvEntry // // Retrieves the first item in the receive-queue. // Assumes that recv queue is locked //---------------------------------------------------------------------------- DWORD DequeueRecvEntry( PLOCKED_LIST pQueue, PDWORD pdwCommand, PBYTE *ppRoutes ) { PLIST_ENTRY ple, phead; PRECV_QUEUE_ENTRY prqe; phead = &pQueue->LL_Head; if (IsListEmpty(phead)) { return ERROR_NO_MORE_ITEMS; } ple = RemoveHeadList(phead); prqe = CONTAINING_RECORD(ple, RECV_QUEUE_ENTRY, RQE_Link); *ppRoutes = prqe->RQE_Routes; *pdwCommand = prqe->RQE_Command; RIP_FREE(prqe); ig.IG_RecvQueueSize -= sizeof(RECV_QUEUE_ENTRY); if (ig.IG_RecvQueueSize < 0) { ig.IG_RecvQueueSize = 0; } return NO_ERROR; } //---------------------------------------------------------------------------- // Function: FlushRecvQueue // // Removes all entries from the receive queue. // Assumes that the queue is locked. //---------------------------------------------------------------------------- DWORD FlushRecvQueue( PLOCKED_LIST pQueue ) { PLIST_ENTRY ple, phead; PRECV_QUEUE_ENTRY prqe; phead = &pQueue->LL_Head; while (!IsListEmpty(phead)) { ple = RemoveHeadList(phead); prqe = CONTAINING_RECORD(ple, RECV_QUEUE_ENTRY, RQE_Link); RIP_FREE(prqe->RQE_Routes); RIP_FREE(prqe); } ig.IG_RecvQueueSize = 0; return NO_ERROR; } //---------------------------------------------------------------------------- // Function: EnqueueEvent // // This function adds an entry to the end of the queue of // Router Manager events. It assumes the queue is locked. //---------------------------------------------------------------------------- DWORD EnqueueEvent( PLOCKED_LIST pQueue, ROUTING_PROTOCOL_EVENTS Event, MESSAGE Result ) { DWORD dwErr; PLIST_ENTRY phead; PEVENT_QUEUE_ENTRY peqe; phead = &pQueue->LL_Head; peqe = RIP_ALLOC(sizeof(EVENT_QUEUE_ENTRY)); if (peqe == NULL) { dwErr = GetLastError(); TRACE2( ANY, "error %d allocating %d bytes for event quue entry", dwErr, sizeof(EVENT_QUEUE_ENTRY) ); LOGERR0(HEAP_ALLOC_FAILED, dwErr); return dwErr; } peqe->EQE_Event = Event; peqe->EQE_Result = Result; InsertTailList(phead, &peqe->EQE_Link); return NO_ERROR; } //---------------------------------------------------------------------------- // Function: DequeueEvent // // This function removes an entry from the head of the queue // of Router Manager events. It assumes the queue is locked //---------------------------------------------------------------------------- DWORD DequeueEvent( PLOCKED_LIST pQueue, ROUTING_PROTOCOL_EVENTS *pEvent, PMESSAGE pResult ) { PLIST_ENTRY phead, ple; PEVENT_QUEUE_ENTRY peqe; phead = &pQueue->LL_Head; if (IsListEmpty(phead)) { return ERROR_NO_MORE_ITEMS; } ple = RemoveHeadList(phead); peqe = CONTAINING_RECORD(ple, EVENT_QUEUE_ENTRY, EQE_Link); *pEvent = peqe->EQE_Event; *pResult = peqe->EQE_Result; RIP_FREE(peqe); return NO_ERROR; }