377 lines
8.5 KiB
C
377 lines
8.5 KiB
C
|
//============================================================================
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|