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.

375 lines
11 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. #ifndef STRICT
  94. #define STRICT
  95. #endif // not defined STRICT
  96. #define LINKDLL_EXPORT
  97. #pragma warning ( disable : 4115 4201 4214 4514 )
  98. #undef _WIN32_WINNT // override bogus platform definition in our common build environment
  99. #include <nt.h>
  100. #include <ntrtl.h>
  101. #include <nturtl.h>
  102. #include <limits.h>
  103. //#include <winsock.h>
  104. #include <windows.h>
  105. #include "queue.h"
  106. #include "linkapi.h"
  107. #include "h245ws.h"
  108. #include "tstable.h"
  109. #if defined(__cplusplus)
  110. extern "C"
  111. {
  112. #endif // (__cplusplus)
  113. // If we are using not using the Unicode version of the IRS display utility, then
  114. // redefine the __TEXT macro to do nothing.
  115. #ifndef UNICODE_TRACE
  116. #undef __TEXT
  117. #define __TEXT(x) x
  118. #endif
  119. extern TSTable<HWSINST>* gpInstanceTable; // global ptr to the instance table
  120. static void SetupTPKTHeader(BYTE *tpkt_header, DWORD length);
  121. /*++
  122. Description:
  123. Attempt to send
  124. Arguments:
  125. pHws - Pointer to context for "connection"
  126. pReq - Pointer to I/O request structure
  127. Return Value:
  128. SUCCESS - Successfully started send.
  129. LINK_SEND_ERROR_WOULD_BLOCK -
  130. LINK_SEND_ERROR_CLOSED - The socket was gracefully closed.
  131. LINK_SEND_ERROR_ERROR - Error receiving data.
  132. --*/
  133. static HRESULT
  134. TrySend(IN PHWSINST pHws, IN const char *data, IN int length, IN OUT int *total_bytes_sent)
  135. {
  136. int requested_length = length - *total_bytes_sent;
  137. int send_result = send(pHws->hws_Socket, data+*total_bytes_sent, requested_length, 0);
  138. if (send_result == SOCKET_ERROR)
  139. {
  140. int err = WSAGetLastError();
  141. switch (err)
  142. {
  143. case WSAEWOULDBLOCK:
  144. return LINK_SEND_WOULD_BLOCK;
  145. case WSAECONNABORTED:
  146. case WSAECONNRESET:
  147. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  148. __TEXT("TrySend: send() returned %s"),
  149. SocketErrorText());
  150. if (pHws->hws_uState == HWS_CONNECTED)
  151. {
  152. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  153. __TEXT("TrySend: calling shutdown"));
  154. if (shutdown(pHws->hws_Socket, 1) == SOCKET_ERROR)
  155. {
  156. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  157. __TEXT("TrySend: shutdown() returned %s"),
  158. SocketErrorText());
  159. }
  160. pHws->hws_uState = HWS_CLOSING;
  161. }
  162. return MAKE_WINSOCK_ERROR(err);
  163. default:
  164. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  165. __TEXT("TrySend: send() returned %s"),
  166. SocketErrorText());
  167. return MAKE_WINSOCK_ERROR(err);
  168. } // switch
  169. }
  170. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("TrySend: send returned %d"), send_result);
  171. *total_bytes_sent += send_result;
  172. return (send_result == requested_length) ? NOERROR : LINK_SEND_WOULD_BLOCK;
  173. }
  174. static HRESULT
  175. SendStart(IN PHWSINST pHws, IN PREQUEST pReq)
  176. {
  177. HRESULT nResult = NOERROR;
  178. // Sanity checks
  179. HWSASSERT(pHws != NULL);
  180. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  181. HWSASSERT(pReq != NULL);
  182. HWSASSERT(pReq->req_dwMagic == SEND_REQUEST_MAGIC);
  183. HWSASSERT(pReq->req_pHws == pHws);
  184. // Send the header first; if that succeeds send the client data
  185. if (pReq->req_header_bytes_done < TPKT_HEADER_SIZE)
  186. {
  187. nResult = TrySend(pHws,
  188. (const char *)pReq->req_TpktHeader,
  189. TPKT_HEADER_SIZE,
  190. &pReq->req_header_bytes_done);
  191. }
  192. if (nResult == NOERROR)
  193. {
  194. nResult = TrySend(pHws,
  195. (const char *)pReq->req_client_data,
  196. pReq->req_client_length,
  197. &pReq->req_client_bytes_done);
  198. }
  199. return nResult;
  200. } // SendStart()
  201. void
  202. ProcessQueuedSends(IN PHWSINST pHws)
  203. {
  204. register PREQUEST pReq;
  205. register DWORD dwPhysicalId = pHws->hws_dwPhysicalId;
  206. HWSASSERT(pHws != NULL);
  207. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  208. HWSASSERT(pHws->hws_uState <= HWS_CONNECTED);
  209. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("ProcessQueuedSends"));
  210. while ((pReq = (PREQUEST)QRemove(pHws->hws_pSendQueue)) != NULL)
  211. {
  212. switch (SendStart(pHws, pReq))
  213. {
  214. case NOERROR:
  215. // Call Send callback
  216. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  217. LINK_SEND_COMPLETE,
  218. pReq->req_client_data,
  219. pReq->req_client_bytes_done);
  220. // Free the I/O request structure
  221. HWSFREE(pReq);
  222. // Check to see if callback deallocated our instance or state changed
  223. if(gpInstanceTable->Lock(dwPhysicalId) == NULL)
  224. return;
  225. gpInstanceTable->Unlock(dwPhysicalId);
  226. if(pHws->hws_uState > HWS_CONNECTED)
  227. return;
  228. break;
  229. default:
  230. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_WARNING,
  231. __TEXT("ProcessQueuedSends: SendStart() failed"));
  232. // Fall-through to next case is intentional
  233. case LINK_SEND_WOULD_BLOCK:
  234. // The send would have blocked; we need to requeue the I/O request
  235. // and wait for a FD_WRITE network event.
  236. // If any part of the data was sent, the bytes_done field has been updated.
  237. if (QInsertAtHead(pHws->hws_pSendQueue, pReq) == FALSE)
  238. {
  239. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_CRITICAL,
  240. __TEXT("ProcessQueuedSends: QInsertAtHead() failed"));
  241. }
  242. return;
  243. } // switch
  244. } // while
  245. } // ProcessQueuedSends()
  246. /**************************************************************************
  247. ** Function : datalinkSendRequest
  248. ** Description : Fills header/tail of buffer and posts buffer to H.223
  249. ***************************************************************************/
  250. LINKDLL HRESULT datalinkSendRequest( DWORD dwPhysicalId,
  251. PBYTE pbyDataBuf,
  252. DWORD dwLength)
  253. {
  254. register PHWSINST pHws;
  255. register PREQUEST pReq;
  256. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("datalinkSendRequest"));
  257. pHws = gpInstanceTable->Lock(dwPhysicalId);
  258. if (pHws == NULL)
  259. {
  260. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  261. __TEXT("datalinkSendRequest: dwPhysicalId not found"));
  262. return LINK_INVALID_INSTANCE;
  263. }
  264. if (pHws->hws_uState > HWS_CONNECTED)
  265. {
  266. HWSTRACE1(dwPhysicalId, HWS_ERROR,
  267. __TEXT("datalinkSendRequest: state = %d"), pHws->hws_uState);
  268. gpInstanceTable->Unlock(dwPhysicalId);
  269. return LINK_INVALID_STATE;
  270. }
  271. // Allocate request structure
  272. pReq = (PREQUEST) HWSMALLOC(sizeof(*pReq));
  273. if (pReq == NULL)
  274. {
  275. HWSTRACE0(dwPhysicalId, HWS_WARNING,
  276. __TEXT("datalinkSendRequest: could not allocate request buffer"));
  277. gpInstanceTable->Unlock(dwPhysicalId);
  278. return LINK_MEM_FAILURE;
  279. }
  280. // The current implementation requires that the size of each message
  281. // fit in a signed int (because that is what Winsock supports in a
  282. // single send). If it is necessary to send larger messages,
  283. // TrySend must be changed to limit the size in each send call, and
  284. // loop until all the data is sent. This assert could then be removed.
  285. HWSASSERT(dwLength <= INT_MAX);
  286. pReq->req_pHws = pHws;
  287. pReq->req_client_data = pbyDataBuf;
  288. pReq->req_client_length = (int)dwLength;
  289. pReq->req_client_bytes_done= 0;
  290. pReq->req_dwMagic = SEND_REQUEST_MAGIC;
  291. // Format TPKT header
  292. SetupTPKTHeader(pReq->req_TpktHeader, dwLength);
  293. pReq->req_header_bytes_done = 0;
  294. if (QInsert(pHws->hws_pSendQueue, pReq) == FALSE)
  295. {
  296. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_CRITICAL,
  297. __TEXT("datalinkSendRequest: QInsert() failed"));
  298. gpInstanceTable->Unlock(dwPhysicalId);
  299. return LINK_SEND_NOBUFF;
  300. }
  301. if (pHws->hws_uState == HWS_CONNECTED)
  302. NotifyWrite(pHws);
  303. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("datalinkSendRequest: succeeded"));
  304. gpInstanceTable->Unlock(dwPhysicalId);
  305. return NOERROR;
  306. } // datalinkSendRequest
  307. static void SetupTPKTHeader(BYTE *tpkt_header, DWORD length)
  308. {
  309. length += TPKT_HEADER_SIZE;
  310. // TPKT requires that the packet size fit in two bytes.
  311. HWSASSERT(length < (1L << 16));
  312. tpkt_header[0] = TPKT_VERSION;
  313. tpkt_header[1] = 0;
  314. tpkt_header[2] = (BYTE)(length >> 8);
  315. tpkt_header[3] = (BYTE)length;
  316. }
  317. #if defined(__cplusplus)
  318. }
  319. #endif // (__cplusplus)