Source code of Windows XP (NT5)
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.

405 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. ipxwan.c
  5. Abstract:
  6. ipxwan control
  7. Author:
  8. Stefan Solomon 02/06/1996
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. ULONG EnableUnnumberedWanLinks;
  14. HANDLE WorkerThreadHandle;
  15. // IPXCP Entry Points
  16. DWORD
  17. (WINAPI *IpxcpGetWanNetNumber)(IN OUT PUCHAR Network,
  18. IN OUT PULONG AllocatedNetworkIndexp,
  19. IN ULONG InterfaceType);
  20. VOID
  21. (WINAPI *IpxcpReleaseWanNetNumber)(ULONG AllocatedNetworkIndex);
  22. DWORD
  23. (WINAPI *IpxcpConfigDone)(ULONG ConnectionId,
  24. PUCHAR Network,
  25. PUCHAR LocalNode,
  26. PUCHAR RemoteNode,
  27. BOOL Success);
  28. VOID
  29. (WINAPI *IpxcpGetInternalNetNumber)(PUCHAR Network);
  30. ULONG
  31. (WINAPI *IpxcpGetInterfaceType)(ULONG ConnectionId);
  32. DWORD
  33. (WINAPI *IpxcpGetRemoteNode)(ULONG ConnectionId,
  34. PUCHAR RemoteNode);
  35. BOOL
  36. (WINAPI *IpxcpIsRoute)(PUCHAR Network);
  37. // worker thread waitable objects
  38. HANDLE hWaitableObject[MAX_WAITABLE_OBJECTS];
  39. VOID
  40. ProcessWorkItem(VOID);
  41. VOID
  42. WorkerThread(VOID);
  43. VOID
  44. ProcessDequeuedIoPacket(DWORD ErrorCode,
  45. DWORD BytesTransferred,
  46. LPOVERLAPPED Overlappedp);
  47. CRITICAL_SECTION DbaseCritSec;
  48. CRITICAL_SECTION QueuesCritSec;
  49. LIST_ENTRY WorkersQueue;
  50. // worker thread object handlers
  51. typedef VOID (*WOBJECT_HANDLER)(VOID);
  52. WOBJECT_HANDLER WaitableObjectHandler[MAX_WAITABLE_OBJECTS] = {
  53. AdapterNotification, // ADAPTER_NOTIFICATION_EVENT
  54. ProcessWorkItem, // WORKERS_QUEUE_EVENT
  55. ProcessTimerQueue // TIMER_HANDLE
  56. };
  57. BOOLEAN Active;
  58. TCHAR ModuleName[MAX_PATH+1];
  59. BOOL WINAPI
  60. IpxWanDllEntry(HINSTANCE hInstDll,
  61. DWORD fdwReason,
  62. LPVOID pReserved)
  63. {
  64. switch (fdwReason)
  65. {
  66. case DLL_PROCESS_ATTACH:
  67. GetModuleFileName (hInstDll, ModuleName,
  68. sizeof (ModuleName)/sizeof (ModuleName[0]));
  69. // Create the adapters hash table lock
  70. InitializeCriticalSection(&DbaseCritSec);
  71. // Create the queues lock
  72. InitializeCriticalSection(&QueuesCritSec);
  73. StartTracing();
  74. break;
  75. case DLL_PROCESS_DETACH:
  76. StopTracing ();
  77. // delete the database lock
  78. DeleteCriticalSection(&DbaseCritSec);
  79. // delete the queues lock
  80. DeleteCriticalSection(&QueuesCritSec);
  81. break;
  82. default:
  83. break;
  84. }
  85. return TRUE;
  86. }
  87. /*++
  88. Function: IpxwanBind
  89. Descr: called by IPXCP to initialize the IPXWAN module
  90. --*/
  91. DWORD
  92. IPXWAN_BIND_ENTRY_POINT(PIPXWAN_INTERFACE IpxwanIfp)
  93. {
  94. DWORD threadid, i;
  95. HANDLE ThreadHandle;
  96. Trace(INIT_TRACE, "IpxwanBind: Entered\n");
  97. EnableUnnumberedWanLinks = IpxwanIfp->EnableUnnumberedWanLinks;
  98. IpxcpGetWanNetNumber = IpxwanIfp->IpxcpGetWanNetNumber;
  99. IpxcpReleaseWanNetNumber = IpxwanIfp->IpxcpReleaseWanNetNumber;
  100. IpxcpConfigDone = IpxwanIfp->IpxcpConfigDone;
  101. IpxcpGetInternalNetNumber = IpxwanIfp->IpxcpGetInternalNetNumber;
  102. IpxcpGetInterfaceType = IpxwanIfp->IpxcpGetInterfaceType;
  103. IpxcpGetRemoteNode = IpxwanIfp->IpxcpGetRemoteNode;
  104. IpxcpIsRoute = IpxwanIfp->IpxcpIsRoute;
  105. // create the worker thread's waitable objects array
  106. // for the ipxwan worker thread
  107. for(i=0; i<MAX_EVENTS; i++) {
  108. if((hWaitableObject[i] = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
  109. return ERROR_CAN_NOT_COMPLETE;
  110. }
  111. }
  112. if((hWaitableObject[TIMER_HANDLE] = CreateWaitableTimer(NULL, FALSE, NULL)) == NULL) {
  113. return ERROR_CAN_NOT_COMPLETE;
  114. }
  115. //
  116. // init all the queues
  117. //
  118. InitializeListHead(&WorkersQueue);
  119. InitializeListHead(&TimerQueue);
  120. // create the workers work items heap
  121. if(CreateWorkItemsManager() != NO_ERROR) {
  122. goto ErrorExit;
  123. }
  124. // open the IpxWan socket for I/O
  125. if(OpenIpxWanSocket() != NO_ERROR) {
  126. Trace(INIT_TRACE, "Cannot open IPXWAN socket\n");
  127. goto ErrorExit;
  128. }
  129. if(! BindIoCompletionCallback(IpxWanSocketHandle,
  130. ProcessDequeuedIoPacket, 0)) {
  131. Trace(INIT_TRACE, "Cannot associate IO CompletionPort\n");
  132. goto ErrorExit;
  133. }
  134. if(StartAdapterManager() != NO_ERROR) {
  135. Trace(INIT_TRACE, "Cannot create adapter config port\n");
  136. goto ErrorExit;
  137. }
  138. // create the Worker thread
  139. if ((WorkerThreadHandle = CreateThread(
  140. (LPSECURITY_ATTRIBUTES) NULL,
  141. 0,
  142. (LPTHREAD_START_ROUTINE) WorkerThread,
  143. NULL,
  144. 0,
  145. &threadid)) == NULL) {
  146. // !!! log error cannot create the worker thread !!!
  147. goto ErrorExit;
  148. }
  149. Active = TRUE;
  150. return NO_ERROR;
  151. ErrorExit:
  152. return ERROR_CAN_NOT_COMPLETE;
  153. }
  154. VOID
  155. IPXWAN_UNBIND_ENTRY_POINT (VOID) {
  156. Active = FALSE;
  157. SetEvent (hWaitableObject[WORKERS_QUEUE_EVENT]);
  158. Trace(INIT_TRACE, "IpxwanUnBind: Finished\n");
  159. }
  160. VOID
  161. WorkerThread(VOID)
  162. {
  163. INT i;
  164. DWORD rc;
  165. DWORD signaled_object;
  166. HINSTANCE hModule = LoadLibrary (ModuleName);
  167. Trace(INIT_TRACE, "IpxwanWorker: Started\n");
  168. StartReceiver();
  169. while(TRUE)
  170. {
  171. rc = WaitForMultipleObjectsEx(
  172. MAX_WAITABLE_OBJECTS,
  173. hWaitableObject,
  174. FALSE, // wait any
  175. INFINITE, // timeout
  176. TRUE // wait alertable, so we can run APCs
  177. );
  178. if (Active) {
  179. ASSERT (((int)rc>=WAIT_OBJECT_0) && (rc<WAIT_OBJECT_0+MAX_WAITABLE_OBJECTS));
  180. signaled_object = rc - WAIT_OBJECT_0;
  181. if(signaled_object < MAX_WAITABLE_OBJECTS) {
  182. // invoke the event handler
  183. (*WaitableObjectHandler[signaled_object])();
  184. }
  185. else
  186. SleepEx (3000, TRUE);
  187. }
  188. else
  189. break;
  190. }
  191. StopAdapterManager ();
  192. CloseIpxWanSocket ();
  193. DestroyWorkItemsManager ();
  194. for(i=0; i<MAX_WAITABLE_OBJECTS; i++) {
  195. CloseHandle (hWaitableObject[i]);
  196. }
  197. Trace(INIT_TRACE, "IpxwanWorker: Finished\n");
  198. FreeLibraryAndExitThread (hModule, 0);
  199. }
  200. VOID
  201. ProcessDequeuedIoPacket(DWORD ErrorCode,
  202. DWORD BytesTransferred,
  203. LPOVERLAPPED Overlappedp)
  204. {
  205. PWORK_ITEM wip;
  206. DWORD nBytes;
  207. wip = CONTAINING_RECORD(Overlappedp, WORK_ITEM, Overlapped);
  208. IpxAdjustIoCompletionParams (Overlappedp, &nBytes, &wip->IoCompletionStatus);
  209. switch(wip->Type) {
  210. case RECEIVE_PACKET_TYPE:
  211. ReceiveComplete(wip);
  212. break;
  213. default:
  214. SendComplete(wip);
  215. break;
  216. }
  217. }
  218. VOID
  219. ProcessWorkItem(VOID)
  220. {
  221. PLIST_ENTRY lep;
  222. PWORK_ITEM wip;
  223. PACB acbp;
  224. ACQUIRE_QUEUES_LOCK;
  225. while(!IsListEmpty(&WorkersQueue)) {
  226. lep = RemoveHeadList(&WorkersQueue);
  227. wip = CONTAINING_RECORD(lep, WORK_ITEM, Linkage);
  228. RELEASE_QUEUES_LOCK;
  229. switch(wip->Type) {
  230. case RECEIVE_PACKET_TYPE:
  231. ACQUIRE_DATABASE_LOCK;
  232. if((acbp = GetAdapterByIndex(wip->AdapterIndex)) != NULL) {
  233. ACQUIRE_ADAPTER_LOCK(acbp);
  234. RELEASE_DATABASE_LOCK;
  235. ProcessReceivedPacket(acbp, wip);
  236. RELEASE_ADAPTER_LOCK(acbp);
  237. }
  238. else
  239. {
  240. RELEASE_DATABASE_LOCK;
  241. }
  242. RepostRcvPacket(wip);
  243. break;
  244. default:
  245. // these are ReXmit packets referencing the adapter via ACB ptr
  246. acbp = wip->acbp;
  247. ACQUIRE_ADAPTER_LOCK(acbp);
  248. acbp->RefCount--;
  249. switch(wip->Type) {
  250. case SEND_PACKET_TYPE:
  251. ProcessReXmitPacket(wip);
  252. break;
  253. case WITIMER_TYPE:
  254. ProcessTimeout(wip);
  255. break;
  256. default:
  257. SS_ASSERT(FALSE);
  258. break;
  259. }
  260. if(acbp->Discarded && (acbp->RefCount == 0)) {
  261. ACQUIRE_DATABASE_LOCK;
  262. // remove the adapter from the discarded list
  263. RemoveEntryList(&acbp->Linkage);
  264. RELEASE_DATABASE_LOCK;
  265. Trace(ADAPTER_TRACE, "ProcessWorkItem: adpt# %d not referenced and discarded. Free CB",
  266. acbp->AdapterIndex);
  267. DeleteCriticalSection(&acbp->AdapterLock);
  268. GlobalFree(acbp);
  269. }
  270. else
  271. {
  272. RELEASE_ADAPTER_LOCK(acbp);
  273. }
  274. }
  275. ACQUIRE_QUEUES_LOCK;
  276. }
  277. RELEASE_QUEUES_LOCK;
  278. }