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.

471 lines
12 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. net\routing\ipx\sap\netio.c
  5. Abstract:
  6. This module handles network io for sap agent
  7. Author:
  8. Vadim Eydelman 05-15-1995
  9. Revision History:
  10. --*/
  11. #include "sapp.h"
  12. // Queues and synchronization associated with net io
  13. typedef struct _IO_QUEUES {
  14. HANDLE IQ_AdptHdl; // Handle to SAP socket port
  15. HANDLE IQ_RecvEvent; // Event signalled when recv completes
  16. #if DBG
  17. LIST_ENTRY IQ_SentPackets; // Packets that are being sent
  18. LIST_ENTRY IQ_RcvdPackets; // Packets that are being received
  19. #endif
  20. CRITICAL_SECTION IQ_Lock; // Queue data protection
  21. } IO_QUEUES, *PIO_QUEUES;
  22. IO_QUEUES IOQueues;
  23. VOID CALLBACK
  24. IoCompletionProc (
  25. DWORD error,
  26. DWORD cbTransferred,
  27. LPOVERLAPPED ovlp
  28. );
  29. VOID CALLBACK
  30. SendCompletionProc (
  31. DWORD status,
  32. DWORD cbSent,
  33. PIO_PARAM_BLOCK sreq
  34. );
  35. VOID CALLBACK
  36. RecvCompletionProc (
  37. DWORD status,
  38. DWORD cbSent,
  39. PIO_PARAM_BLOCK rreq
  40. );
  41. DWORD
  42. CreateIOQueue (
  43. HANDLE *RecvEvent
  44. ) {
  45. DWORD status;
  46. InitializeCriticalSection (&IOQueues.IQ_Lock);
  47. #if DBG
  48. InitializeListHead (&IOQueues.IQ_SentPackets);
  49. InitializeListHead (&IOQueues.IQ_RcvdPackets);
  50. #endif
  51. IOQueues.IQ_AdptHdl = INVALID_HANDLE_VALUE;
  52. IOQueues.IQ_RecvEvent = CreateEvent (NULL,
  53. FALSE, // auto-reset (reset by recv operation
  54. // and when thread is signalled (it may
  55. // not post new request if limit is
  56. // exceded)
  57. FALSE, // not signalled
  58. NULL);
  59. if (IOQueues.IQ_RecvEvent!=NULL) {
  60. INT i;
  61. *RecvEvent = IOQueues.IQ_RecvEvent;
  62. return NO_ERROR;
  63. }
  64. else {
  65. status = GetLastError ();
  66. Trace (DEBUG_FAILURES,
  67. "Failed to create recv comp event (gle:%ld)", status);
  68. }
  69. DeleteCriticalSection (&IOQueues.IQ_Lock);
  70. return status;
  71. }
  72. VOID
  73. DeleteIOQueue (
  74. VOID
  75. ) {
  76. CloseHandle (IOQueues.IQ_RecvEvent);
  77. DeleteCriticalSection (&IOQueues.IQ_Lock);
  78. }
  79. DWORD
  80. StartIO (
  81. VOID
  82. ) {
  83. DWORD status=NO_ERROR;
  84. EnterCriticalSection (&IOQueues.IQ_Lock);
  85. if (IOQueues.IQ_AdptHdl==INVALID_HANDLE_VALUE) {
  86. USHORT sockNum;
  87. IpxSockCpy (&sockNum, IPX_SAP_SOCKET);
  88. Trace (DEBUG_NET_IO, "Creating socket port.");
  89. IOQueues.IQ_AdptHdl = CreateSocketPort (sockNum);
  90. if (IOQueues.IQ_AdptHdl!=INVALID_HANDLE_VALUE) {
  91. status = NO_ERROR;
  92. if (! BindIoCompletionCallback(
  93. IOQueues.IQ_AdptHdl,
  94. IoCompletionProc,
  95. 0))
  96. {
  97. status = GetLastError();
  98. }
  99. if (status==NO_ERROR) {
  100. BOOL res;
  101. LeaveCriticalSection (&IOQueues.IQ_Lock);
  102. res = SetEvent (IOQueues.IQ_RecvEvent);
  103. ASSERTMSG ("Could not set recv event ", res);
  104. return NO_ERROR;
  105. }
  106. else {
  107. status = GetLastError ();
  108. Trace (DEBUG_FAILURES,
  109. "Failed to create completion port (gle:%ld)", status);
  110. }
  111. DeleteSocketPort (IOQueues.IQ_AdptHdl);
  112. IOQueues.IQ_AdptHdl = INVALID_HANDLE_VALUE;
  113. }
  114. else {
  115. status = GetLastError ();
  116. Trace (DEBUG_FAILURES,
  117. "Failed to create adapter port (gle:%ld)", status);
  118. IF_LOG (EVENTLOG_ERROR_TYPE) {
  119. RouterLogErrorA (RouterEventLogHdl,
  120. ROUTERLOG_IPXSAP_SAP_SOCKET_IN_USE,
  121. 0, NULL, status);
  122. }
  123. }
  124. }
  125. LeaveCriticalSection (&IOQueues.IQ_Lock);
  126. return status;
  127. }
  128. VOID
  129. StopIO (
  130. VOID
  131. ) {
  132. EnterCriticalSection (&IOQueues.IQ_Lock);
  133. if (IOQueues.IQ_AdptHdl!=INVALID_HANDLE_VALUE) {
  134. DWORD status;
  135. HANDLE Port = IOQueues.IQ_AdptHdl;
  136. IOQueues.IQ_AdptHdl = INVALID_HANDLE_VALUE;
  137. LeaveCriticalSection (&IOQueues.IQ_Lock);
  138. Trace (DEBUG_NET_IO, "Deleting socket port.");
  139. DeleteSocketPort (Port);
  140. }
  141. else
  142. LeaveCriticalSection (&IOQueues.IQ_Lock);
  143. }
  144. /*++
  145. *******************************************************************
  146. I o C o m p l e t i o n P r o c
  147. Routine Description:
  148. Called on completion of each io request
  149. Arguments:
  150. error - result of io
  151. cbTransferred - number of bytes actually sent
  152. ovlp - overlapped structure associated with io request
  153. Return Value:
  154. None
  155. *******************************************************************
  156. --*/
  157. VOID CALLBACK
  158. IoCompletionProc (
  159. DWORD error,
  160. DWORD cbTransferred,
  161. LPOVERLAPPED ovlp
  162. ) {
  163. PIO_PARAM_BLOCK req = CONTAINING_RECORD (ovlp, IO_PARAM_BLOCK, ovlp);
  164. // Get actual parameters adjusted by the adapter dll
  165. IpxAdjustIoCompletionParams (ovlp, &cbTransferred, &error);
  166. (*req->comp)(error, cbTransferred, req);
  167. }
  168. /*++
  169. *******************************************************************
  170. E n q u e u e S e n d R e q u e s t
  171. Routine Description:
  172. Sets adapter id field in request io param block and enqueues
  173. send request to adapter's driver.
  174. Arguments:
  175. sreq - io parameter block, the following fields must be set:
  176. intf - pointer to interface external data
  177. buffer - pointer to buffer that contains data to be sent
  178. cbBuffer - count of bytes of data in the buffer
  179. Return Value:
  180. None
  181. *******************************************************************
  182. --*/
  183. VOID
  184. EnqueueSendRequest (
  185. PIO_PARAM_BLOCK sreq
  186. ) {
  187. DWORD status;
  188. sreq->status = ERROR_IO_PENDING;
  189. sreq->ovlp.hEvent = NULL;
  190. sreq->comp = SendCompletionProc;
  191. #if DBG
  192. EnterCriticalSection (&IOQueues.IQ_Lock);
  193. InsertTailList (&IOQueues.IQ_SentPackets, &sreq->link);
  194. LeaveCriticalSection (&IOQueues.IQ_Lock);
  195. #endif
  196. status = IpxSendPacket (IOQueues.IQ_AdptHdl,
  197. sreq->adpt,
  198. sreq->buffer,
  199. sreq->cbBuffer,
  200. &sreq->rsvd,
  201. &sreq->ovlp,
  202. NULL
  203. );
  204. // If request failed and thus completion routine won't be called
  205. // we'll simulate completion ourselves so that request won't get
  206. // lost
  207. if (status!=NO_ERROR)
  208. SendCompletionProc (status, 0, sreq);
  209. }
  210. /*++
  211. *******************************************************************
  212. S e n d C o m p l e t i o n P r o c
  213. Routine Description:
  214. Called on completion for each sent packet.
  215. Sets fields of send request io param block and enqueues it to
  216. completion queue.
  217. Arguments:
  218. status - result of io
  219. cbSent - number of bytes actually sent
  220. context - context associated with send request (IO_PARAM_BLOCK)
  221. Return Value:
  222. None
  223. *******************************************************************
  224. --*/
  225. VOID CALLBACK
  226. SendCompletionProc (
  227. DWORD status,
  228. DWORD cbSent,
  229. PIO_PARAM_BLOCK sreq
  230. ) {
  231. BOOL res;
  232. BOOL releaseSend = FALSE;
  233. sreq->compTime = GetTickCount ();
  234. sreq->status = status;
  235. if (status!=NO_ERROR) {
  236. #define dstPtr (sreq->buffer+FIELD_OFFSET (SAP_BUFFER, Dst.Network))
  237. Trace (DEBUG_FAILURES, "Error %d while sending to"
  238. " %02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%02x%02x"
  239. " on adapter %d.", status,
  240. *dstPtr, *(dstPtr+1), *(dstPtr+2), *(dstPtr+3),
  241. *(dstPtr+4), *(dstPtr+5), *(dstPtr+6), *(dstPtr+7), *(dstPtr+8), *(dstPtr+9),
  242. *(dstPtr+10), *(dstPtr+11),
  243. sreq->adpt);
  244. #undef dstPtr
  245. }
  246. sreq->cbBuffer = cbSent;
  247. #if DBG
  248. // Maintain queue of posted requests
  249. EnterCriticalSection (&IOQueues.IQ_Lock);
  250. RemoveEntryList (&sreq->link);
  251. LeaveCriticalSection (&IOQueues.IQ_Lock);
  252. #endif
  253. ProcessCompletedIORequest (sreq);
  254. }
  255. /*++
  256. *******************************************************************
  257. E n q u e u e R e c v R e q u e s t
  258. Routine Description:
  259. Enqueues recv request to be posted to the network driver.
  260. Arguments:
  261. rreq - io parameter block, the following fields must be set:
  262. buffer - pointer to buffer to receive data
  263. cbBuffer - size of the buffer
  264. Return Value:
  265. TRUE - need more recv requests (number of posted requests is below
  266. low water mark)
  267. FALSE - no more requests needed.
  268. *******************************************************************
  269. --*/
  270. VOID
  271. EnqueueRecvRequest (
  272. PIO_PARAM_BLOCK rreq
  273. ) {
  274. DWORD status;
  275. rreq->status = ERROR_IO_PENDING;
  276. rreq->adpt = INVALID_ADAPTER_INDEX;
  277. rreq->ovlp.hEvent = IOQueues.IQ_RecvEvent;
  278. rreq->comp = RecvCompletionProc;
  279. #if DBG
  280. EnterCriticalSection (&IOQueues.IQ_Lock);
  281. InsertTailList (&IOQueues.IQ_RcvdPackets, &rreq->link);
  282. LeaveCriticalSection (&IOQueues.IQ_Lock);
  283. #endif
  284. status = IpxRecvPacket (IOQueues.IQ_AdptHdl,
  285. rreq->buffer,
  286. rreq->cbBuffer,
  287. &rreq->rsvd,
  288. &rreq->ovlp,
  289. NULL
  290. );
  291. if (status==NO_ERROR) {
  292. NOTHING;
  293. }
  294. else {
  295. Trace (DEBUG_FAILURES, "Error %d while posting receive packet", status);
  296. // If request failed and thus completion routine won't be called
  297. // we'll simulate completion ourselves so that request won't get
  298. // lost
  299. RecvCompletionProc (status, 0, rreq);
  300. }
  301. }
  302. /*++
  303. *******************************************************************
  304. R e c v C o m p l e t i o n P r o c
  305. Routine Description:
  306. Called on completion of each received packet.
  307. Sets fields of recv request io param block and enqueues it to
  308. completion queue.
  309. Arguments:
  310. status - result of io
  311. cbSent - number of bytes actually sent
  312. context - context associated with send request (IO_PARAM_BLOCK)
  313. Return Value:
  314. None
  315. *******************************************************************
  316. --*/
  317. VOID CALLBACK
  318. RecvCompletionProc (
  319. DWORD status,
  320. DWORD cbRecvd,
  321. PIO_PARAM_BLOCK rreq
  322. ) {
  323. BOOL completed=TRUE;
  324. rreq->adpt = GetNicId (&rreq->rsvd);
  325. rreq->compTime = GetTickCount ();
  326. rreq->cbBuffer = cbRecvd;
  327. rreq->status = status;
  328. if (status!=NO_ERROR)
  329. Trace (DEBUG_FAILURES, "Error %d while receiving packet on adapter %d.",
  330. status, rreq->adpt);
  331. #if DBG
  332. EnterCriticalSection (&IOQueues.IQ_Lock);
  333. RemoveEntryList (&rreq->link);
  334. LeaveCriticalSection (&IOQueues.IQ_Lock);
  335. #endif
  336. ProcessCompletedIORequest (rreq);
  337. }
  338. /*++
  339. *******************************************************************
  340. D u m p P a c k e t
  341. Routine Description:
  342. Dumps IPX SAP packet fields to stdio
  343. Arguments:
  344. Packet - pointer to IPX SAP packet
  345. count - size of the packet
  346. Return Value:
  347. None
  348. *******************************************************************
  349. --*/
  350. /*
  351. #if DBG
  352. VOID
  353. DumpPacket (
  354. PSAP_BUFFER packet,
  355. DWORD count
  356. ) {
  357. SS_PRINTF(("Length : %d.", GETUSHORT (&packet->Length)));
  358. SS_PRINTF(("Packet type : %02X.", packet->PacketType));
  359. SS_PRINTF(("Dest. net : %02X%02X%02X%02X.",
  360. packet->Dst.Net[0],
  361. packet->Dst.Net[1],
  362. packet->Dst.Net[2],
  363. packet->Dst.Net[3]));
  364. SS_PRINTF(("Dest. node : %02X%02X%02X%02X%02X%02X.",
  365. packet->Dst.Node[0],
  366. packet->Dst.Node[1],
  367. packet->Dst.Node[2],
  368. packet->Dst.Node[3],
  369. packet->Dst.Node[4],
  370. packet->Dst.Node[5]));
  371. SS_PRINTF(("Dest. socket : %04X.", GETUSHORT (&packet->Dst.Socket)));
  372. SS_PRINTF(("Src. net : %02X%02X%02X%02X.",
  373. packet->Src.Net[0],
  374. packet->Src.Net[1],
  375. packet->Src.Net[2],
  376. packet->Src.Net[3]));
  377. SS_PRINTF(("Src. node : %02X%02X%02X%02X%02X%02X.",
  378. packet->Src.Node[0],
  379. packet->Src.Node[1],
  380. packet->Src.Node[2],
  381. packet->Src.Node[3],
  382. packet->Src.Node[4],
  383. packet->Src.Node[5]));
  384. SS_PRINTF(("Src. socket : %04X.", GETUSHORT (&packet->Src.Socket)));
  385. if (count>=(DWORD)FIELD_OFFSET(SAP_BUFFER, Entries[0])) {
  386. INT j;
  387. SS_PRINTF(("SAP Operation : %d.", GETUSHORT (&packet->Operation)));
  388. for (j=0; (j<7) && (count>=(DWORD)FIELD_OFFSET (SAP_BUFFER, Entries[j+1])); j++) {
  389. SS_PRINTF(("Server type : %04X.", GETUSHORT (&packet->Entries[j].Type)));
  390. SS_PRINTF(("Server name : %.48s.", packet->Entries[j].Name));
  391. SS_PRINTF(("Server net : %02X%02X%02X%02X.",
  392. packet->Entries[j].Network[0],
  393. packet->Entries[j].Network[1],
  394. packet->Entries[j].Network[2],
  395. packet->Entries[j].Network[3]));
  396. SS_PRINTF(("Server node : %02X%02X%02X%02X%02X%02X.",
  397. packet->Entries[j].Node[0],
  398. packet->Entries[j].Node[1],
  399. packet->Entries[j].Node[2],
  400. packet->Entries[j].Node[3],
  401. packet->Entries[j].Node[4],
  402. packet->Entries[j].Node[5]));
  403. SS_PRINTF(("Server socket : %02X%02X.",
  404. packet->Entries[j].Socket[0],
  405. packet->Entries[j].Socket[1]));
  406. SS_PRINTF(("Server hops : %d.", GETUSHORT (&packet->Entries[j].HopCount)));
  407. }
  408. if ((j==0) && (count>=(DWORD)FIELD_OFFSET (SAP_BUFFER, Entries[0].Name)))
  409. SS_PRINTF(("Server type : %04X.", GETUSHORT (&packet->Entries[0].Type)));
  410. }
  411. }
  412. #endif
  413. */