windows-nt/Source/XPSP1/NT/net/rras/ip/rip/queue.c
2020-09-26 16:20:57 +08:00

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;
}