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.

1905 lines
58 KiB

  1. /***************************************************************************
  2. *
  3. * File: h245ws.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. *
  15. * $Workfile: h245ws.cpp $
  16. * $Revision: 2.11 $
  17. * $Modtime: 31 Jan 1997 19:22:28 $
  18. * $Log: S:\sturgeon\src\h245ws\vcs\h245ws.cpv $
  19. *
  20. * Rev 2.11 31 Jan 1997 20:24:34 SBELL1
  21. * Relinquished CallControl Stack lock before DefWindowProc
  22. *
  23. * Rev 2.10 31 Jan 1997 14:54:12 EHOWARDX
  24. * Added CCLOCK support.
  25. *
  26. * Rev 2.9 20 Jan 1997 20:42:34 SBELL1
  27. * Fixed GPF when shutting down.
  28. *
  29. * Rev 2.8 07 Jan 1997 11:51:48 EHOWARDX
  30. *
  31. * Fixed "assignment within conditional expression" warning
  32. * in GetLinkLayerInstance().
  33. *
  34. * Rev 2.7 03 Jan 1997 13:15:18 EHOWARDX
  35. * Attempt at workaround for #1718 linkLayerListen() returns WSAENOBUFS.
  36. *
  37. * Rev 2.6 23 Dec 1996 15:30:16 EHOWARDX
  38. *
  39. * Set window to zero after call to destroy window -- Uninitialize seems
  40. * to be called more than once.
  41. *
  42. * Rev 2.5 20 Dec 1996 17:49:10 SBELL1
  43. * changed to blocking mode before closesocket in SocketClose.
  44. * This makes the linger work.
  45. *
  46. * Rev 2.4 19 Dec 1996 19:03:18 SBELL1
  47. * Moved Initialize to linkLayerInit
  48. * Set linger option on accept socket
  49. * reversed "new" change
  50. *
  51. * Rev 2.3 Dec 13 1996 17:12:36 plantz
  52. * fixed string for UNICODE.
  53. //
  54. // Rev 1.3 13 Dec 1996 14:32:10 SBELL1
  55. // fixed string for UNICODE.
  56. //
  57. // Rev 1.1 12 Dec 1996 17:59:02 SBELL1
  58. // Fixed bug in lingering on Q.931 Listen socket.
  59. //
  60. // Rev 1.0 11 Dec 1996 13:41:14 SBELL1
  61. // Initial revision.
  62. *
  63. * Rev 1.46 18 Oct 1996 16:46:12 EHOWARDX
  64. *
  65. * Changed GetIpAddress to take wide char cAddr field.
  66. *
  67. * Rev 1.45 Oct 01 1996 14:29:56 EHOWARDX
  68. * Moved Initialize() and Unitialize() calls to DllMain().
  69. *
  70. * Rev 1.44 26 Sep 1996 18:52:10 EHOWARDX
  71. *
  72. * Moved some initialization around to prevent possible assertion failure
  73. * in SocketClose().
  74. *
  75. * Rev 1.43 15 Aug 1996 13:59:00 rodellx
  76. *
  77. * Added additional address validation for DOMAIN_NAME addresses
  78. * which cannot be resolved, but are used with SocketBind().
  79. *
  80. * Rev 1.42 Aug 07 1996 14:38:00 mandrews
  81. * Set bMulticast field of CC_ADDR structures correctly.
  82. *
  83. * Rev 1.41 24 Jul 1996 11:53:02 EHOWARDX
  84. * Changed ADDR to CC_ADDR, IP_XXX to CC_IP_XXX.
  85. * Fixed bug in SocketCloseEvent - needed to revalidate pHws after callback.
  86. *
  87. * Rev 1.40 08 Jul 1996 19:27:18 unknown
  88. * Second experiment to try to fix Q.931 shutdown problem.
  89. *
  90. * Rev 1.39 02 Jul 1996 16:23:02 EHOWARDX
  91. * Backed out experimental change.
  92. *
  93. * Rev 1.37 28 Jun 1996 18:06:50 unknown
  94. * Added breaks to GetPort.
  95. *
  96. * Rev 1.36 27 Jun 1996 14:06:06 EHOWARDX
  97. * Byte-swapped port number for debug trace in linkLayerListen & linkLayerConn
  98. *
  99. * Rev 1.35 21 Jun 1996 18:52:14 unknown
  100. * Fixed yet another shutdown bug - linkLayerShutdown re-entrancy check.
  101. *
  102. * Rev 1.34 18 Jun 1996 16:56:20 EHOWARDX
  103. * Added check to see if callback deallocated our instance to SocketConnect().
  104. *
  105. * Rev 1.33 17 Jun 1996 13:23:48 EHOWARDX
  106. * Workaround for PostQuitMessage() bug.
  107. *
  108. * Rev 1.32 12 Jun 1996 11:43:26 EHOWARDX
  109. * Changed linkLayerConnect errors from HWS_CRITICAL to HWS_WARNING.
  110. *
  111. * Rev 1.31 May 28 1996 18:14:00 plantz
  112. * Change error codes to use HRESULT. Propogate Winsock errors where appropriate
  113. *
  114. * Rev 1.30 May 28 1996 10:38:08 plantz
  115. * Change sprintf to wsprintf.
  116. *
  117. * Rev 1.29 17 May 1996 16:49:24 EHOWARDX
  118. * Shutdown fix.
  119. *
  120. * Rev 1.28 16 May 1996 13:09:18 EHOWARDX
  121. * Made reporting of IP Addres and port consistent between linkLayerListen
  122. * and LinkLayerConnect.
  123. *
  124. * Rev 1.27 14 May 1996 11:31:50 EHOWARDX
  125. * Fixed bug with doing another connect on instance that failed previous
  126. * connect. Instance now returns LINK_INVALID_STATE, and must be closed
  127. * and reopened.
  128. *
  129. * Rev 1.26 09 May 1996 18:33:22 EHOWARDX
  130. *
  131. * Changes to build with new LINKAPI.H.
  132. *
  133. * Rev 1.25 Apr 29 1996 19:06:48 plantz
  134. * Reenable code to try to send all messages when shutting down.
  135. *
  136. * Rev 1.24 Apr 29 1996 14:02:58 plantz
  137. * Add NotifyRead and NotifyWrite functions.
  138. * Delete unused function FindH245Instance.
  139. * .
  140. *
  141. * Rev 1.23 Apr 25 1996 21:16:26 plantz
  142. * Add connect callback parameter to linkLayerAccept.
  143. * Pass message type to connect callback.
  144. *
  145. * Rev 1.22 Apr 24 1996 20:49:30 plantz
  146. * Listen on address passed to linkLayerListen; use INADDR_ANY if it is 0.
  147. * Return the result of getsockname after listening.
  148. * Add a callback parameter to linkLayerConnect. Call it when FD_CONNECT event
  149. * occurs and after calling accept, passing error code and local and peer
  150. * addresses.
  151. *
  152. * Rev 1.21 Apr 24 1996 16:55:20 plantz
  153. * Merge 1.15.1.0 with 1.20 (winsock 1 changes)
  154. *
  155. * Rev 1.20 19 Apr 1996 18:28:50 EHOWARDX
  156. * Changed Send and receive flush to call send and receive callback with
  157. * LINK_FLUSH_COMPLETE message to more accurately emulate behavior
  158. * of H245SRP.DLL.
  159. *
  160. * Rev 1.19 19 Apr 1996 10:34:26 EHOWARDX
  161. * Updated to latest LINKAPI.H - WINAPI keywork eliminated.
  162. *
  163. * Rev 1.18 12 Apr 1996 19:17:02 unknown
  164. * Removed annoying trace message.
  165. *
  166. * Rev 1.17 11 Apr 1996 14:53:22 EHOWARDX
  167. * Changed to include INCOMMON.H instead of CALLCONT.H.
  168. *
  169. * Rev 1.16 04 Apr 1996 12:35:04 EHOWARDX
  170. * Valiantly trying to track never-ending changes to Link Layer API
  171. * (Thanks Dan! Changing linkLayerGetInstId to linkLayerGetInstance() --
  172. * what a stroke of genius!)
  173. *
  174. * Rev 1.15.1.0 Apr 24 1996 16:23:02 plantz
  175. * Change to use winsock 1.
  176. *
  177. * Rev 1.15 03 Apr 1996 16:35:46 EHOWARDX
  178. * CLOSED state no longer implies that we have a thread;
  179. * replaced assert with if statement.
  180. *
  181. * Rev 1.14 03 Apr 1996 14:52:24 EHOWARDX
  182. * Fixed yet another shutdown problem.
  183. *
  184. * Rev 1.13 02 Apr 1996 18:28:50 EHOWARDX
  185. * Added ProcessQueuedRecvs() to SocketAccept().
  186. *
  187. * Rev 1.12 01 Apr 1996 16:25:46 EHOWARDX
  188. * Experiment with calling ProcessRecvQueue on FD_WRITE event.
  189. *
  190. * Rev 1.11 01 Apr 1996 14:20:40 unknown
  191. * Shutdown redesign.
  192. *
  193. * Rev 1.10 29 Mar 1996 11:12:56 EHOWARDX
  194. * Added line to SocketClose to set state to HWS_CLOSED.
  195. *
  196. * Rev 1.9 27 Mar 1996 13:00:30 EHOWARDX
  197. * Added dwThreadId to H245WS instance structure.
  198. * Reversed shutdown loop to check state first BEFORE checking send queue.
  199. *
  200. * Rev 1.8 22 Mar 1996 10:54:20 unknown
  201. *
  202. * Minor change in trace text.
  203. *
  204. * Rev 1.7 20 Mar 1996 14:11:20 unknown
  205. * Added Sleep(0) to bind retry loop.
  206. *
  207. * Rev 1.6 19 Mar 1996 20:21:56 EHOWARDX
  208. * Redesigned shutdown.
  209. *
  210. * Rev 1.4 18 Mar 1996 19:08:28 EHOWARDX
  211. * Fixed shutdown; eliminated TPKT/WSCB dependencies.
  212. * Define TPKT to put TPKT/WSCB dependencies back in.
  213. *
  214. * Rev 1.3 14 Mar 1996 17:01:46 EHOWARDX
  215. *
  216. * NT4.0 testing; got rid of HwsAssert(); got rid of TPKT/WSCB.
  217. *
  218. * Rev 1.2 09 Mar 1996 21:12:26 EHOWARDX
  219. * Fixes as result of testing.
  220. *
  221. * Rev 1.1 08 Mar 1996 20:24:24 unknown
  222. * This is the real version of the main h245ws.dll code.
  223. * Version 1.0 was a stub version created by Mike Andrews.
  224. *
  225. ***************************************************************************/
  226. #ifndef STRICT
  227. #define STRICT
  228. #endif // not defined STRICT
  229. #define LINKDLL_EXPORT
  230. #pragma warning ( disable : 4115 4201 4214 4514 )
  231. #include <nt.h>
  232. #include <ntrtl.h>
  233. #include <nturtl.h>
  234. #include <windows.h>
  235. #include "queue.h"
  236. #include "linkapi.h"
  237. #include "incommon.h"
  238. #include "h245ws.h"
  239. #include "tstable.h"
  240. #include "provider.h"
  241. #if defined(__cplusplus)
  242. extern "C"
  243. {
  244. #endif // (__cplusplus)
  245. // REVIEW: Should we use the newer definition from winsock2.h ?
  246. #undef FD_ALL_EVENTS
  247. #define FD_ALL_EVENTS (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE)
  248. #define WINSOCK_EVENT_MSG (WM_USER+1)
  249. HRESULT SocketOpen(PHWSINST pHws, BOOL bSetLinger = TRUE);
  250. /*
  251. * Static variables
  252. */
  253. static HWND window = 0;
  254. TSTable<HWSINST>* gpInstanceTable; // global ptr to the instance table
  255. static CRITICAL_SECTION SocketToHWSInstanceMapLock;
  256. static SOCKET_TO_INSTANCE *pSocketToHWSInstanceMap = NULL;
  257. // If we are not using the Unicode enabled tracing, then undefine the __TEXT macro.
  258. // Do not place anything that should be a Unicode constant string between this #undef
  259. // and the corresponding redefinition of the macro
  260. #if defined(DBG)
  261. #ifndef UNICODE_TRACE
  262. #undef __TEXT
  263. #define __TEXT(x) x
  264. static const char * StateMap[] =
  265. #else
  266. static const LPTSTR StateMap[] =
  267. #endif
  268. {
  269. __TEXT("HWS_START"), // 0 Initial state
  270. __TEXT("HWS_LISTENING"), // 1 Waiting for FD_ACCEPT
  271. __TEXT("HWS_CONNECTING"), // 2 Waiting for FD_CONNECT
  272. __TEXT("HWS_CONNECTED"), // 3 Data transfer state
  273. __TEXT("HWS_CLOSING"), // 4 Waiting for FD_CLOSE
  274. __TEXT("HWS_CLOSED"), // 5 Waiting for linkLayerShutdown()
  275. __TEXT("HWS_SHUTDOWN"), // 6 linkLayerShutdown() called from callback
  276. };
  277. typedef struct _ERROR_MAP
  278. {
  279. int nErrorCode;
  280. #ifdef UNICODE_TRACE
  281. LPCTSTR pszErrorText;
  282. #else
  283. const char *pszErrorText;
  284. #endif
  285. } ERROR_MAP;
  286. static const ERROR_MAP ErrorMap[] =
  287. {
  288. 0, __TEXT("OK"),
  289. WSAEINTR, __TEXT("WSAEINTR - Interrupted function call"),
  290. WSAEBADF, __TEXT("WSAEBADF"),
  291. WSAEACCES, __TEXT("WSAEACCES - Permission denied"),
  292. WSAEFAULT, __TEXT("WSAEFAULT - Bad address"),
  293. WSAEINVAL, __TEXT("WSAEINVAL - Invalid argument"),
  294. WSAEMFILE, __TEXT("WSAEMFILE - Too many open files"),
  295. WSAEWOULDBLOCK, __TEXT("WSAEWOULDBLOCK - Resource temporarily unavailable"),
  296. WSAEINPROGRESS, __TEXT("WSAEINPROGRESS - Operation now in progress"),
  297. WSAEALREADY, __TEXT("WSAEALREADY - Operation already in progress"),
  298. WSAENOTSOCK, __TEXT("WSAENOTSOCK - Socket operation on non-socket"),
  299. WSAEDESTADDRREQ, __TEXT("WSAEDESTADDRREQ - Destination address required"),
  300. WSAEMSGSIZE, __TEXT("WSAEMSGSIZE - Message too long"),
  301. WSAEPROTOTYPE, __TEXT("WSAEPROTOTYPE - Protocol wrong type for socket"),
  302. WSAENOPROTOOPT, __TEXT("WSAENOPROTOOPT - Bad protocol option"),
  303. WSAEPROTONOSUPPORT, __TEXT("WSAEPROTONOSUPPORT - Protocol not supported"),
  304. WSAESOCKTNOSUPPORT, __TEXT("WSAESOCKTNOSUPPORT - Socket type not supported"),
  305. WSAEOPNOTSUPP, __TEXT("WSAEOPNOTSUPP - Operation not supported"),
  306. WSAEPFNOSUPPORT, __TEXT("WSAEPFNOSUPPORT - Protocol family not supported"),
  307. WSAEAFNOSUPPORT, __TEXT("WSAEAFNOSUPPORT - Address family not supported by protocol family"),
  308. WSAEADDRINUSE, __TEXT("WSAEADDRINUSE - Address already in use"),
  309. WSAEADDRNOTAVAIL, __TEXT("WSAEADDRNOTAVAIL - Cannot assign requested address"),
  310. WSAENETDOWN, __TEXT("WSAENETDOWN - Network is down"),
  311. WSAENETUNREACH, __TEXT("WSAENETUNREACH - Network is unreachable"),
  312. WSAENETRESET, __TEXT("WSAENETRESET - Network dropped connection on reset"),
  313. WSAECONNABORTED, __TEXT("WSAECONNABORTED - Software caused connection abort"),
  314. WSAECONNRESET, __TEXT("WSAECONNRESET - Connection reset by peer"),
  315. WSAENOBUFS, __TEXT("WSAENOBUFS - No buffer space available"),
  316. WSAEISCONN, __TEXT("WSAEISCONN - Socket is already connected"),
  317. WSAENOTCONN, __TEXT("WSAENOTCONN - Socket is not connected"),
  318. WSAESHUTDOWN, __TEXT("WSAESHUTDOWN - Cannot send after socket shutdown"),
  319. WSAETOOMANYREFS, __TEXT("WSAETOOMANYREFS"),
  320. WSAETIMEDOUT, __TEXT("WSAETIMEDOUT - Connection timed out"),
  321. WSAECONNREFUSED, __TEXT("WSAECONNREFUSED - Connection refused"),
  322. WSAELOOP, __TEXT("WSAELOOP"),
  323. WSAENAMETOOLONG, __TEXT("WSAENAMETOOLONG"),
  324. WSAEHOSTDOWN, __TEXT("WSAEHOSTDOWN - Host is down"),
  325. WSAEHOSTUNREACH, __TEXT("WSAEHOSTUNREACH - No route to host"),
  326. WSAENOTEMPTY, __TEXT("WSAENOTEMPTY"),
  327. WSAEPROCLIM, __TEXT("WSAEPROCLIM - Too many processes"),
  328. WSAEUSERS, __TEXT("WSAEUSERS"),
  329. WSAEDQUOT, __TEXT("WSAEDQUOT"),
  330. WSAESTALE, __TEXT("WSAESTALE"),
  331. WSAEREMOTE, __TEXT("WSAEREMOTE"),
  332. WSASYSNOTREADY, __TEXT("WSASYSNOTREADY - Network subsystem is unavailable"),
  333. WSAVERNOTSUPPORTED, __TEXT("WSAVERNOTSUPPORTED - WINSOCK.DLL version out of range"),
  334. WSANOTINITIALISED, __TEXT("WSANOTINITIALISED - Successful WSAStartup() not yet performed"),
  335. WSAEDISCON, __TEXT("WSAEDISCON - Graceful shutdown in progress"),
  336. WSAHOST_NOT_FOUND, __TEXT("WSAHOST_NOT_FOUND - Host not found"),
  337. WSATRY_AGAIN, __TEXT("WSATRY_AGAIN - Non-authoritative host not found"),
  338. WSANO_RECOVERY, __TEXT("WSANO_RECOVERY - This is a non-recoverable error"),
  339. WSANO_DATA, __TEXT("WSANO_DATA - Valid name, no data record of requested type"),
  340. // WSA_INVALID_HANDLE, __TEXT("WSA_INVALID_HANDLE - Specified event object handle is invalid"),
  341. // WSA_INVALID_PARAMETER, __TEXT("WSA_INVALID_PARAMETER - One or more parameters are invalid"),
  342. // WSA_IO_PENDING, __TEXT("WSA_IO_PENDING - Overlapped operations will complete later"),
  343. // WSA_IO_INCOMPLETE, __TEXT("WSA_IO_INCOMPLETE - Overlapped I/O event object not in signaled state"),
  344. // WSA_NOT_ENOUGH_MEMORY, __TEXT("WSA_NOT_ENOUGH_MEMORY - Insufficient memory available"),
  345. // WSA_OPERATION_ABORTED, __TEXT("WSA_OPERATION_ABORTED - Overlapped operation aborted"),
  346. };
  347. //
  348. // Function Definitions
  349. //
  350. #include <string.h>
  351. #ifdef UNICODE_TRACE
  352. static const LPTSTR
  353. #else
  354. static const char *
  355. #endif
  356. SocketStateText(UINT uState)
  357. {
  358. #ifdef UNICODE_TRACE
  359. static TCHAR szSocketStateText[80];
  360. #else
  361. static char szSocketStateText[80];
  362. #endif
  363. if (uState <= HWS_SHUTDOWN)
  364. return StateMap[uState];
  365. wsprintf(szSocketStateText, __TEXT("Unknown state %d"), uState);
  366. return szSocketStateText;
  367. } // SocketStateText()
  368. #ifdef UNICODE_TRACE
  369. static LPCTSTR
  370. #else
  371. static const char *
  372. #endif
  373. SocketErrorText1(int nErrorCode)
  374. {
  375. register int nIndex = sizeof(ErrorMap) / sizeof(ErrorMap[0]);
  376. #ifdef UNICODE_TRACE
  377. static TCHAR szSocketErrorText[80];
  378. #else
  379. static char szSocketErrorText[80];
  380. #endif
  381. while (nIndex > 0)
  382. {
  383. if (ErrorMap[--nIndex].nErrorCode == nErrorCode)
  384. {
  385. return ErrorMap[nIndex].pszErrorText;
  386. }
  387. }
  388. wsprintf(szSocketErrorText, __TEXT("Unknown error 0x%x"), nErrorCode);
  389. return szSocketErrorText;
  390. } // SocketErrorText1()
  391. #ifdef UNICODE_TRACE
  392. LPCTSTR
  393. #else
  394. const char *
  395. #endif
  396. SocketErrorText(void)
  397. {
  398. return SocketErrorText1(WSAGetLastError());
  399. } // SocketErrorText()
  400. #endif // (DBG)
  401. /***************************************************************************
  402. *
  403. * Local routines
  404. *
  405. ***************************************************************************/
  406. static DWORD
  407. HashSocket(SOCKET socket)
  408. {
  409. return (DWORD)((socket >> 2) % SOCK_TO_PHYSID_TABLE_SIZE);
  410. }
  411. DWORD
  412. SocketToPhysicalId(SOCKET socket)
  413. {
  414. // hash the socket to get an index into the SocketToHWSInstanceMap table
  415. DWORD idx = HashSocket(socket);
  416. if(pSocketToHWSInstanceMap == NULL)
  417. return(INVALID_PHYS_ID);
  418. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  419. // idx indicates the entry point in the array, now traverse the linked list
  420. PSOCKET_TO_INSTANCE pEntry = &pSocketToHWSInstanceMap[idx];
  421. while(pEntry != NULL)
  422. {
  423. if(pEntry->socket == socket)
  424. {
  425. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  426. return(pEntry->dwPhysicalId);
  427. } else
  428. {
  429. pEntry = pEntry->next;
  430. }
  431. }
  432. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  433. return(INVALID_PHYS_ID);
  434. } // SocketToPhysicalId()
  435. BOOL
  436. CreateSocketToPhysicalIdMapping(SOCKET socket, DWORD dwPhysicalId)
  437. {
  438. // hash the socket to get an index into the SocketToHWSInstanceMap table
  439. DWORD idx = HashSocket(socket);
  440. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  441. // idx indicates the entry point in the array, now traverse the linked list
  442. PSOCKET_TO_INSTANCE pEntry = &pSocketToHWSInstanceMap[idx];
  443. PSOCKET_TO_INSTANCE pNewEntry;
  444. if (pEntry->socket == INVALID_SOCKET)
  445. {
  446. pNewEntry = pEntry;
  447. } else
  448. {
  449. pNewEntry = new SOCKET_TO_INSTANCE;
  450. if (pNewEntry == NULL)
  451. {
  452. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  453. return(FALSE);
  454. }
  455. pNewEntry->next = pEntry->next;
  456. pEntry->next = pNewEntry;
  457. }
  458. pNewEntry->socket = socket;
  459. pNewEntry->dwPhysicalId = dwPhysicalId;
  460. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  461. return(TRUE);
  462. }
  463. BOOL
  464. RemoveSocketToPhysicalIdMapping(SOCKET socket)
  465. {
  466. if (socket == INVALID_SOCKET)
  467. return(FALSE);
  468. // hash the socket to get an index into the SocketToHWSInstanceMap table
  469. DWORD idx = HashSocket(socket);
  470. BOOL bFound = FALSE;
  471. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  472. // idx indicates the entry point in the array, now traverse the linked list
  473. PSOCKET_TO_INSTANCE pEntry = &pSocketToHWSInstanceMap[idx];
  474. if (pEntry->socket == socket)
  475. {
  476. pEntry->socket = INVALID_SOCKET;
  477. bFound = TRUE;
  478. } else
  479. {
  480. PSOCKET_TO_INSTANCE pNextEntry;
  481. pNextEntry = pEntry->next;
  482. while (bFound == FALSE && pNextEntry != NULL)
  483. {
  484. if(pNextEntry->socket == socket)
  485. {
  486. pEntry->next = pNextEntry->next;
  487. delete pNextEntry;
  488. bFound = TRUE;
  489. } else
  490. {
  491. pEntry = pNextEntry;
  492. pNextEntry = pNextEntry->next;
  493. }
  494. }
  495. }
  496. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  497. return(bFound);
  498. }
  499. static unsigned short GetPort (CC_ADDR *pAddr)
  500. {
  501. unsigned short int port = 0;
  502. switch (pAddr->nAddrType)
  503. {
  504. case CC_IP_DOMAIN_NAME:
  505. port = pAddr->Addr.IP_DomainName.wPort;
  506. break;
  507. case CC_IP_DOT:
  508. port = pAddr->Addr.IP_Dot.wPort;
  509. break;
  510. case CC_IP_BINARY:
  511. port = pAddr->Addr.IP_Binary.wPort;
  512. break;
  513. } // switch
  514. return htons(port);
  515. } // GetPort()
  516. static unsigned long GetIPAddress (CC_ADDR *pAddr)
  517. {
  518. struct hostent * pHostEnt;
  519. char szAddr[256];
  520. switch (pAddr->nAddrType)
  521. {
  522. case CC_IP_DOMAIN_NAME:
  523. WideCharToMultiByte(CP_ACP, // code page
  524. 0, // dwFlags
  525. pAddr->Addr.IP_DomainName.cAddr,
  526. -1, // Unicode string length (bytes)
  527. szAddr, // ASCII string
  528. sizeof(szAddr), // max ASCII string length
  529. NULL, // default character
  530. NULL); // default character used
  531. pHostEnt = gethostbyname(szAddr);
  532. if (pHostEnt == NULL || pHostEnt->h_addr_list == NULL)
  533. return 0;
  534. return *((unsigned long *)pHostEnt->h_addr_list[0]);
  535. case CC_IP_DOT:
  536. WideCharToMultiByte(CP_ACP, // code page
  537. 0, // dwFlags
  538. pAddr->Addr.IP_Dot.cAddr,
  539. -1, // Unicode string length (bytes)
  540. szAddr, // ASCII string
  541. sizeof(szAddr), // max ASCII string length
  542. NULL, // default character
  543. NULL); // default character used
  544. return inet_addr(szAddr);
  545. case CC_IP_BINARY:
  546. return pAddr->Addr.IP_Binary.dwAddr == 0 ? INADDR_ANY : htonl(pAddr->Addr.IP_Binary.dwAddr);
  547. } // switch
  548. return 0;
  549. } // GetIPAddress()
  550. static HRESULT GetLocalAddr(PHWSINST pHws, CC_ADDR *pAddr)
  551. {
  552. SOCKADDR_IN sockaddr;
  553. int len = sizeof(sockaddr);
  554. if (getsockname(pHws->hws_Socket,
  555. (struct sockaddr *)&sockaddr,
  556. &len) == SOCKET_ERROR)
  557. {
  558. return MAKE_WINSOCK_ERROR(WSAGetLastError());
  559. }
  560. pAddr->nAddrType = CC_IP_BINARY;
  561. pAddr->bMulticast = FALSE;
  562. pAddr->Addr.IP_Binary.wPort = ntohs(sockaddr.sin_port);
  563. pAddr->Addr.IP_Binary.dwAddr = ntohl(sockaddr.sin_addr.S_un.S_addr);
  564. return NOERROR;
  565. }
  566. static HRESULT GetPeerAddr(PHWSINST pHws, CC_ADDR *pAddr)
  567. {
  568. SOCKADDR_IN sockaddr;
  569. int len = sizeof(sockaddr);
  570. if (getpeername(pHws->hws_Socket,
  571. (struct sockaddr *)&sockaddr,
  572. &len) == SOCKET_ERROR)
  573. {
  574. return MAKE_WINSOCK_ERROR(WSAGetLastError());
  575. }
  576. pAddr->nAddrType = CC_IP_BINARY;
  577. pAddr->bMulticast = FALSE;
  578. pAddr->Addr.IP_Binary.wPort = ntohs(sockaddr.sin_port);
  579. pAddr->Addr.IP_Binary.dwAddr = ntohl(sockaddr.sin_addr.S_un.S_addr);
  580. return NOERROR;
  581. }
  582. void
  583. SocketFlushRecv(PHWSINST pHws)
  584. {
  585. register PREQUEST pReq;
  586. if (pHws->hws_pRecvQueue)
  587. {
  588. while ((pReq = (PREQUEST) QRemove(pHws->hws_pRecvQueue)) != NULL)
  589. {
  590. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,
  591. LINK_RECV_ABORT,
  592. pReq->req_client_data,
  593. 0);
  594. HWSFREE(pReq);
  595. }
  596. }
  597. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,
  598. LINK_FLUSH_COMPLETE,
  599. NULL,
  600. 0);
  601. } // SocketFlushRecv()
  602. void
  603. SocketFlushSend(PHWSINST pHws)
  604. {
  605. register PREQUEST pReq;
  606. if (pHws->hws_pSendQueue)
  607. {
  608. while ((pReq = (PREQUEST) QRemove(pHws->hws_pSendQueue)) != NULL)
  609. {
  610. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  611. LINK_SEND_ABORT,
  612. pReq->req_client_data,
  613. 0);
  614. HWSFREE(pReq);
  615. }
  616. }
  617. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  618. LINK_FLUSH_COMPLETE,
  619. NULL,
  620. 0);
  621. } // SocketFlushSend()
  622. void
  623. SocketCloseEvent(PHWSINST pHws)
  624. {
  625. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketCloseEvent"));
  626. if (pHws->hws_uState == HWS_CONNECTED)
  627. {
  628. register DWORD dwPhysicalId = pHws->hws_dwPhysicalId;
  629. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,LINK_RECV_CLOSED,0,0);
  630. // Check to see if callback deallocated our instance or state changed
  631. if(gpInstanceTable->Validate(dwPhysicalId) == FALSE)
  632. return;
  633. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  634. __TEXT("SocketCloseEvent: calling shutdown"));
  635. if (shutdown(pHws->hws_Socket, 1) == SOCKET_ERROR)
  636. {
  637. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  638. __TEXT("HandleNetworkEvent: shutdown() returned %s"),
  639. SocketErrorText());
  640. }
  641. }
  642. pHws->hws_uState = HWS_CLOSED;
  643. } // SocketCloseEvent()
  644. /*
  645. * DESCRIPTION
  646. * Deallocate all allocated objects except for task handle
  647. */
  648. void
  649. SocketClose(PHWSINST pHws)
  650. {
  651. HWSASSERT(pHws != NULL);
  652. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  653. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketClose"));
  654. pHws->hws_uState = HWS_CLOSED;
  655. RemoveSocketToPhysicalIdMapping(pHws->hws_Socket);
  656. // Close the socket
  657. if (pHws->hws_Socket != INVALID_SOCKET)
  658. {
  659. // To make the linger work, turn off WSAAsyncSelect to turn off
  660. // non-blocking via ioctlsocket, to close the socket.
  661. unsigned long blocking = 0;
  662. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  663. __TEXT("SocketClose: calling closesocket"));
  664. WSAAsyncSelect(pHws->hws_Socket,
  665. window, WINSOCK_EVENT_MSG,
  666. 0);
  667. ioctlsocket(pHws->hws_Socket, FIONBIO,&blocking);
  668. if (closesocket(pHws->hws_Socket) == SOCKET_ERROR)
  669. {
  670. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  671. __TEXT("SocketClose: closesocket() returned %s"),
  672. SocketErrorText());
  673. }
  674. pHws->hws_Socket = INVALID_SOCKET;
  675. }
  676. } // SocketClose()
  677. HRESULT
  678. SocketOpen(PHWSINST pHws, BOOL bSetLinger)
  679. {
  680. HWSASSERT(pHws != NULL);
  681. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  682. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketOpen"));
  683. // Create a socket
  684. pHws->hws_Socket = socket(AF_INET, SOCK_STREAM, 0);
  685. if (pHws->hws_Socket == INVALID_SOCKET)
  686. {
  687. // WSASocket() failed
  688. int err = WSAGetLastError();
  689. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  690. __TEXT("SocketOpen: socket() returned %s"),
  691. SocketErrorText1(err));
  692. SocketClose(pHws);
  693. return MAKE_WINSOCK_ERROR(err);
  694. }
  695. /*
  696. ** Request notification messages for all events on this socket.
  697. ** Note that this call automatically puts the socket into non-blocking
  698. ** mode, as if we had called WSAIoctl with the FIONBIO flag.
  699. **/
  700. if (WSAAsyncSelect(pHws->hws_Socket,
  701. window, WINSOCK_EVENT_MSG,
  702. FD_ALL_EVENTS) == SOCKET_ERROR)
  703. {
  704. int err = WSAGetLastError();
  705. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  706. __TEXT("SocketOpen: WSAASyncSelect() returned %s"),
  707. SocketErrorText1(err));
  708. SocketClose(pHws);
  709. return MAKE_WINSOCK_ERROR(err);
  710. }
  711. if(bSetLinger == TRUE)
  712. {
  713. // Set a linger structure for the socket so that closesocket will block for a period of time (until all
  714. // data is sent or the timeout value) before actually killing the connection.
  715. // This change is being made in order to get rid of the PeekMessage() loops in linklayerShutdown().
  716. struct linger sockLinger;
  717. sockLinger.l_onoff = 1; // yes we want to linger (wait for FIN ACK after sending data and FIN)
  718. sockLinger.l_linger = 1; // linger for up to 1 second
  719. if(setsockopt (pHws->hws_Socket,
  720. SOL_SOCKET,
  721. SO_LINGER,
  722. (const char*) &sockLinger,
  723. sizeof(sockLinger)) == SOCKET_ERROR)
  724. {
  725. int err = WSAGetLastError();
  726. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  727. __TEXT("SocketOpen: setsockopt returned %s"),
  728. SocketErrorText1(err));
  729. SocketClose(pHws);
  730. return MAKE_WINSOCK_ERROR(err);
  731. }
  732. }
  733. // add an entry in the socket to instance map
  734. if(CreateSocketToPhysicalIdMapping(pHws->hws_Socket, pHws->hws_dwPhysicalId) != TRUE)
  735. {
  736. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_WARNING,
  737. __TEXT("SocketOpen: CreateSocketToPhysicalIdMapping() failed"));
  738. SocketClose(pHws);
  739. return(LINK_MEM_FAILURE);
  740. }
  741. return NOERROR;
  742. } // SocketOpen()
  743. HRESULT
  744. SocketBind(PHWSINST pHws, CC_ADDR *pAddr)
  745. {
  746. HWSASSERT(pHws != NULL);
  747. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  748. HWSASSERT(pAddr != NULL);
  749. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketBind"));
  750. // Get a local address to bind the socket to
  751. pHws->hws_SockAddr.sin_family = AF_INET;
  752. pHws->hws_SockAddr.sin_port = GetPort(pAddr);
  753. pHws->hws_SockAddr.sin_addr.S_un.S_addr = GetIPAddress(pAddr);
  754. if ((pAddr->nAddrType == CC_IP_DOMAIN_NAME) &&
  755. (pHws->hws_SockAddr.sin_addr.S_un.S_addr == 0))
  756. {
  757. return LINK_UNKNOWN_ADDR;
  758. }
  759. // Bind the socket
  760. while (bind(pHws->hws_Socket, // s
  761. (const struct sockaddr *)&pHws->hws_SockAddr, // name
  762. sizeof(pHws->hws_SockAddr)) == SOCKET_ERROR) // namelen
  763. {
  764. // bind() failed
  765. int err = WSAGetLastError();
  766. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  767. __TEXT("SocketBind: bind() returned %s"),
  768. SocketErrorText1(err));
  769. if (err != WSAENOBUFS)
  770. {
  771. return MAKE_WINSOCK_ERROR(err);
  772. }
  773. Sleep(0);
  774. }
  775. return NOERROR;
  776. } // SocketBind()
  777. void
  778. SocketConnect(PHWSINST pHws, int error)
  779. {
  780. HWSASSERT(pHws != NULL);
  781. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  782. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketConnect"));
  783. if (error == 0)
  784. {
  785. pHws->hws_uState = HWS_CONNECTED;
  786. if (pHws->hws_h245ConnectCallback)
  787. {
  788. CC_ADDR LocalAddr;
  789. CC_ADDR PeerAddr;
  790. PCC_ADDR pLocalAddr = &LocalAddr;
  791. PCC_ADDR pPeerAddr = &PeerAddr;
  792. DWORD dwPhysicalId = pHws->hws_dwPhysicalId;
  793. if (GetLocalAddr(pHws, pLocalAddr) != NOERROR)
  794. pLocalAddr = NULL;
  795. if (GetPeerAddr(pHws, pPeerAddr) != NOERROR)
  796. pPeerAddr = NULL;
  797. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  798. LINK_CONNECT_COMPLETE, pLocalAddr, pPeerAddr);
  799. // Check to see if callback deallocated our instance - this can be done
  800. // by attempting a lock - which will now fail if the entry has been marked
  801. // for deletion. Thus, if the lock succeeds, then just unlock it (since we
  802. // already have a lock on it).
  803. if(gpInstanceTable->Validate(dwPhysicalId) == FALSE)
  804. return;
  805. }
  806. NotifyWrite(pHws);
  807. NotifyRead(pHws);
  808. }
  809. else
  810. {
  811. if (pHws->hws_h245ConnectCallback)
  812. {
  813. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  814. MAKE_WINSOCK_ERROR(error), NULL, NULL);
  815. }
  816. }
  817. } // SocketConnect()
  818. HRESULT
  819. SocketAccept(PHWSINST pHwsListen, PHWSINST pHwsAccept)
  820. {
  821. SOCKET listen_socket = pHwsListen->hws_Socket;
  822. struct linger sockLinger;
  823. sockLinger.l_onoff = 1; // yes we want to linger (wait for FIN ACK after sending data and FIN)
  824. sockLinger.l_linger = 1; // linger for up to 1 second
  825. // Accept the connection.
  826. pHwsAccept->hws_uSockAddrLen = sizeof(pHwsAccept->hws_SockAddr);
  827. pHwsAccept->hws_Socket = accept(pHwsListen->hws_Socket,
  828. (struct sockaddr *)&pHwsAccept->hws_SockAddr,
  829. (int *)&pHwsAccept->hws_uSockAddrLen);
  830. if (pHwsAccept->hws_Socket == INVALID_SOCKET)
  831. {
  832. int err = WSAGetLastError();
  833. HWSTRACE1(pHwsAccept->hws_dwPhysicalId, HWS_WARNING,
  834. __TEXT("linkLayerAccept: accept() returned %s"),
  835. SocketErrorText1(err));
  836. SocketConnect(pHwsAccept, err);
  837. return MAKE_WINSOCK_ERROR(err);
  838. }
  839. if (pHwsListen == pHwsAccept)
  840. {
  841. HWSTRACE0(pHwsListen->hws_dwPhysicalId, HWS_TRACE,
  842. __TEXT("SocketClose: calling closesocket"));
  843. closesocket(listen_socket);
  844. RemoveSocketToPhysicalIdMapping(listen_socket);
  845. }
  846. // Set a linger structure for the socket so that closesocket will block for a period of time (until all
  847. // data is sent or the timeout value) before actually killing the connection.
  848. // This change is being made in order to get rid of the PeekMessage() loops in linklayerShutdown().
  849. if(setsockopt (pHwsAccept->hws_Socket,
  850. SOL_SOCKET,
  851. SO_LINGER,
  852. (const char*) &sockLinger,
  853. sizeof(sockLinger)) == SOCKET_ERROR)
  854. {
  855. int err = WSAGetLastError();
  856. HWSTRACE1(pHwsAccept->hws_dwPhysicalId, HWS_WARNING,
  857. __TEXT("SocketAccept: setsockopt returned %s"),
  858. SocketErrorText1(err));
  859. SocketClose(pHwsAccept);
  860. return MAKE_WINSOCK_ERROR(err);
  861. }
  862. // add the new socket to the socket to phys id map
  863. CreateSocketToPhysicalIdMapping(pHwsAccept->hws_Socket, pHwsAccept->hws_dwPhysicalId);
  864. SocketConnect(pHwsAccept, 0);
  865. return NOERROR;
  866. } // SocketAccept()
  867. /*++
  868. Description:
  869. Handles network events that may occur on a connected socket.
  870. The events handled by this function are FD_ACCEPT, FD_CLOSE, FD_READ, and
  871. FD_WRITE.
  872. Arguments:
  873. pHws - pointer to data for the connection on which the event happened.
  874. event - event that occurred
  875. error - error code accompanying the event
  876. Return Value:
  877. SUCCESS - The network event was successfully handled.
  878. LINK_FATAL_ERROR - Some kind of error occurred while handling the
  879. event, and the connection should be closed.
  880. LINK_RECV_CLOSED - The connection has been gracefully closed.
  881. --*/
  882. void
  883. HandleNetworkEvent(PHWSINST pHws, int event, int error)
  884. {
  885. HWSASSERT(pHws != NULL);
  886. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  887. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("HandleNetworkEvent"));
  888. if (error == WSAENETDOWN)
  889. {
  890. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  891. __TEXT("HandleSocketEvent: Connection error"));
  892. pHws->hws_uState = HWS_CLOSED;
  893. return;
  894. }
  895. switch (event)
  896. {
  897. case FD_READ:
  898. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  899. __TEXT("HandleNetworkEvent: FD_READ %s"),
  900. SocketErrorText1(error));
  901. if (error == 0 && pHws->hws_uState <= HWS_CLOSING)
  902. {
  903. ProcessQueuedRecvs(pHws);
  904. }
  905. break;
  906. case FD_WRITE:
  907. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  908. __TEXT("HandleNetworkEvent: FD_WRITE %s"),
  909. SocketErrorText1(error));
  910. if (error == 0 && pHws->hws_uState <= HWS_CONNECTED)
  911. {
  912. ProcessQueuedSends(pHws);
  913. }
  914. break;
  915. case FD_OOB:
  916. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  917. __TEXT("HandleNetworkEvent: FD_OOB %s"),
  918. SocketErrorText1(error));
  919. break;
  920. case FD_ACCEPT:
  921. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  922. __TEXT("HandleNetworkEvent: FD_ACCEPT %s"),
  923. SocketErrorText1(error));
  924. if (pHws->hws_h245ConnectCallback != NULL)
  925. {
  926. if (error == 0)
  927. {
  928. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  929. LINK_CONNECT_REQUEST, NULL, NULL);
  930. }
  931. else
  932. {
  933. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  934. MAKE_WINSOCK_ERROR(error), NULL, NULL);
  935. }
  936. }
  937. else if (error == 0)
  938. {
  939. // If the client did not specify a callback, accept the call using the same physical
  940. // Id as the listen. This will result in the listen socket being closed.
  941. SocketAccept(pHws, pHws);
  942. }
  943. break;
  944. case FD_CONNECT:
  945. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  946. __TEXT("HandleNetworkEvent: FD_CONNECT %s"),
  947. SocketErrorText1(error));
  948. SocketConnect(pHws, error);
  949. break;
  950. case FD_CLOSE:
  951. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  952. __TEXT("HandleNetworkEvent: FD_CLOSE %s"),
  953. SocketErrorText1(error));
  954. SocketCloseEvent(pHws);
  955. break;
  956. }
  957. } // HandleNetworkEvent()
  958. LRESULT CALLBACK WndProc(
  959. HWND hWnd, /* window handle */
  960. UINT message, /* type of message */
  961. WPARAM wParam, /* additional information */
  962. LPARAM lParam) /* additional information */
  963. {
  964. PHWSINST pHws;
  965. DWORD dwPhysicalId;
  966. #if defined(USE_PROVIDER_LOCK)
  967. H323LockProvider();
  968. #endif
  969. switch (message)
  970. {
  971. case WINSOCK_EVENT_MSG:
  972. if (((dwPhysicalId=SocketToPhysicalId((SOCKET)wParam)) == INVALID_PHYS_ID) ||
  973. ((pHws=gpInstanceTable->Lock(dwPhysicalId)) == NULL))
  974. {
  975. HWSTRACE1(0, HWS_WARNING,
  976. __TEXT("WndProc: Winsock event on unknown socket 0x%x"),
  977. wParam);
  978. break;
  979. }
  980. HandleNetworkEvent(pHws, WSAGETSELECTEVENT(lParam), WSAGETSELECTERROR(lParam));
  981. gpInstanceTable->Unlock(dwPhysicalId);
  982. break;
  983. default:
  984. {
  985. #if defined(USE_PROVIDER_LOCK)
  986. H323UnlockProvider();
  987. #endif
  988. return DefWindowProc(hWnd, message, wParam, lParam);
  989. }
  990. }
  991. #if defined(USE_PROVIDER_LOCK)
  992. H323UnlockProvider();
  993. #endif
  994. return (0);
  995. }
  996. void NotifyRead(PHWSINST pHws)
  997. {
  998. PostMessage(window, WINSOCK_EVENT_MSG, (WPARAM)pHws->hws_Socket, (LPARAM)MAKELONG(FD_READ, 0));
  999. }
  1000. void NotifyWrite(PHWSINST pHws)
  1001. {
  1002. PostMessage(window, WINSOCK_EVENT_MSG, (WPARAM)pHws->hws_Socket, (LPARAM)MAKELONG(FD_WRITE, 0));
  1003. }
  1004. /*++
  1005. Description:
  1006. Calls WSAStartup, makes sure we have a good version of WinSock
  1007. Arguments:
  1008. None.
  1009. Return Value:
  1010. 0 WinSock DLL successfully started up.
  1011. LINK_FATAL_ERROR Error starting up WinSock DLL.
  1012. --*/
  1013. static const TCHAR CLASS_NAME[] = __TEXT("H245WSWndClass");
  1014. int WinsockInitError = -1;
  1015. HRESULT InitializeStatus = LINK_INVALID_STATE;
  1016. void Initialize()
  1017. {
  1018. WORD wVersion = MAKEWORD(1, 1);
  1019. WSADATA WsaData; // receives data from WSAStartup
  1020. WNDCLASS wndclass = { 0, WndProc, 0, 0, 0, 0, 0, 0, NULL, CLASS_NAME };
  1021. DWORD dwIndex;
  1022. // Caveat: We can't use WSAGetLastError() for WSAStartup failure!
  1023. if ((WinsockInitError = WSAStartup(wVersion, &WsaData)) != 0)
  1024. {
  1025. HWSTRACE0(0, HWS_WARNING, __TEXT("linkLayerInit: WSAStartup() failed"));
  1026. InitializeStatus = MAKE_WINSOCK_ERROR(WinsockInitError);
  1027. return;
  1028. }
  1029. if (LOBYTE(WsaData.wVersion) != 1 ||
  1030. HIBYTE(WsaData.wVersion) != 1)
  1031. {
  1032. HWSTRACE0(0, HWS_WARNING, __TEXT("linkLayerInit: Winsock version mismatch"));
  1033. InitializeStatus = MAKE_WINSOCK_ERROR(WSAVERNOTSUPPORTED);
  1034. return;
  1035. }
  1036. // Create window to receive Winsock messages
  1037. if (RegisterClass(&wndclass) == 0
  1038. || (window = CreateWindow(CLASS_NAME, __TEXT(""), WS_OVERLAPPED, 0, 0, 0, 0, 0, 0, 0, NULL)) == 0)
  1039. {
  1040. HWSTRACE0(0, HWS_WARNING, __TEXT("linkLayerInit: error creating window"));
  1041. InitializeStatus = HRESULT_FROM_WIN32(GetLastError());
  1042. return;
  1043. }
  1044. gpInstanceTable = new TSTable <HWSINST> (30); // note: table will resize automatically
  1045. if(gpInstanceTable == NULL || gpInstanceTable->IsInitialized() == FALSE)
  1046. {
  1047. InitializeStatus = LINK_MEM_FAILURE;
  1048. return;
  1049. }
  1050. pSocketToHWSInstanceMap = new SOCKET_TO_INSTANCE[SOCK_TO_PHYSID_TABLE_SIZE];
  1051. if(pSocketToHWSInstanceMap == NULL)
  1052. {
  1053. InitializeStatus = LINK_MEM_FAILURE;
  1054. return;
  1055. }
  1056. __try {
  1057. // initialize lock (and allocate event immediately)
  1058. InitializeCriticalSectionAndSpinCount(&SocketToHWSInstanceMapLock,H323_SPIN_COUNT);
  1059. } __except ((GetExceptionCode() == STATUS_NO_MEMORY)
  1060. ? EXCEPTION_EXECUTE_HANDLER
  1061. : EXCEPTION_CONTINUE_SEARCH
  1062. ) {
  1063. // report memory failure
  1064. InitializeStatus = LINK_MEM_FAILURE;
  1065. return;
  1066. }
  1067. memset(pSocketToHWSInstanceMap, 0, sizeof(SOCKET_TO_INSTANCE) * SOCK_TO_PHYSID_TABLE_SIZE);
  1068. // Init the sockets to a bad value
  1069. for (dwIndex = 0; dwIndex < SOCK_TO_PHYSID_TABLE_SIZE; dwIndex++)
  1070. {
  1071. pSocketToHWSInstanceMap[dwIndex].socket = INVALID_SOCKET;
  1072. }
  1073. InitializeStatus = NOERROR;
  1074. }
  1075. void Uninitialize()
  1076. {
  1077. if (WinsockInitError == 0)
  1078. {
  1079. if (window)
  1080. {
  1081. DestroyWindow(window);
  1082. window = 0;
  1083. UnregisterClass(CLASS_NAME, 0);
  1084. if (gpInstanceTable)
  1085. {
  1086. delete gpInstanceTable;
  1087. if (InitializeStatus == NOERROR)
  1088. {
  1089. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  1090. delete pSocketToHWSInstanceMap;
  1091. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  1092. DeleteCriticalSection(&SocketToHWSInstanceMapLock);
  1093. }
  1094. }
  1095. }
  1096. WSACleanup();
  1097. }
  1098. }
  1099. /***************************************************************************
  1100. *
  1101. * External entry points
  1102. *
  1103. ***************************************************************************/
  1104. //MULTITHREAD => dwH245Instance is now an OUTPUT param not an INPUT param.
  1105. LINKDLL HRESULT linkLayerInit (DWORD *dwPhysicalId,
  1106. DWORD dwH245Instance,
  1107. H245SRCALLBACK cbReceiveComplete,
  1108. H245SRCALLBACK cbTransmitComplete)
  1109. {
  1110. register PHWSINST pHws;
  1111. *dwPhysicalId = INVALID_PHYS_ID; // Just in case...
  1112. // Put Initialize back in here so we know everything we need is up and
  1113. // running.
  1114. if (InitializeStatus == LINK_INVALID_STATE)
  1115. Initialize();
  1116. if (InitializeStatus != NOERROR)
  1117. return InitializeStatus;
  1118. pHws = (PHWSINST)HWSMALLOC(sizeof(*pHws));
  1119. if (pHws == NULL)
  1120. {
  1121. // couldn't allocate our context. Return
  1122. HWSTRACE0(INVALID_PHYS_ID, HWS_WARNING, __TEXT("linkLayerInit: could not allocate context"));
  1123. return LINK_MEM_FAILURE;
  1124. }
  1125. memset(pHws, 0, sizeof(*pHws));
  1126. pHws->hws_Socket = INVALID_SOCKET;
  1127. #if defined(DBG)
  1128. pHws->hws_dwMagic = HWSINST_MAGIC;
  1129. #endif // (DBG)
  1130. // Create and initialize the Receive queue
  1131. pHws->hws_pRecvQueue = QCreate();
  1132. if (pHws->hws_pRecvQueue == NULL)
  1133. {
  1134. HWSTRACE0(INVALID_PHYS_ID, HWS_WARNING, __TEXT("linkLayerInit: could not allocate Receive queue"));
  1135. SocketClose(pHws);
  1136. HWSFREE(pHws);
  1137. return LINK_MEM_FAILURE;
  1138. }
  1139. // Create and initialize the Send queue
  1140. pHws->hws_pSendQueue = QCreate();
  1141. if (pHws->hws_pSendQueue == NULL)
  1142. {
  1143. HWSTRACE0(INVALID_PHYS_ID, HWS_WARNING, __TEXT("linkLayerInit: could not allocate Send queue"));
  1144. SocketClose(pHws);
  1145. HWSFREE(pHws);
  1146. return LINK_MEM_FAILURE;
  1147. }
  1148. // Save intance identifiers and callback pointers
  1149. pHws->hws_uState = HWS_START;
  1150. pHws->hws_dwH245Instance = dwH245Instance;
  1151. pHws->hws_h245RecvCallback = cbReceiveComplete;
  1152. pHws->hws_h245SendCallback = cbTransmitComplete;
  1153. // Open Channel 0 for the Forward and Reverse Directions
  1154. // TBD
  1155. // Add instance to instance list
  1156. gpInstanceTable->CreateAndLock(pHws, &pHws->hws_dwPhysicalId);
  1157. *dwPhysicalId = pHws->hws_dwPhysicalId;
  1158. gpInstanceTable->Unlock(pHws->hws_dwPhysicalId);
  1159. HWSTRACE2(*dwPhysicalId, HWS_TRACE,
  1160. __TEXT("linkLayerInit(%d, %d) succeeded"), dwPhysicalId, dwH245Instance);
  1161. return NOERROR;
  1162. } // linkLayerInit()
  1163. LINKDLL HRESULT linkLayerShutdown(DWORD dwPhysicalId)
  1164. {
  1165. register PHWSINST pHws;
  1166. UINT uRetryCount;
  1167. register PREQUEST pReq;
  1168. if (InitializeStatus != NOERROR)
  1169. return InitializeStatus;
  1170. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1171. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1172. {
  1173. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  1174. __TEXT("linkLayerShutdown: dwPhysicalId not found"));
  1175. return LINK_INVALID_INSTANCE;
  1176. }
  1177. // mark this instance as deleted so we don't process anymore messages for it -
  1178. // note: the FALSE indicates to the TSTable class to NOT do the deletion of memory
  1179. // once the last unlock has completed (which is at the end of this function)
  1180. gpInstanceTable->Delete(dwPhysicalId, FALSE);
  1181. RemoveSocketToPhysicalIdMapping(pHws->hws_Socket);
  1182. switch (pHws->hws_uState)
  1183. {
  1184. case HWS_START:
  1185. case HWS_LISTENING:
  1186. case HWS_CONNECTING:
  1187. break;
  1188. case HWS_CONNECTED:
  1189. // Try to send all messages waiting on send queue
  1190. HWSASSERT(pHws->hws_pSendQueue != NULL);
  1191. ProcessQueuedSends(pHws);
  1192. uRetryCount = 0;
  1193. while ( pHws->hws_uState == HWS_CONNECTED &&
  1194. IsQEmpty(pHws->hws_pSendQueue) == FALSE &&
  1195. ++uRetryCount <= 5)
  1196. {
  1197. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  1198. __TEXT("linkLayerShutdown: Waiting for send %d"), uRetryCount);
  1199. ProcessQueuedSends(pHws);
  1200. Sleep(100);
  1201. }
  1202. if (pHws->hws_uState == HWS_CONNECTED)
  1203. {
  1204. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  1205. __TEXT("linkLayerShutdown: calling shutdown"));
  1206. if (shutdown(pHws->hws_Socket, 1) == SOCKET_ERROR)
  1207. {
  1208. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  1209. __TEXT("linkLayerShutdown: shutdown() returned %s"),
  1210. SocketErrorText());
  1211. }
  1212. pHws->hws_uState = HWS_CLOSING;
  1213. }
  1214. case HWS_CLOSING:
  1215. break;
  1216. case HWS_CLOSED:
  1217. break;
  1218. default:
  1219. HWSASSERT(FALSE);
  1220. } // switch
  1221. // Deallocate instance objects
  1222. SocketClose(pHws);
  1223. // Deallocate Receive queue
  1224. if (pHws->hws_pRecvQueue)
  1225. {
  1226. while ((pReq = (PREQUEST) QRemove(pHws->hws_pRecvQueue)) != NULL)
  1227. {
  1228. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,
  1229. LINK_RECV_ABORT,
  1230. pReq->req_client_data,
  1231. 0);
  1232. HWSFREE(pReq);
  1233. }
  1234. QFree(pHws->hws_pRecvQueue);
  1235. pHws->hws_pRecvQueue = NULL;
  1236. }
  1237. // Deallocate Send queue
  1238. if (pHws->hws_pSendQueue)
  1239. {
  1240. while ((pReq = (PREQUEST) QRemove(pHws->hws_pSendQueue)) != NULL)
  1241. {
  1242. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  1243. LINK_SEND_ABORT,
  1244. pReq->req_client_data,
  1245. 0);
  1246. HWSFREE(pReq);
  1247. }
  1248. QFree(pHws->hws_pSendQueue);
  1249. pHws->hws_pSendQueue = NULL;
  1250. }
  1251. gpInstanceTable->Unlock(dwPhysicalId);
  1252. HWSFREE(pHws);
  1253. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerShutdown: succeeded"));
  1254. return NOERROR;
  1255. } // linkLayerShutdown
  1256. /***************************************************************************
  1257. *
  1258. * NAME
  1259. * linkLayerGetInstance - return instance id corresponding to physical id
  1260. *
  1261. * SYNOPSIS
  1262. * LINKDLL DWORD linkLayerGetInstance(DWORD dwPhysicalId);
  1263. *
  1264. * DESCRIPTION
  1265. * Returns the Instance identifier corresponding to dwPhysId.
  1266. *
  1267. * PARAMETERS
  1268. * dwPhysicalId Physical identifier to search for
  1269. *
  1270. * RETURN VALUE
  1271. //MULTITHREAD
  1272. * INVALID_PHYS_ID (-1)No instance corresponding to dwPhysicalId found
  1273. * n>0 Instance Id corresponding to dwPhysicalId
  1274. *
  1275. ***************************************************************************/
  1276. LINKDLL DWORD linkLayerGetInstance(DWORD dwPhysicalId)
  1277. {
  1278. if (InitializeStatus == NOERROR &&
  1279. dwPhysicalId != INVALID_PHYS_ID &&
  1280. gpInstanceTable->Lock(dwPhysicalId) != NULL)
  1281. {
  1282. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerGetInstance: succeeded"));
  1283. gpInstanceTable->Unlock(dwPhysicalId);
  1284. return dwPhysicalId;
  1285. }
  1286. HWSTRACE0(dwPhysicalId, HWS_ERROR, __TEXT("linkLayerGetInstance: failed"));
  1287. return INVALID_PHYS_ID; // return failure
  1288. } // linkLayerGetInstance()
  1289. /***************************************************************************
  1290. *
  1291. * NAME
  1292. * linkLayerFlushChannel - flush transmit and/or receive channels
  1293. *
  1294. * DESCRIPTION
  1295. * This is a dummy function required only for compatibility with the SRP API.
  1296. *
  1297. * RETURN VALUE
  1298. * 0 Function succeeded.
  1299. * n!=0 Link error code (see LINKAPI.H for definitions.)
  1300. *
  1301. ***************************************************************************/
  1302. LINKDLL HRESULT linkLayerFlushChannel(DWORD dwPhysicalId, DWORD dwDirectionMask)
  1303. {
  1304. if (InitializeStatus != NOERROR)
  1305. return InitializeStatus;
  1306. PHWSINST pHws;
  1307. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1308. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1309. {
  1310. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  1311. __TEXT("linkLayerFlushChannel: dwPhysicalId not found"));
  1312. return LINK_INVALID_INSTANCE;
  1313. }
  1314. switch (dwDirectionMask & (DATALINK_RECEIVE | DATALINK_TRANSMIT))
  1315. {
  1316. case DATALINK_TRANSMIT | DATALINK_RECEIVE:
  1317. // Flush both receive and transmit
  1318. // Caveat: H.245 expects us to flush receive first!
  1319. SocketFlushRecv(pHws);
  1320. // Fall through to next case
  1321. case DATALINK_TRANSMIT:
  1322. // Flush transmit
  1323. // SockFlushSend() just removes the entries from the queue - it doesn't send them.
  1324. // So instead, call ProcessQueuedSends() to actually empty the send queue.
  1325. // SocketFlushSend(pHws);
  1326. ProcessQueuedSends(pHws);
  1327. break;
  1328. case DATALINK_RECEIVE:
  1329. // Flush receive
  1330. SocketFlushRecv(pHws);
  1331. break;
  1332. } // switch
  1333. gpInstanceTable->Unlock(dwPhysicalId);
  1334. HWSTRACE2(dwPhysicalId, HWS_TRACE,
  1335. __TEXT("linkLayerFlushChannel(%d, 0x%X) succeeded"),
  1336. dwPhysicalId, dwDirectionMask);
  1337. return NOERROR;
  1338. } // linkLayerFlushChannel()
  1339. /***************************************************************************
  1340. *
  1341. * NAME
  1342. * linkLayerFlushAll - flush transmit and receive channels
  1343. *
  1344. * DESCRIPTION
  1345. * This is a dummy function required only for compatibility with the SRP API.
  1346. *
  1347. * RETURN VALUE
  1348. * 0 Function succeeded.
  1349. * n!=0 Link error code (see LINKAPI.H for definitions.)
  1350. *
  1351. ***************************************************************************/
  1352. LINKDLL HRESULT linkLayerFlushAll(DWORD dwPhysicalId)
  1353. {
  1354. if (InitializeStatus != NOERROR)
  1355. return InitializeStatus;
  1356. PHWSINST pHws;
  1357. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1358. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1359. {
  1360. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  1361. __TEXT("linkLayerFlushAll: dwPhysicalId not found"));
  1362. return LINK_INVALID_INSTANCE;
  1363. }
  1364. // Flush both receive and transmit
  1365. // Caveat: H.245 expects us to flush receive first!
  1366. SocketFlushRecv(pHws);
  1367. SocketFlushSend(pHws);
  1368. gpInstanceTable->Unlock(dwPhysicalId);
  1369. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerFlushAll succeeded"));
  1370. return NOERROR;
  1371. } // linkLayerFlushAll()
  1372. /*++
  1373. Description:
  1374. Initiates a call to a remote node.
  1375. 1) Create a socket.
  1376. 2) Set the socket up for windows message notification of FD_CONNECT events.
  1377. 3) Attempt a connection
  1378. Arguments:
  1379. pHws - Pointer to context data from connection.
  1380. Return Value:
  1381. SUCCESS - A connection attempt was successfully initiated.
  1382. LINK_FATAL_ERROR - Error occurred while attempting to initiate a connection.
  1383. --*/
  1384. LINKDLL HRESULT linkLayerConnect(DWORD dwPhysicalId, CC_ADDR *pAddr, H245CONNECTCALLBACK callback)
  1385. {
  1386. register PHWSINST pHws;
  1387. CC_ADDR Addr;
  1388. HRESULT hr;
  1389. if (InitializeStatus != NOERROR)
  1390. return InitializeStatus;
  1391. HWSTRACE5(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerConnect: connecting to %d.%d.%d.%d/%d"),
  1392. GetIPAddress(pAddr) & 0xFF,
  1393. (GetIPAddress(pAddr) >> 8) & 0xFF,
  1394. (GetIPAddress(pAddr) >> 16) & 0xFF,
  1395. GetIPAddress(pAddr) >> 24,
  1396. ntohs(GetPort(pAddr)));
  1397. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1398. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1399. {
  1400. HWSTRACE0(dwPhysicalId, HWS_ERROR, __TEXT("linkLayerConnect: dwPhysicalId not found"));
  1401. return LINK_INVALID_INSTANCE;
  1402. }
  1403. if (pHws->hws_uState != HWS_START)
  1404. {
  1405. HWSTRACE1(dwPhysicalId, HWS_ERROR, __TEXT("linkLayerConnect: State = %s"),
  1406. SocketStateText(pHws->hws_uState));
  1407. gpInstanceTable->Unlock(dwPhysicalId);
  1408. return LINK_INVALID_STATE;
  1409. }
  1410. pHws->hws_h245ConnectCallback = callback;
  1411. // Create a socket, bind to a local address and initiate a connection.
  1412. if ((hr = SocketOpen(pHws)) != NOERROR)
  1413. {
  1414. HWSTRACE0(dwPhysicalId, HWS_WARNING,
  1415. __TEXT("linkLayerConnect: SocketOpen() failed"));
  1416. pHws->hws_uState = HWS_START;
  1417. gpInstanceTable->Unlock(dwPhysicalId);
  1418. return hr;
  1419. }
  1420. Addr.nAddrType = CC_IP_BINARY;
  1421. Addr.bMulticast = FALSE;
  1422. Addr.Addr.IP_Binary.wPort = 0;
  1423. Addr.Addr.IP_Binary.dwAddr = 0;
  1424. if ((hr = SocketBind(pHws, &Addr)) != NOERROR)
  1425. {
  1426. HWSTRACE0(dwPhysicalId, HWS_WARNING,
  1427. __TEXT("linkLayerConnect: SocketBind() failed"));
  1428. pHws->hws_uState = HWS_START;
  1429. gpInstanceTable->Unlock(dwPhysicalId);
  1430. return hr;
  1431. }
  1432. // Reminder: WinSock requires that we pass a struct sockaddr *
  1433. // to connect; however, the service provider is free to
  1434. // interpret the pointer as an arbitrary chunk of data of size
  1435. // uSockAddrLen.
  1436. pHws->hws_SockAddr.sin_port = GetPort(pAddr);
  1437. pHws->hws_SockAddr.sin_addr.S_un.S_addr = GetIPAddress(pAddr);
  1438. if (connect(pHws->hws_Socket, // s
  1439. (const struct sockaddr *)&pHws->hws_SockAddr, // name
  1440. sizeof(pHws->hws_SockAddr)) == SOCKET_ERROR) // namelen
  1441. {
  1442. int err = WSAGetLastError();
  1443. switch (err)
  1444. {
  1445. case WSAEWOULDBLOCK:
  1446. break;
  1447. default:
  1448. HWSTRACE1(dwPhysicalId, HWS_WARNING,
  1449. __TEXT("linkLayerConnect: WSAConnect() returned %s"),
  1450. SocketErrorText1(err));
  1451. SocketClose(pHws);
  1452. pHws->hws_uState = HWS_START;
  1453. gpInstanceTable->Unlock(dwPhysicalId);
  1454. return MAKE_WINSOCK_ERROR(err);
  1455. } // switch
  1456. } // if
  1457. else
  1458. {
  1459. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("connect() succeeded"));
  1460. SocketConnect(pHws, 0);
  1461. gpInstanceTable->Unlock(dwPhysicalId);
  1462. return NOERROR;
  1463. } // else
  1464. pHws->hws_uState = HWS_CONNECTING;
  1465. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerConnect: succeeded"));
  1466. gpInstanceTable->Unlock(dwPhysicalId);
  1467. return NOERROR;
  1468. } // linkLayerConnect()
  1469. /***************************************************************************
  1470. *
  1471. * NAME
  1472. * linkLayerListen - start listen on connection
  1473. *
  1474. * DESCRIPTION
  1475. * This function creates a socket,
  1476. * binds to a local address, and listens on the created socket.
  1477. * The address being listened to is returned in the structure
  1478. * pointed to by pAddr.
  1479. *
  1480. * PARAMETERS
  1481. * dwPhysicalId Link layer identifier returned by linkLayerGetInstance().
  1482. * pAddr Pointer to address structure (defined in CALLCONT.H.)
  1483. *
  1484. * RETURN VALUE
  1485. * 0 Function succeeded.
  1486. * n!=0 Error code (see LINKAPI.H for definitions.)
  1487. *
  1488. ***************************************************************************/
  1489. //MULTITHREAD => dwPhysicalID was INPUT now it's OUTPUT
  1490. LINKDLL HRESULT linkLayerListen (DWORD *dwPhysicalId, DWORD dwH245Instance, CC_ADDR *pAddr, H245CONNECTCALLBACK callback)
  1491. {
  1492. HRESULT hr;
  1493. register PHWSINST pHws;
  1494. if (InitializeStatus == LINK_INVALID_STATE)
  1495. Initialize();
  1496. if (InitializeStatus != NOERROR)
  1497. return InitializeStatus;
  1498. if ((*dwPhysicalId == INVALID_PHYS_ID) ||
  1499. (!(pHws = gpInstanceTable->Lock(*dwPhysicalId))))
  1500. {
  1501. if ((hr = linkLayerInit(dwPhysicalId, dwH245Instance, NULL, NULL)) != NOERROR)
  1502. return hr;
  1503. pHws = gpInstanceTable->Lock(*dwPhysicalId);
  1504. HWSASSERT(pHws != NULL);
  1505. }
  1506. else
  1507. {
  1508. HWSASSERT(pHws->hws_dwH245Instance == dwH245Instance);
  1509. }
  1510. if (pHws->hws_uState != HWS_START)
  1511. {
  1512. HWSTRACE1(*dwPhysicalId, HWS_ERROR, __TEXT("linkLayerListen: State = %s"),
  1513. SocketStateText(pHws->hws_uState));
  1514. gpInstanceTable->Unlock(*dwPhysicalId);
  1515. return LINK_INVALID_STATE;
  1516. }
  1517. pHws->hws_h245ConnectCallback = callback;
  1518. if ((hr = SocketOpen(pHws, FALSE)) != NOERROR)
  1519. {
  1520. HWSTRACE0(*dwPhysicalId, HWS_WARNING, __TEXT("linkLayerListen: SocketBind() failed"));
  1521. pHws->hws_uState = HWS_START;
  1522. gpInstanceTable->Unlock(*dwPhysicalId);
  1523. return hr;
  1524. }
  1525. if ((hr = SocketBind(pHws, pAddr)) != NOERROR)
  1526. {
  1527. HWSTRACE0(*dwPhysicalId, HWS_WARNING, __TEXT("linkLayerListen: SocketBind() failed"));
  1528. pHws->hws_uState = HWS_START;
  1529. gpInstanceTable->Unlock(*dwPhysicalId);
  1530. return hr;
  1531. }
  1532. // Listen for incoming connection requests on the socket.
  1533. int nBacklog = SOMAXCONN;
  1534. while (listen(pHws->hws_Socket, nBacklog) == SOCKET_ERROR)
  1535. {
  1536. int err = WSAGetLastError();
  1537. HWSTRACE1(*dwPhysicalId,
  1538. HWS_WARNING,
  1539. __TEXT("linkLayerListen: listen() returned %s"),
  1540. SocketErrorText1(err));
  1541. if (nBacklog == SOMAXCONN)
  1542. nBacklog = 10;
  1543. if (err != WSAENOBUFS || --nBacklog == 0)
  1544. {
  1545. SocketClose(pHws);
  1546. pHws->hws_uState = HWS_START;
  1547. gpInstanceTable->Unlock(*dwPhysicalId);
  1548. return MAKE_WINSOCK_ERROR(err);
  1549. }
  1550. Sleep(0);
  1551. }
  1552. if ((hr = GetLocalAddr(pHws, pAddr)) != NOERROR)
  1553. {
  1554. // getsockname() failed
  1555. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  1556. __TEXT("linkLayerListen: getsockname() returned %s"),
  1557. SocketErrorText());
  1558. SocketClose(pHws);
  1559. pHws->hws_uState = HWS_START;
  1560. gpInstanceTable->Unlock(*dwPhysicalId);
  1561. return hr;
  1562. }
  1563. HWSTRACE5(*dwPhysicalId, HWS_TRACE, __TEXT("linkLayerListen: listening on %d.%d.%d.%d/%d"),
  1564. GetIPAddress(pAddr) & 0xFF,
  1565. (GetIPAddress(pAddr) >> 8) & 0xFF,
  1566. (GetIPAddress(pAddr) >> 16) & 0xFF,
  1567. GetIPAddress(pAddr) >> 24,
  1568. ntohs(GetPort(pAddr)));
  1569. pHws->hws_uState = HWS_LISTENING;
  1570. HWSTRACE0(*dwPhysicalId, HWS_TRACE, __TEXT("linkLayerListen: succeeded"));
  1571. gpInstanceTable->Unlock(*dwPhysicalId);
  1572. return NOERROR;
  1573. } // linkLayerListen()
  1574. LINKDLL HRESULT
  1575. linkLayerAccept(DWORD dwPhysicalIdListen, DWORD dwPhysicalIdAccept, H245CONNECTCALLBACK callback)
  1576. {
  1577. PHWSINST pHwsListen;
  1578. PHWSINST pHwsAccept;
  1579. HRESULT rc;
  1580. if (InitializeStatus != NOERROR)
  1581. return InitializeStatus;
  1582. HWSTRACE0(dwPhysicalIdAccept, HWS_TRACE, __TEXT("linkLayerAccept"));
  1583. if ((dwPhysicalIdListen == INVALID_PHYS_ID) ||
  1584. (!(pHwsListen = gpInstanceTable->Lock(dwPhysicalIdListen))))
  1585. {
  1586. HWSTRACE0(dwPhysicalIdListen, HWS_ERROR, __TEXT("linkLayerAccept: dwPhysicalIdListen not found"));
  1587. return LINK_INVALID_INSTANCE;
  1588. }
  1589. pHwsAccept = gpInstanceTable->Lock(dwPhysicalIdAccept);
  1590. if (pHwsAccept == NULL)
  1591. {
  1592. HWSTRACE0(dwPhysicalIdAccept, HWS_ERROR, __TEXT("linkLayerAccept: dwPhysicalIdAccept not found"));
  1593. gpInstanceTable->Unlock(dwPhysicalIdListen);
  1594. return LINK_INVALID_INSTANCE;
  1595. }
  1596. HWSASSERT(pHwsListen->hws_uState == HWS_LISTENING);
  1597. HWSASSERT(pHwsAccept == pHwsListen || pHwsAccept->hws_uState == HWS_START);
  1598. pHwsAccept->hws_h245ConnectCallback = callback;
  1599. rc = SocketAccept(pHwsListen, pHwsAccept);
  1600. gpInstanceTable->Unlock(dwPhysicalIdListen);
  1601. gpInstanceTable->Unlock(dwPhysicalIdAccept);
  1602. return rc;
  1603. }
  1604. // Here is the corresponding redefinition of the __TEXT macro
  1605. #ifndef UNICODE_TRACE
  1606. #undef __TEXT
  1607. #define __TEXT(x) L##x
  1608. #endif
  1609. #if defined(__cplusplus)
  1610. }
  1611. #endif // (__cplusplus)