Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
8.9 KiB

  1. //============================================================================
  2. // Copyright (c) 1995, Microsoft Corporation
  3. //
  4. // File: queue.c
  5. //
  6. // History:
  7. // Abolade Gbadegesin Aug-8-1995 Created.
  8. //
  9. // timer queue, change queue, and event message queue implementation
  10. //============================================================================
  11. #include "pchrip.h"
  12. #pragma hdrstop
  13. //----------------------------------------------------------------------------
  14. // Function: EnqueueSendEntry
  15. //
  16. // This function adds an entry to the end of the queue of changed routes.
  17. // It assumes the queue is already locked, and since it needs to check
  18. // the maximum queue size, it assumes the global config is locked for
  19. // reading or writing
  20. //----------------------------------------------------------------------------
  21. DWORD
  22. EnqueueSendEntry(
  23. PLOCKED_LIST pQueue,
  24. PRIP_IP_ROUTE pRoute
  25. ) {
  26. DWORD dwErr;
  27. PLIST_ENTRY phead, ple;
  28. PSEND_QUEUE_ENTRY psqe;
  29. RIP_IP_ROUTE rir;
  30. phead = &pQueue->LL_Head;
  31. if (IsListEmpty(phead)) {
  32. psqe = NULL;
  33. }
  34. else {
  35. ple = phead->Blink;
  36. psqe = CONTAINING_RECORD(ple, SEND_QUEUE_ENTRY, SQE_Link);
  37. }
  38. if (psqe == NULL || psqe->SQE_Count >= MAX_PACKET_ENTRIES) {
  39. //
  40. // we'll need to allocate a new entry
  41. // check that the max queue size is not exceeded
  42. //
  43. if ((DWORD)ig.IG_SendQueueSize >= ig.IG_Config->GC_MaxSendQueueSize) {
  44. TRACE2(
  45. SEND,
  46. "dropping route: send queue size is %d bytes and max is %d bytes",
  47. ig.IG_SendQueueSize, ig.IG_Config->GC_MaxSendQueueSize
  48. );
  49. return ERROR_INSUFFICIENT_BUFFER;
  50. }
  51. psqe = RIP_ALLOC(sizeof(SEND_QUEUE_ENTRY));
  52. if (psqe == NULL) {
  53. dwErr = GetLastError();
  54. TRACE2(
  55. ANY, "error %d allocating %d bytes for send queue entry",
  56. dwErr, sizeof(SEND_QUEUE_ENTRY)
  57. );
  58. LOGERR0(HEAP_ALLOC_FAILED, dwErr);
  59. return dwErr;
  60. }
  61. psqe->SQE_Count = 0;
  62. InsertTailList(phead, &psqe->SQE_Link);
  63. ig.IG_SendQueueSize += sizeof(SEND_QUEUE_ENTRY);
  64. }
  65. *(psqe->SQE_Routes + psqe->SQE_Count) = *pRoute;
  66. ++psqe->SQE_Count;
  67. return NO_ERROR;
  68. }
  69. //----------------------------------------------------------------------------
  70. // Function: DequeueSendEntry
  71. //
  72. // This function removes an entry from the head of the queue of changed routes
  73. // assuming the queue is already locked
  74. //----------------------------------------------------------------------------
  75. DWORD
  76. DequeueSendEntry(
  77. PLOCKED_LIST pQueue,
  78. PRIP_IP_ROUTE pRoute
  79. ) {
  80. PLIST_ENTRY phead, ple;
  81. PSEND_QUEUE_ENTRY psqe;
  82. phead = &pQueue->LL_Head;
  83. if (IsListEmpty(phead)) {
  84. return ERROR_NO_MORE_ITEMS;
  85. }
  86. ple = phead->Flink;
  87. psqe = CONTAINING_RECORD(ple, SEND_QUEUE_ENTRY, SQE_Link);
  88. --psqe->SQE_Count;
  89. *pRoute = *(psqe->SQE_Routes + psqe->SQE_Count);
  90. if (psqe->SQE_Count == 0) {
  91. RemoveEntryList(&psqe->SQE_Link);
  92. RIP_FREE(psqe);
  93. ig.IG_SendQueueSize -= sizeof(SEND_QUEUE_ENTRY);
  94. if (ig.IG_SendQueueSize < 0) { ig.IG_SendQueueSize = 0; }
  95. }
  96. return NO_ERROR;
  97. }
  98. //----------------------------------------------------------------------------
  99. // Function: FlushSendQueue
  100. //
  101. // This function removes all entries from the send-queue. It assumes
  102. // that the queue is locked.
  103. //----------------------------------------------------------------------------
  104. DWORD
  105. FlushSendQueue(
  106. PLOCKED_LIST pQueue
  107. ) {
  108. PLIST_ENTRY ple, phead;
  109. PSEND_QUEUE_ENTRY psqe;
  110. phead = &pQueue->LL_Head;
  111. while (!IsListEmpty(phead)) {
  112. ple = RemoveHeadList(phead);
  113. psqe = CONTAINING_RECORD(ple, SEND_QUEUE_ENTRY, SQE_Link);
  114. RIP_FREE(psqe);
  115. }
  116. ig.IG_SendQueueSize = 0;
  117. return NO_ERROR;
  118. }
  119. //----------------------------------------------------------------------------
  120. // Function: EnqueueRecvEntry
  121. //
  122. // assumes that recv queue is locked and that global config is locked
  123. // for reading or writing
  124. //----------------------------------------------------------------------------
  125. DWORD
  126. EnqueueRecvEntry(
  127. PLOCKED_LIST pQueue,
  128. DWORD dwCommand,
  129. PBYTE pRoutes
  130. ) {
  131. DWORD dwErr;
  132. PLIST_ENTRY phead;
  133. PRECV_QUEUE_ENTRY prqe;
  134. //
  135. // check that the max queue size is not exceeded
  136. //
  137. if ((DWORD)ig.IG_RecvQueueSize >= ig.IG_Config->GC_MaxRecvQueueSize) {
  138. TRACE2(
  139. RECEIVE,
  140. "dropping route: recv queue size is %d bytes and max is %d bytes",
  141. ig.IG_RecvQueueSize, ig.IG_Config->GC_MaxRecvQueueSize
  142. );
  143. return ERROR_INSUFFICIENT_BUFFER;
  144. }
  145. phead = &pQueue->LL_Head;
  146. prqe = RIP_ALLOC(sizeof(RECV_QUEUE_ENTRY));
  147. if (prqe == NULL) {
  148. dwErr = GetLastError();
  149. TRACE2(
  150. ANY, "error %d allocating %d bytes for receive queue entry",
  151. dwErr, sizeof(RECV_QUEUE_ENTRY)
  152. );
  153. LOGERR0(HEAP_ALLOC_FAILED, dwErr);
  154. return dwErr;
  155. }
  156. prqe->RQE_Routes = pRoutes;
  157. prqe->RQE_Command = dwCommand;
  158. InsertTailList(phead, &prqe->RQE_Link);
  159. ig.IG_RecvQueueSize += sizeof(RECV_QUEUE_ENTRY);
  160. return NO_ERROR;
  161. }
  162. //----------------------------------------------------------------------------
  163. // Function: DequeueRecvEntry
  164. //
  165. // Retrieves the first item in the receive-queue.
  166. // Assumes that recv queue is locked
  167. //----------------------------------------------------------------------------
  168. DWORD
  169. DequeueRecvEntry(
  170. PLOCKED_LIST pQueue,
  171. PDWORD pdwCommand,
  172. PBYTE *ppRoutes
  173. ) {
  174. PLIST_ENTRY ple, phead;
  175. PRECV_QUEUE_ENTRY prqe;
  176. phead = &pQueue->LL_Head;
  177. if (IsListEmpty(phead)) { return ERROR_NO_MORE_ITEMS; }
  178. ple = RemoveHeadList(phead);
  179. prqe = CONTAINING_RECORD(ple, RECV_QUEUE_ENTRY, RQE_Link);
  180. *ppRoutes = prqe->RQE_Routes;
  181. *pdwCommand = prqe->RQE_Command;
  182. RIP_FREE(prqe);
  183. ig.IG_RecvQueueSize -= sizeof(RECV_QUEUE_ENTRY);
  184. if (ig.IG_RecvQueueSize < 0) { ig.IG_RecvQueueSize = 0; }
  185. return NO_ERROR;
  186. }
  187. //----------------------------------------------------------------------------
  188. // Function: FlushRecvQueue
  189. //
  190. // Removes all entries from the receive queue.
  191. // Assumes that the queue is locked.
  192. //----------------------------------------------------------------------------
  193. DWORD
  194. FlushRecvQueue(
  195. PLOCKED_LIST pQueue
  196. ) {
  197. PLIST_ENTRY ple, phead;
  198. PRECV_QUEUE_ENTRY prqe;
  199. phead = &pQueue->LL_Head;
  200. while (!IsListEmpty(phead)) {
  201. ple = RemoveHeadList(phead);
  202. prqe = CONTAINING_RECORD(ple, RECV_QUEUE_ENTRY, RQE_Link);
  203. RIP_FREE(prqe->RQE_Routes);
  204. RIP_FREE(prqe);
  205. }
  206. ig.IG_RecvQueueSize = 0;
  207. return NO_ERROR;
  208. }
  209. //----------------------------------------------------------------------------
  210. // Function: EnqueueEvent
  211. //
  212. // This function adds an entry to the end of the queue of
  213. // Router Manager events. It assumes the queue is locked.
  214. //----------------------------------------------------------------------------
  215. DWORD
  216. EnqueueEvent(
  217. PLOCKED_LIST pQueue,
  218. ROUTING_PROTOCOL_EVENTS Event,
  219. MESSAGE Result
  220. ) {
  221. DWORD dwErr;
  222. PLIST_ENTRY phead;
  223. PEVENT_QUEUE_ENTRY peqe;
  224. phead = &pQueue->LL_Head;
  225. peqe = RIP_ALLOC(sizeof(EVENT_QUEUE_ENTRY));
  226. if (peqe == NULL) {
  227. dwErr = GetLastError();
  228. TRACE2(
  229. ANY, "error %d allocating %d bytes for event quue entry",
  230. dwErr, sizeof(EVENT_QUEUE_ENTRY)
  231. );
  232. LOGERR0(HEAP_ALLOC_FAILED, dwErr);
  233. return dwErr;
  234. }
  235. peqe->EQE_Event = Event;
  236. peqe->EQE_Result = Result;
  237. InsertTailList(phead, &peqe->EQE_Link);
  238. return NO_ERROR;
  239. }
  240. //----------------------------------------------------------------------------
  241. // Function: DequeueEvent
  242. //
  243. // This function removes an entry from the head of the queue
  244. // of Router Manager events. It assumes the queue is locked
  245. //----------------------------------------------------------------------------
  246. DWORD
  247. DequeueEvent(
  248. PLOCKED_LIST pQueue,
  249. ROUTING_PROTOCOL_EVENTS *pEvent,
  250. PMESSAGE pResult
  251. ) {
  252. PLIST_ENTRY phead, ple;
  253. PEVENT_QUEUE_ENTRY peqe;
  254. phead = &pQueue->LL_Head;
  255. if (IsListEmpty(phead)) {
  256. return ERROR_NO_MORE_ITEMS;
  257. }
  258. ple = RemoveHeadList(phead);
  259. peqe = CONTAINING_RECORD(ple, EVENT_QUEUE_ENTRY, EQE_Link);
  260. *pEvent = peqe->EQE_Event;
  261. *pResult = peqe->EQE_Result;
  262. RIP_FREE(peqe);
  263. return NO_ERROR;
  264. }