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.

345 lines
11 KiB

  1. /*
  2. * Copyright (c) Microsoft Corporation
  3. *
  4. * Module Name :
  5. * bridge.c
  6. *
  7. * This contains the main worker thread that passes information between the clients
  8. * the Com port.
  9. *
  10. * Sadagopan Rajaram -- Oct 15, 1999
  11. *
  12. */
  13. #include "tcsrv.h"
  14. #include "tcsrvc.h"
  15. #include "proto.h"
  16. DWORD
  17. bridge(
  18. PCOM_PORT_INFO pComPortInfo
  19. )
  20. {
  21. NTSTATUS Status;
  22. PCONNECTION_INFO pTemp;
  23. DWORD waitStatus;
  24. int SocketStatus;
  25. Status = ReadFile(pComPortInfo->ComPortHandle,
  26. pComPortInfo->Buffer,
  27. MAX_QUEUE_SIZE,
  28. &(pComPortInfo->BytesRead),
  29. &(pComPortInfo->Overlapped)
  30. );
  31. if (!NT_SUCCESS(Status)) {
  32. TCDebugPrint(("Could not read from Com Port %x\n",GetLastError()));
  33. goto end;
  34. }
  35. while(1){
  36. MutexLock(pComPortInfo);
  37. // Get the new sockets that have been added to the port since
  38. // you were asleep. Send them the requested information and add
  39. // them to the connections list so that they are primed to receive
  40. // information.
  41. while(pComPortInfo->Sockets != NULL){
  42. pTemp = pComPortInfo->Sockets;
  43. SocketStatus = 1;
  44. if(pTemp->Flags){
  45. SocketStatus=GetBufferInfo(pTemp, pComPortInfo);
  46. pTemp->Flags = 0;
  47. }
  48. TCDebugPrint(("Got conn\n"));
  49. pComPortInfo->Sockets = pTemp->Next;
  50. pTemp->Next = pComPortInfo->Connections;
  51. pComPortInfo->Connections = pTemp;
  52. if (SocketStatus == SOCKET_ERROR) {
  53. TCDebugPrint(("something wrong with socket %d\n",
  54. WSAGetLastError()));
  55. CleanupSocket(pTemp);
  56. continue;
  57. }
  58. SocketStatus = WSARecv(pTemp->Socket,
  59. &(pTemp->Buffer),
  60. 1 ,
  61. &(pTemp->BytesRecvd),
  62. &(pTemp->Flags),
  63. &(pTemp->Overlapped),
  64. updateComPort
  65. );
  66. if (SocketStatus == SOCKET_ERROR ) {
  67. SocketStatus = WSAGetLastError();
  68. if (SocketStatus != WSA_IO_PENDING) {
  69. TCDebugPrint(("something wrong with socket %d\n",
  70. SocketStatus));
  71. CleanupSocket(pTemp);
  72. }
  73. }
  74. }
  75. MutexRelease(pComPortInfo);
  76. wait:
  77. waitStatus=NtWaitForMultipleObjects(4,
  78. pComPortInfo->Events,
  79. WaitAny,
  80. TRUE,
  81. NULL
  82. );
  83. if(waitStatus == WAIT_FAILED){
  84. TCDebugPrint(("Fatal Error %x", waitStatus));
  85. closesocket(MainSocket);
  86. goto end;
  87. }
  88. else{
  89. if(waitStatus == WAIT_IO_COMPLETION){
  90. goto wait;
  91. }
  92. waitStatus = waitStatus - WAIT_OBJECT_0;
  93. switch(waitStatus){
  94. case 0:
  95. Status = STATUS_SUCCESS;
  96. goto end;
  97. break;
  98. case 1:
  99. ResetEvent(pComPortInfo->Events[1]);
  100. break;
  101. case 2:
  102. ResetEvent(pComPortInfo->Events[2]);
  103. updateClients(pComPortInfo);
  104. goto wait;
  105. break;
  106. case 3:
  107. Status = STATUS_SUCCESS;
  108. ResetEvent(pComPortInfo->Events[3]);
  109. goto end;
  110. break;
  111. default:
  112. goto wait;
  113. break;
  114. }
  115. }
  116. }
  117. end:
  118. // Cancel the pending IRPs and close all the sockets.
  119. TCDebugPrint(("Cancelling all irps and shutting down the thread\n"));
  120. MutexLock(pComPortInfo);
  121. CancelIo(pComPortInfo->ComPortHandle);
  122. NtClose(pComPortInfo->ComPortHandle);
  123. while(pComPortInfo->Sockets != NULL){
  124. pTemp = pComPortInfo->Sockets;
  125. closesocket(pTemp->Socket);
  126. pComPortInfo->Sockets = pTemp->Next;
  127. pTemp->Next = NULL;
  128. TCFree(pTemp);
  129. }
  130. pTemp = pComPortInfo->Connections;
  131. while(pTemp != NULL){
  132. closesocket(pTemp->Socket);
  133. pTemp = pTemp->Next;
  134. }
  135. pComPortInfo->ShuttingDown = TRUE;
  136. if(pComPortInfo->Connections == NULL) SetEvent(pComPortInfo->TerminateEvent);
  137. MutexRelease(pComPortInfo);
  138. wait2:
  139. waitStatus=NtWaitForSingleObject(pComPortInfo->TerminateEvent,TRUE,NULL);
  140. if(waitStatus == WAIT_IO_COMPLETION){
  141. goto wait2;
  142. }
  143. TCDebugPrint(("End of COM port\n"));
  144. return Status;
  145. }
  146. VOID
  147. CALLBACK
  148. updateComPort(
  149. IN DWORD dwError,
  150. IN DWORD cbTransferred,
  151. IN LPWSAOVERLAPPED lpOverlapped,
  152. IN DWORD dwFlags
  153. )
  154. /*++
  155. Writes the data that it has gotten from the socket to all the connection
  156. that it currently has and to the com port.
  157. --*/
  158. {
  159. PCONNECTION_INFO pTemp = (PCONNECTION_INFO) lpOverlapped->hEvent;
  160. PCONNECTION_INFO pConn;
  161. PCOM_PORT_INFO pComPort;
  162. int Status;
  163. pComPort = pTemp->pComPortInfo;
  164. MutexLock(pComPort);
  165. if((cbTransferred == 0) && (dwError == 0)) {
  166. // For byte stream socket, this indicates graceful closure
  167. CleanupSocket(pTemp);
  168. MutexRelease(pComPort);
  169. return;
  170. }
  171. // If socket closed, remove it from the connection list.
  172. if(pComPort->ShuttingDown){
  173. CleanupSocket(pTemp);
  174. if(pComPort->Connections == NULL){
  175. SetEvent(pComPort->TerminateEvent);
  176. MutexRelease(pComPort);
  177. return;
  178. }
  179. MutexRelease(pComPort);
  180. return;
  181. }
  182. if (dwError != 0) {
  183. // Something wrong with the connection. Close the socket and
  184. // delete it from the listeners list.
  185. CleanupSocket(pTemp);
  186. MutexRelease(pComPort);
  187. return;
  188. }
  189. Status =WriteFile(pComPort->ComPortHandle,
  190. (pTemp->Buffer).buf,
  191. cbTransferred,
  192. &(pTemp->BytesRecvd),
  193. &(pComPort->WriteOverlapped)
  194. );
  195. if(!Status){
  196. if(GetLastError() != ERROR_IO_PENDING)
  197. TCDebugPrint(("Error writing to comport %d",GetLastError()));
  198. }
  199. Status = WSARecv(pTemp->Socket,
  200. &(pTemp->Buffer),
  201. 1 ,
  202. &(pTemp->BytesRecvd),
  203. &(pTemp->Flags),
  204. &(pTemp->Overlapped),
  205. updateComPort
  206. );
  207. if (Status == SOCKET_ERROR ) {
  208. Status = WSAGetLastError();
  209. if (Status != WSA_IO_PENDING) {
  210. TCDebugPrint(("something wrong with socket %d\n",
  211. Status));
  212. CleanupSocket(pTemp);
  213. }
  214. }
  215. MutexRelease(pComPort);
  216. return;
  217. }
  218. VOID
  219. updateClients(
  220. PCOM_PORT_INFO pComPortInfo
  221. )
  222. /*++
  223. Writes the data that it has gotten from the com port to all the connection
  224. that it currently has
  225. --*/
  226. {
  227. PCONNECTION_INFO pConn;
  228. BOOL Status;
  229. DWORD Error;
  230. NTSTATUS stat;
  231. if((pComPortInfo->Overlapped.InternalHigh == 0)||
  232. (!NT_SUCCESS(pComPortInfo->Overlapped.Internal))){
  233. TCDebugPrint(("Problem with Com Port %x\n", pComPortInfo->Overlapped.Internal));
  234. MutexLock(pComPortInfo);
  235. if(pComPortInfo->ShuttingDown){
  236. // will never occur because this is a procedure called from
  237. // the thread
  238. MutexRelease(pComPortInfo);
  239. return;
  240. }
  241. if (pComPortInfo->Overlapped.Internal == STATUS_CANCELLED){
  242. // something wrong, try reinitializing the com port
  243. // this thing happens every time the m/c on the other end
  244. // reboots. Pretty painful.Probably can improve this later.
  245. // Why should the reboot cause this com port
  246. // to go awry ??
  247. stat = NtClose(pComPortInfo->ComPortHandle);
  248. if(!NT_SUCCESS(stat)){
  249. TCDebugPrint(("Cannot close handle\n"));
  250. }
  251. stat = InitializeComPort(pComPortInfo);
  252. if(!NT_SUCCESS(stat)){
  253. TCDebugPrint(("Cannot reinitialize com port\n"));
  254. MutexRelease(pComPortInfo);
  255. return;
  256. }
  257. }
  258. Status = ReadFile(pComPortInfo->ComPortHandle,
  259. pComPortInfo->Buffer,
  260. MAX_QUEUE_SIZE,
  261. &(pComPortInfo->BytesRead),
  262. &(pComPortInfo->Overlapped)
  263. );
  264. if(Status == 0){
  265. if ((Error = GetLastError()) != ERROR_IO_PENDING) {
  266. TCDebugPrint(("Error = %d\n", Error));
  267. }
  268. }
  269. MutexRelease(pComPortInfo);
  270. return;
  271. }
  272. MutexLock(pComPortInfo);
  273. Enqueue(pComPortInfo);
  274. pConn = pComPortInfo->Connections;
  275. while(pConn!=NULL){
  276. send(pConn->Socket,
  277. pComPortInfo->Buffer,
  278. (int)pComPortInfo->Overlapped.InternalHigh,
  279. 0
  280. );
  281. pConn = pConn->Next;
  282. }
  283. Status = ReadFile(pComPortInfo->ComPortHandle,
  284. pComPortInfo->Buffer,
  285. MAX_QUEUE_SIZE,
  286. &(pComPortInfo->BytesRead),
  287. &(pComPortInfo->Overlapped)
  288. );
  289. if (Status == 0) {
  290. if((Error=GetLastError())!= ERROR_IO_PENDING){
  291. TCDebugPrint(("Problem with Com Port %x\n", Error));
  292. }
  293. }
  294. MutexRelease(pComPortInfo);
  295. return;
  296. }
  297. VOID CleanupSocket(
  298. PCONNECTION_INFO pConn
  299. )
  300. {
  301. PCOM_PORT_INFO pTemp;
  302. PCONNECTION_INFO pPrevConn;
  303. // Assume that the structure is locked earlier.
  304. // the socket connection is closed when this occurs.
  305. // We free the socket either if the TCP port on the
  306. // client end has died or we are deleting this com port.
  307. pTemp = pConn->pComPortInfo;
  308. if(pConn == pTemp->Connections) {
  309. pTemp->Connections = pConn->Next;
  310. }
  311. else{
  312. pPrevConn = pTemp->Connections;
  313. while((pPrevConn !=NULL) &&(pPrevConn->Next != pConn)){
  314. pPrevConn=pPrevConn->Next;
  315. }
  316. if(pPrevConn == NULL) return;
  317. pPrevConn->Next = pConn->Next;
  318. }
  319. pConn->Next = NULL;
  320. TCFree(pConn);
  321. }