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.

369 lines
12 KiB

  1. /***************************************************************************
  2. *
  3. * File: h245wstx.c
  4. *
  5. * INTEL Corporation Proprietary Information
  6. * Copyright (c) 1996 Intel Corporation.
  7. *
  8. * This listing is supplied under the terms of a license agreement
  9. * with INTEL Corporation and may not be used, copied, nor disclosed
  10. * except in accordance with the terms of that agreement.
  11. *
  12. ***************************************************************************
  13. *
  14. * $Workfile: h245wstx.cpp $
  15. * $Revision: 2.4 $
  16. * $Modtime: 30 Jan 1997 17:15:58 $
  17. * $Log: S:/STURGEON/SRC/H245WS/VCS/h245wstx.cpv $
  18. *
  19. * Rev 2.4 30 Jan 1997 17:18:02 EHOWARDX
  20. * Fixed bug in trace message - need to do trace before
  21. * calling shutdown() sent shutdown clears error retrieved
  22. * by WSAGetLastError().
  23. *
  24. * Rev 2.3 14 Jan 1997 15:49:00 EHOWARDX
  25. * Changed TryRecv() and TrySend() to check for WSAECONNRESET and
  26. * WSAECONNABORT return from recv() and send() and act accordingly.
  27. *
  28. * Rev 2.2 19 Dec 1996 18:55:12 SBELL1
  29. * took out tag comments
  30. *
  31. * Rev 2.1 Dec 13 1996 17:33:24 plantz
  32. * moved #ifdef _cplusplus to after include files
  33. //
  34. // Rev 1.1 13 Dec 1996 12:12:02 SBELL1
  35. // moved #ifdef _cplusplus to after include files
  36. //
  37. // Rev 1.0 11 Dec 1996 13:41:54 SBELL1
  38. // Initial revision.
  39. *
  40. * Rev 1.16 May 28 1996 18:14:40 plantz
  41. * Change error codes to use HRESULT. Propogate Winsock errors where appropriate
  42. *
  43. * Rev 1.15 17 May 1996 16:49:34 EHOWARDX
  44. * Shutdown fix.
  45. *
  46. * Rev 1.14 09 May 1996 18:33:20 EHOWARDX
  47. *
  48. * Changes to build with new LINKAPI.H.
  49. *
  50. * Rev 1.13 29 Apr 1996 16:53:28 EHOWARDX
  51. *
  52. * Added trace statement.
  53. *
  54. * Rev 1.12 Apr 29 1996 14:04:38 plantz
  55. * Call NotifyWrite instead of ProcessQueuedSends.
  56. *
  57. * Rev 1.11 Apr 29 1996 12:15:04 plantz
  58. * Change tpkt header to include header size in packet length.
  59. * Assert that message length does not exceed INT_MAX.
  60. * .
  61. *
  62. * Rev 1.10 27 Apr 1996 14:46:24 EHOWARDX
  63. * Parenthesized TrySend() return.
  64. *
  65. * Rev 1.9 Apr 24 1996 16:41:30 plantz
  66. * Merge 1.5.1.0 with 1.8 (changes for winsock 1).
  67. *
  68. * Rev 1.5.1.0 Apr 24 1996 16:22:22 plantz
  69. * Change to not use overlapped I/O (for winsock 1).
  70. *
  71. * Rev 1.5 01 Apr 1996 14:20:44 unknown
  72. * Shutdown redesign.
  73. *
  74. * Rev 1.4 19 Mar 1996 20:18:20 EHOWARDX
  75. *
  76. * Redesigned shutdown.
  77. *
  78. * Rev 1.3 18 Mar 1996 19:08:32 EHOWARDX
  79. * Fixed shutdown; eliminated TPKT/WSCB dependencies.
  80. * Define TPKT to put TPKT/WSCB dependencies back in.
  81. *
  82. * Rev 1.2 14 Mar 1996 17:02:02 EHOWARDX
  83. *
  84. * NT4.0 testing; got rid of HwsAssert(); got rid of TPKT/WSCB.
  85. *
  86. * Rev 1.1 09 Mar 1996 21:12:30 EHOWARDX
  87. * Fixes as result of testing.
  88. *
  89. * Rev 1.0 08 Mar 1996 20:20:06 unknown
  90. * Initial revision.
  91. *
  92. ***************************************************************************/
  93. #define LINKDLL_EXPORT
  94. #pragma warning ( disable : 4115 4201 4214 4514 )
  95. #undef _WIN32_WINNT // override bogus platform definition in our common build environment
  96. #include "precomp.h"
  97. #include <limits.h>
  98. //#include <winsock.h>
  99. #include "queue.h"
  100. #include "linkapi.h"
  101. #include "h245ws.h"
  102. #include "tstable.h"
  103. #if defined(__cplusplus)
  104. extern "C"
  105. {
  106. #endif // (__cplusplus)
  107. // If we are using not using the Unicode version of the IRS display utility, then
  108. // redefine the __TEXT macro to do nothing.
  109. #ifndef UNICODE_TRACE
  110. #undef __TEXT
  111. #define __TEXT(x) x
  112. #endif
  113. extern TSTable<HWSINST>* gpInstanceTable; // global ptr to the instance table
  114. static void SetupTPKTHeader(BYTE *tpkt_header, DWORD length);
  115. /*++
  116. Description:
  117. Attempt to send
  118. Arguments:
  119. pHws - Pointer to context for "connection"
  120. pReq - Pointer to I/O request structure
  121. Return Value:
  122. SUCCESS - Successfully started send.
  123. LINK_SEND_ERROR_WOULD_BLOCK -
  124. LINK_SEND_ERROR_CLOSED - The socket was gracefully closed.
  125. LINK_SEND_ERROR_ERROR - Error receiving data.
  126. --*/
  127. static HRESULT
  128. TrySend(IN PHWSINST pHws, IN const char *data, IN int length, IN OUT int *total_bytes_sent)
  129. {
  130. int requested_length = length - *total_bytes_sent;
  131. int send_result = send(pHws->hws_Socket, data+*total_bytes_sent, requested_length, 0);
  132. if (send_result == SOCKET_ERROR)
  133. {
  134. int err = WSAGetLastError();
  135. switch (err)
  136. {
  137. case WSAEWOULDBLOCK:
  138. return LINK_SEND_WOULD_BLOCK;
  139. case WSAECONNABORTED:
  140. case WSAECONNRESET:
  141. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  142. __TEXT("TrySend: send() returned %s"),
  143. SocketErrorText());
  144. if (pHws->hws_uState == HWS_CONNECTED)
  145. {
  146. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  147. __TEXT("TrySend: calling shutdown"));
  148. if (shutdown(pHws->hws_Socket, 1) == SOCKET_ERROR)
  149. {
  150. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  151. __TEXT("TrySend: shutdown() returned %s"),
  152. SocketErrorText());
  153. }
  154. pHws->hws_uState = HWS_CLOSING;
  155. }
  156. return MAKE_WINSOCK_ERROR(err);
  157. default:
  158. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  159. __TEXT("TrySend: send() returned %s"),
  160. SocketErrorText());
  161. return MAKE_WINSOCK_ERROR(err);
  162. } // switch
  163. }
  164. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("TrySend: send returned %d"), send_result);
  165. *total_bytes_sent += send_result;
  166. return (send_result == requested_length) ? NOERROR : LINK_SEND_WOULD_BLOCK;
  167. }
  168. static HRESULT
  169. SendStart(IN PHWSINST pHws, IN PREQUEST pReq)
  170. {
  171. HRESULT nResult = NOERROR;
  172. // Sanity checks
  173. HWSASSERT(pHws != NULL);
  174. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  175. HWSASSERT(pReq != NULL);
  176. HWSASSERT(pReq->req_dwMagic == SEND_REQUEST_MAGIC);
  177. HWSASSERT(pReq->req_pHws == pHws);
  178. // Send the header first; if that succeeds send the client data
  179. if (pReq->req_header_bytes_done < TPKT_HEADER_SIZE)
  180. {
  181. nResult = TrySend(pHws,
  182. (const char *)pReq->req_TpktHeader,
  183. TPKT_HEADER_SIZE,
  184. &pReq->req_header_bytes_done);
  185. }
  186. if (nResult == NOERROR)
  187. {
  188. nResult = TrySend(pHws,
  189. (const char *)pReq->req_client_data,
  190. pReq->req_client_length,
  191. &pReq->req_client_bytes_done);
  192. }
  193. return nResult;
  194. } // SendStart()
  195. void
  196. ProcessQueuedSends(IN PHWSINST pHws)
  197. {
  198. register PREQUEST pReq;
  199. register DWORD dwPhysicalId = pHws->hws_dwPhysicalId;
  200. HWSASSERT(pHws != NULL);
  201. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  202. HWSASSERT(pHws->hws_uState <= HWS_CONNECTED);
  203. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("ProcessQueuedSends"));
  204. while ((pReq = (PREQUEST)QRemove(pHws->hws_pSendQueue)) != NULL)
  205. {
  206. switch (SendStart(pHws, pReq))
  207. {
  208. case NOERROR:
  209. // Call Send callback
  210. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  211. LINK_SEND_COMPLETE,
  212. pReq->req_client_data,
  213. pReq->req_client_bytes_done);
  214. // Free the I/O request structure
  215. MemFree(pReq);
  216. // Check to see if callback deallocated our instance or state changed
  217. if(gpInstanceTable->Lock(dwPhysicalId) == NULL)
  218. return;
  219. gpInstanceTable->Unlock(dwPhysicalId);
  220. if(pHws->hws_uState > HWS_CONNECTED)
  221. return;
  222. break;
  223. default:
  224. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_WARNING,
  225. __TEXT("ProcessQueuedSends: SendStart() failed"));
  226. // Fall-through to next case is intentional
  227. case LINK_SEND_WOULD_BLOCK:
  228. // The send would have blocked; we need to requeue the I/O request
  229. // and wait for a FD_WRITE network event.
  230. // If any part of the data was sent, the bytes_done field has been updated.
  231. if (QInsertAtHead(pHws->hws_pSendQueue, pReq) == FALSE)
  232. {
  233. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_CRITICAL,
  234. __TEXT("ProcessQueuedSends: QInsertAtHead() failed"));
  235. }
  236. return;
  237. } // switch
  238. } // while
  239. } // ProcessQueuedSends()
  240. /**************************************************************************
  241. ** Function : datalinkSendRequest
  242. ** Description : Fills header/tail of buffer and posts buffer to H.223
  243. ***************************************************************************/
  244. LINKDLL HRESULT datalinkSendRequest( DWORD dwPhysicalId,
  245. PBYTE pbyDataBuf,
  246. DWORD dwLength)
  247. {
  248. register PHWSINST pHws;
  249. register PREQUEST pReq;
  250. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("datalinkSendRequest"));
  251. pHws = gpInstanceTable->Lock(dwPhysicalId);
  252. if (pHws == NULL)
  253. {
  254. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  255. __TEXT("datalinkSendRequest: dwPhysicalId not found"));
  256. return LINK_INVALID_INSTANCE;
  257. }
  258. if (pHws->hws_uState > HWS_CONNECTED)
  259. {
  260. HWSTRACE1(dwPhysicalId, HWS_ERROR,
  261. __TEXT("datalinkSendRequest: state = %d"), pHws->hws_uState);
  262. gpInstanceTable->Unlock(dwPhysicalId);
  263. return LINK_INVALID_STATE;
  264. }
  265. // Allocate request structure
  266. pReq = (PREQUEST) MemAlloc(sizeof(*pReq));
  267. if (pReq == NULL)
  268. {
  269. HWSTRACE0(dwPhysicalId, HWS_WARNING,
  270. __TEXT("datalinkSendRequest: could not allocate request buffer"));
  271. gpInstanceTable->Unlock(dwPhysicalId);
  272. return LINK_MEM_FAILURE;
  273. }
  274. // The current implementation requires that the size of each message
  275. // fit in a signed int (because that is what Winsock supports in a
  276. // single send). If it is necessary to send larger messages,
  277. // TrySend must be changed to limit the size in each send call, and
  278. // loop until all the data is sent. This ASSERT could then be removed.
  279. HWSASSERT(dwLength <= INT_MAX);
  280. pReq->req_pHws = pHws;
  281. pReq->req_client_data = pbyDataBuf;
  282. pReq->req_client_length = (int)dwLength;
  283. pReq->req_client_bytes_done= 0;
  284. pReq->req_dwMagic = SEND_REQUEST_MAGIC;
  285. // Format TPKT header
  286. SetupTPKTHeader(pReq->req_TpktHeader, dwLength);
  287. pReq->req_header_bytes_done = 0;
  288. if (QInsert(pHws->hws_pSendQueue, pReq) == FALSE)
  289. {
  290. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_CRITICAL,
  291. __TEXT("datalinkSendRequest: QInsert() failed"));
  292. gpInstanceTable->Unlock(dwPhysicalId);
  293. MemFree(pReq);
  294. return LINK_SEND_NOBUFF;
  295. }
  296. if (pHws->hws_uState == HWS_CONNECTED)
  297. NotifyWrite(pHws);
  298. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("datalinkSendRequest: succeeded"));
  299. gpInstanceTable->Unlock(dwPhysicalId);
  300. return NOERROR;
  301. } // datalinkSendRequest
  302. static void SetupTPKTHeader(BYTE *tpkt_header, DWORD length)
  303. {
  304. length += TPKT_HEADER_SIZE;
  305. // TPKT requires that the packet size fit in two bytes.
  306. HWSASSERT(length < (1L << 16));
  307. tpkt_header[0] = TPKT_VERSION;
  308. tpkt_header[1] = 0;
  309. tpkt_header[2] = (BYTE)(length >> 8);
  310. tpkt_header[3] = (BYTE)length;
  311. }
  312. #if defined(__cplusplus)
  313. }
  314. #endif // (__cplusplus)