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.

1988 lines
62 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. #define LINKDLL_EXPORT
  227. #undef _WIN32_WINNT // override bogus platform definition in our common build environment
  228. #pragma warning ( disable : 4115 4201 4214 4514 )
  229. #include "precomp.h"
  230. //#include <winsock.h>
  231. #include "queue.h"
  232. #include "linkapi.h"
  233. #include "incommon.h"
  234. #include "h245ws.h"
  235. #include "tstable.h"
  236. #ifdef FORCE_SERIALIZE_CALL_CONTROL
  237. #include "cclock.h"
  238. #endif
  239. #include "q931.h"
  240. #include "hcall.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. static HRESULT SocketOpen(PHWSINST pHws, BOOL bSetLinger = TRUE);
  250. void Uninitialize();
  251. /*
  252. * Static variables
  253. */
  254. static BOOL bInitialized = FALSE;
  255. static HWND window = 0;
  256. TSTable<HWSINST>* gpInstanceTable; // global ptr to the instance table
  257. static CRITICAL_SECTION SocketToHWSInstanceMapLock;
  258. static SOCKET_TO_INSTANCE *pSocketToHWSInstanceMap = NULL;
  259. // If we are not using the Unicode enabled tracing, then undefine the __TEXT macro.
  260. // Do not place anything that should be a Unicode constant string between this #undef
  261. // and the corresponding redefinition of the macro
  262. #if defined(_DEBUG)
  263. #ifndef UNICODE_TRACE
  264. #undef __TEXT
  265. #define __TEXT(x) x
  266. static const char * StateMap[] =
  267. #else
  268. static const LPTSTR StateMap[] =
  269. #endif
  270. {
  271. __TEXT("HWS_START"), // 0 Initial state
  272. __TEXT("HWS_LISTENING"), // 1 Waiting for FD_ACCEPT
  273. __TEXT("HWS_CONNECTING"), // 2 Waiting for FD_CONNECT
  274. __TEXT("HWS_CONNECTED"), // 3 Data transfer state
  275. __TEXT("HWS_CLOSING"), // 4 Waiting for FD_CLOSE
  276. __TEXT("HWS_CLOSED"), // 5 Waiting for linkLayerShutdown()
  277. __TEXT("HWS_SHUTDOWN"), // 6 linkLayerShutdown() called from callback
  278. };
  279. static const ERROR_MAP ErrorMap[] =
  280. {
  281. 0, __TEXT("OK"),
  282. WSAEINTR, __TEXT("WSAEINTR - Interrupted function call"),
  283. WSAEBADF, __TEXT("WSAEBADF"),
  284. WSAEACCES, __TEXT("WSAEACCES - Permission denied"),
  285. WSAEFAULT, __TEXT("WSAEFAULT - Bad address"),
  286. WSAEINVAL, __TEXT("WSAEINVAL - Invalid argument"),
  287. WSAEMFILE, __TEXT("WSAEMFILE - Too many open files"),
  288. WSAEWOULDBLOCK, __TEXT("WSAEWOULDBLOCK - Resource temporarily unavailable"),
  289. WSAEINPROGRESS, __TEXT("WSAEINPROGRESS - Operation now in progress"),
  290. WSAEALREADY, __TEXT("WSAEALREADY - Operation already in progress"),
  291. WSAENOTSOCK, __TEXT("WSAENOTSOCK - Socket operation on non-socket"),
  292. WSAEDESTADDRREQ, __TEXT("WSAEDESTADDRREQ - Destination address required"),
  293. WSAEMSGSIZE, __TEXT("WSAEMSGSIZE - Message too long"),
  294. WSAEPROTOTYPE, __TEXT("WSAEPROTOTYPE - Protocol wrong type for socket"),
  295. WSAENOPROTOOPT, __TEXT("WSAENOPROTOOPT - Bad protocol option"),
  296. WSAEPROTONOSUPPORT, __TEXT("WSAEPROTONOSUPPORT - Protocol not supported"),
  297. WSAESOCKTNOSUPPORT, __TEXT("WSAESOCKTNOSUPPORT - Socket type not supported"),
  298. WSAEOPNOTSUPP, __TEXT("WSAEOPNOTSUPP - Operation not supported"),
  299. WSAEPFNOSUPPORT, __TEXT("WSAEPFNOSUPPORT - Protocol family not supported"),
  300. WSAEAFNOSUPPORT, __TEXT("WSAEAFNOSUPPORT - Address family not supported by protocol family"),
  301. WSAEADDRINUSE, __TEXT("WSAEADDRINUSE - Address already in use"),
  302. WSAEADDRNOTAVAIL, __TEXT("WSAEADDRNOTAVAIL - Cannot assign requested address"),
  303. WSAENETDOWN, __TEXT("WSAENETDOWN - Network is down"),
  304. WSAENETUNREACH, __TEXT("WSAENETUNREACH - Network is unreachable"),
  305. WSAENETRESET, __TEXT("WSAENETRESET - Network dropped connection on reset"),
  306. WSAECONNABORTED, __TEXT("WSAECONNABORTED - Software caused connection abort"),
  307. WSAECONNRESET, __TEXT("WSAECONNRESET - Connection reset by peer"),
  308. WSAENOBUFS, __TEXT("WSAENOBUFS - No buffer space available"),
  309. WSAEISCONN, __TEXT("WSAEISCONN - Socket is already connected"),
  310. WSAENOTCONN, __TEXT("WSAENOTCONN - Socket is not connected"),
  311. WSAESHUTDOWN, __TEXT("WSAESHUTDOWN - Cannot send after socket shutdown"),
  312. WSAETOOMANYREFS, __TEXT("WSAETOOMANYREFS"),
  313. WSAETIMEDOUT, __TEXT("WSAETIMEDOUT - Connection timed out"),
  314. WSAECONNREFUSED, __TEXT("WSAECONNREFUSED - Connection refused"),
  315. WSAELOOP, __TEXT("WSAELOOP"),
  316. WSAENAMETOOLONG, __TEXT("WSAENAMETOOLONG"),
  317. WSAEHOSTDOWN, __TEXT("WSAEHOSTDOWN - Host is down"),
  318. WSAEHOSTUNREACH, __TEXT("WSAEHOSTUNREACH - No route to host"),
  319. WSAENOTEMPTY, __TEXT("WSAENOTEMPTY"),
  320. WSAEPROCLIM, __TEXT("WSAEPROCLIM - Too many processes"),
  321. WSAEUSERS, __TEXT("WSAEUSERS"),
  322. WSAEDQUOT, __TEXT("WSAEDQUOT"),
  323. WSAESTALE, __TEXT("WSAESTALE"),
  324. WSAEREMOTE, __TEXT("WSAEREMOTE"),
  325. WSASYSNOTREADY, __TEXT("WSASYSNOTREADY - Network subsystem is unavailable"),
  326. WSAVERNOTSUPPORTED, __TEXT("WSAVERNOTSUPPORTED - WINSOCK.DLL version out of range"),
  327. WSANOTINITIALISED, __TEXT("WSANOTINITIALISED - Successful WSAStartup() not yet performed"),
  328. WSAEDISCON, __TEXT("WSAEDISCON - Graceful shutdown in progress"),
  329. WSAHOST_NOT_FOUND, __TEXT("WSAHOST_NOT_FOUND - Host not found"),
  330. WSATRY_AGAIN, __TEXT("WSATRY_AGAIN - Non-authoritative host not found"),
  331. WSANO_RECOVERY, __TEXT("WSANO_RECOVERY - This is a non-recoverable error"),
  332. WSANO_DATA, __TEXT("WSANO_DATA - Valid name, no data record of requested type"),
  333. // WSA_INVALID_HANDLE, __TEXT("WSA_INVALID_HANDLE - Specified event object handle is invalid"),
  334. // WSA_INVALID_PARAMETER, __TEXT("WSA_INVALID_PARAMETER - One or more parameters are invalid"),
  335. // WSA_IO_PENDING, __TEXT("WSA_IO_PENDING - Overlapped operations will complete later"),
  336. // WSA_IO_INCOMPLETE, __TEXT("WSA_IO_INCOMPLETE - Overlapped I/O event object not in signaled state"),
  337. // WSA_NOT_ENOUGH_MEMORY, __TEXT("WSA_NOT_ENOUGH_MEMORY - Insufficient memory available"),
  338. // WSA_OPERATION_ABORTED, __TEXT("WSA_OPERATION_ABORTED - Overlapped operation aborted"),
  339. };
  340. //
  341. // Function Definitions
  342. //
  343. #include <string.h>
  344. #ifdef UNICODE_TRACE
  345. static const LPTSTR
  346. #else
  347. static const char *
  348. #endif
  349. SocketStateText(UINT uState)
  350. {
  351. #ifdef UNICODE_TRACE
  352. static TCHAR szSocketStateText[80];
  353. #else
  354. static char szSocketStateText[80];
  355. #endif
  356. if (uState <= HWS_SHUTDOWN)
  357. return StateMap[uState];
  358. wsprintf(szSocketStateText, __TEXT("Unknown state %d"), uState);
  359. return szSocketStateText;
  360. } // SocketStateText()
  361. #ifdef UNICODE_TRACE
  362. static LPCTSTR
  363. #else
  364. static const char *
  365. #endif
  366. SocketErrorText1(int nErrorCode)
  367. {
  368. register int nIndex = sizeof(ErrorMap) / sizeof(ErrorMap[0]);
  369. #ifdef UNICODE_TRACE
  370. static TCHAR szSocketErrorText[80];
  371. #else
  372. static char szSocketErrorText[80];
  373. #endif
  374. while (nIndex > 0)
  375. {
  376. if (ErrorMap[--nIndex].nErrorCode == nErrorCode)
  377. {
  378. return ErrorMap[nIndex].pszErrorText;
  379. }
  380. }
  381. wsprintf(szSocketErrorText, __TEXT("Unknown error 0x%x"), nErrorCode);
  382. return szSocketErrorText;
  383. } // SocketErrorText1()
  384. #ifdef UNICODE_TRACE
  385. LPCTSTR
  386. #else
  387. const char *
  388. #endif
  389. SocketErrorText(void)
  390. {
  391. return SocketErrorText1(WSAGetLastError());
  392. } // SocketErrorText()
  393. #endif // (_DEBUG)
  394. /***************************************************************************
  395. *
  396. * Local routines
  397. *
  398. ***************************************************************************/
  399. static DWORD
  400. HashSocket(SOCKET socket)
  401. {
  402. return(DWORD)((socket >> 2) % SOCK_TO_PHYSID_TABLE_SIZE);
  403. }
  404. DWORD
  405. SocketToPhysicalId(SOCKET socket)
  406. {
  407. // hash the socket to get an index into the SocketToHWSInstanceMap table
  408. DWORD idx = HashSocket(socket);
  409. if(pSocketToHWSInstanceMap == NULL)
  410. return(INVALID_PHYS_ID);
  411. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  412. // idx indicates the entry point in the array, now traverse the linked list
  413. PSOCKET_TO_INSTANCE pEntry = &pSocketToHWSInstanceMap[idx];
  414. while(pEntry != NULL)
  415. {
  416. if(pEntry->socket == socket)
  417. {
  418. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  419. return(pEntry->dwPhysicalId);
  420. } else
  421. {
  422. pEntry = pEntry->next;
  423. }
  424. }
  425. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  426. return(INVALID_PHYS_ID);
  427. } // SocketToPhysicalId()
  428. BOOL
  429. CreateSocketToPhysicalIdMapping(SOCKET socket, DWORD dwPhysicalId)
  430. {
  431. // hash the socket to get an index into the SocketToHWSInstanceMap table
  432. DWORD idx = HashSocket(socket);
  433. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  434. // idx indicates the entry point in the array, now traverse the linked list
  435. PSOCKET_TO_INSTANCE pEntry = &pSocketToHWSInstanceMap[idx];
  436. PSOCKET_TO_INSTANCE pNewEntry;
  437. if (pEntry->socket == INVALID_SOCKET)
  438. {
  439. pNewEntry = pEntry;
  440. } else
  441. {
  442. pNewEntry = new SOCKET_TO_INSTANCE;
  443. if (pNewEntry == NULL)
  444. {
  445. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  446. return(FALSE);
  447. }
  448. pNewEntry->next = pEntry->next;
  449. pEntry->next = pNewEntry;
  450. }
  451. pNewEntry->socket = socket;
  452. pNewEntry->dwPhysicalId = dwPhysicalId;
  453. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  454. return(TRUE);
  455. }
  456. BOOL
  457. RemoveSocketToPhysicalIdMapping(SOCKET socket)
  458. {
  459. if (socket == INVALID_SOCKET)
  460. return(FALSE);
  461. // hash the socket to get an index into the SocketToHWSInstanceMap table
  462. DWORD idx = HashSocket(socket);
  463. BOOL bFound = FALSE;
  464. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  465. // idx indicates the entry point in the array, now traverse the linked list
  466. PSOCKET_TO_INSTANCE pEntry = &pSocketToHWSInstanceMap[idx];
  467. if (pEntry->socket == socket)
  468. {
  469. pEntry->socket = INVALID_SOCKET;
  470. bFound = TRUE;
  471. } else
  472. {
  473. PSOCKET_TO_INSTANCE pNextEntry;
  474. pNextEntry = pEntry->next;
  475. while (bFound == FALSE && pNextEntry != NULL)
  476. {
  477. if(pNextEntry->socket == socket)
  478. {
  479. pEntry->next = pNextEntry->next;
  480. delete pNextEntry;
  481. bFound = TRUE;
  482. } else
  483. {
  484. pEntry = pNextEntry;
  485. pNextEntry = pNextEntry->next;
  486. }
  487. }
  488. }
  489. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  490. return(bFound);
  491. }
  492. static unsigned short GetPort (CC_ADDR *pAddr)
  493. {
  494. unsigned short int port = 0;
  495. switch (pAddr->nAddrType)
  496. {
  497. case CC_IP_DOMAIN_NAME:
  498. port = pAddr->Addr.IP_DomainName.wPort;
  499. break;
  500. case CC_IP_DOT:
  501. port = pAddr->Addr.IP_Dot.wPort;
  502. break;
  503. case CC_IP_BINARY:
  504. port = pAddr->Addr.IP_Binary.wPort;
  505. break;
  506. } // switch
  507. return htons(port);
  508. } // GetPort()
  509. static unsigned long GetIPAddress (CC_ADDR *pAddr)
  510. {
  511. struct hostent * pHostEnt;
  512. char szAddr[256];
  513. switch (pAddr->nAddrType)
  514. {
  515. case CC_IP_DOMAIN_NAME:
  516. WideCharToMultiByte(CP_ACP, // code page
  517. 0, // dwFlags
  518. pAddr->Addr.IP_DomainName.cAddr,
  519. -1, // Unicode string length (bytes)
  520. szAddr, // ASCII string
  521. sizeof(szAddr), // max ASCII string length
  522. NULL, // default character
  523. NULL); // default character used
  524. pHostEnt = gethostbyname(szAddr);
  525. if (pHostEnt == NULL || pHostEnt->h_addr_list == NULL)
  526. return 0;
  527. return *((unsigned long *)pHostEnt->h_addr_list[0]);
  528. case CC_IP_DOT:
  529. WideCharToMultiByte(CP_ACP, // code page
  530. 0, // dwFlags
  531. pAddr->Addr.IP_Dot.cAddr,
  532. -1, // Unicode string length (bytes)
  533. szAddr, // ASCII string
  534. sizeof(szAddr), // max ASCII string length
  535. NULL, // default character
  536. NULL); // default character used
  537. return inet_addr(szAddr);
  538. case CC_IP_BINARY:
  539. return pAddr->Addr.IP_Binary.dwAddr == 0 ? INADDR_ANY : htonl(pAddr->Addr.IP_Binary.dwAddr);
  540. } // switch
  541. return 0;
  542. } // GetIPAddress()
  543. static HRESULT GetLocalAddr(PHWSINST pHws, CC_ADDR *pAddr)
  544. {
  545. SOCKADDR_IN sockaddr;
  546. int len = sizeof(sockaddr);
  547. if (getsockname(pHws->hws_Socket,
  548. (struct sockaddr *)&sockaddr,
  549. &len) == SOCKET_ERROR)
  550. {
  551. return MAKE_WINSOCK_ERROR(WSAGetLastError());
  552. }
  553. pAddr->nAddrType = CC_IP_BINARY;
  554. pAddr->bMulticast = FALSE;
  555. pAddr->Addr.IP_Binary.wPort = ntohs(sockaddr.sin_port);
  556. pAddr->Addr.IP_Binary.dwAddr = ntohl(sockaddr.sin_addr.S_un.S_addr);
  557. return NOERROR;
  558. }
  559. static HRESULT GetPeerAddr(PHWSINST pHws, CC_ADDR *pAddr)
  560. {
  561. SOCKADDR_IN sockaddr;
  562. int len = sizeof(sockaddr);
  563. if (getpeername(pHws->hws_Socket,
  564. (struct sockaddr *)&sockaddr,
  565. &len) == SOCKET_ERROR)
  566. {
  567. return MAKE_WINSOCK_ERROR(WSAGetLastError());
  568. }
  569. pAddr->nAddrType = CC_IP_BINARY;
  570. pAddr->bMulticast = FALSE;
  571. pAddr->Addr.IP_Binary.wPort = ntohs(sockaddr.sin_port);
  572. pAddr->Addr.IP_Binary.dwAddr = ntohl(sockaddr.sin_addr.S_un.S_addr);
  573. return NOERROR;
  574. }
  575. static void
  576. SocketFlushRecv(PHWSINST pHws)
  577. {
  578. register PREQUEST pReq;
  579. if (pHws->hws_pRecvQueue)
  580. {
  581. while ((pReq = (PREQUEST) QRemove(pHws->hws_pRecvQueue)) != NULL)
  582. {
  583. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,
  584. LINK_RECV_ABORT,
  585. pReq->req_client_data,
  586. 0);
  587. MemFree(pReq);
  588. }
  589. }
  590. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,
  591. LINK_FLUSH_COMPLETE,
  592. NULL,
  593. 0);
  594. } // SocketFlushRecv()
  595. static void
  596. SocketFlushSend(PHWSINST pHws)
  597. {
  598. register PREQUEST pReq;
  599. if (pHws->hws_pSendQueue)
  600. {
  601. while ((pReq = (PREQUEST) QRemove(pHws->hws_pSendQueue)) != NULL)
  602. {
  603. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  604. LINK_SEND_ABORT,
  605. pReq->req_client_data,
  606. 0);
  607. MemFree(pReq);
  608. }
  609. }
  610. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  611. LINK_FLUSH_COMPLETE,
  612. NULL,
  613. 0);
  614. } // SocketFlushSend()
  615. void
  616. SocketCloseEvent(PHWSINST pHws)
  617. {
  618. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketCloseEvent"));
  619. if (pHws->hws_uState == HWS_CONNECTED)
  620. {
  621. register DWORD dwPhysicalId = pHws->hws_dwPhysicalId;
  622. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,LINK_RECV_CLOSED,0,0);
  623. // Check to see if callback deallocated our instance or state changed
  624. if(gpInstanceTable->Validate(dwPhysicalId) == FALSE)
  625. return;
  626. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  627. __TEXT("SocketCloseEvent: calling shutdown"));
  628. if (shutdown(pHws->hws_Socket, 1) == SOCKET_ERROR)
  629. {
  630. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  631. __TEXT("HandleNetworkEvent: shutdown() returned %s"),
  632. SocketErrorText());
  633. }
  634. }
  635. pHws->hws_uState = HWS_CLOSED;
  636. } // SocketCloseEvent()
  637. /*
  638. * DESCRIPTION
  639. * Deallocate all allocated objects except for task handle
  640. */
  641. static void
  642. SocketClose(PHWSINST pHws)
  643. {
  644. HWSASSERT(pHws != NULL);
  645. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  646. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketClose"));
  647. pHws->hws_uState = HWS_CLOSED;
  648. RemoveSocketToPhysicalIdMapping(pHws->hws_Socket);
  649. // Close the socket
  650. if (pHws->hws_Socket != INVALID_SOCKET)
  651. {
  652. // To make the linger work, turn off WSAAsyncSelect to turn off
  653. // non-blocking via ioctlsocket, to close the socket.
  654. unsigned long blocking = 0;
  655. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  656. __TEXT("SocketClose: calling closesocket"));
  657. WSAAsyncSelect(pHws->hws_Socket,
  658. window, WINSOCK_EVENT_MSG,
  659. 0);
  660. ioctlsocket(pHws->hws_Socket, FIONBIO,&blocking);
  661. if (closesocket(pHws->hws_Socket) == SOCKET_ERROR)
  662. {
  663. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  664. __TEXT("SocketClose: closesocket() returned %s"),
  665. SocketErrorText());
  666. }
  667. pHws->hws_Socket = INVALID_SOCKET;
  668. }
  669. } // SocketClose()
  670. static HRESULT
  671. SocketOpen(PHWSINST pHws, BOOL bSetLinger)
  672. {
  673. HWSASSERT(pHws != NULL);
  674. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  675. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketOpen"));
  676. // Create a socket
  677. pHws->hws_Socket = socket(AF_INET, SOCK_STREAM, 0);
  678. if (pHws->hws_Socket == INVALID_SOCKET)
  679. {
  680. // WSASocket() failed
  681. int err = WSAGetLastError();
  682. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  683. __TEXT("SocketOpen: socket() returned %s"),
  684. SocketErrorText1(err));
  685. SocketClose(pHws);
  686. return MAKE_WINSOCK_ERROR(err);
  687. }
  688. /*
  689. ** Request notification messages for all events on this socket.
  690. ** Note that this call automatically puts the socket into non-blocking
  691. ** mode, as if we had called WSAIoctl with the FIONBIO flag.
  692. **/
  693. if (WSAAsyncSelect(pHws->hws_Socket,
  694. window, WINSOCK_EVENT_MSG,
  695. FD_ALL_EVENTS) == SOCKET_ERROR)
  696. {
  697. int err = WSAGetLastError();
  698. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  699. __TEXT("SocketOpen: WSAASyncSelect() returned %s"),
  700. SocketErrorText1(err));
  701. SocketClose(pHws);
  702. return MAKE_WINSOCK_ERROR(err);
  703. }
  704. if(bSetLinger == TRUE)
  705. {
  706. // Set a linger structure for the socket so that closesocket will block for a period of time (until all
  707. // data is sent or the timeout value) before actually killing the connection.
  708. // This change is being made in order to get rid of the PeekMessage() loops in linklayerShutdown().
  709. struct linger sockLinger;
  710. sockLinger.l_onoff = 1; // yes we want to linger (wait for FIN ACK after sending data and FIN)
  711. sockLinger.l_linger = 1; // linger for up to 1 second
  712. if(setsockopt (pHws->hws_Socket,
  713. SOL_SOCKET,
  714. SO_LINGER,
  715. (const char*) &sockLinger,
  716. sizeof(sockLinger)) == SOCKET_ERROR)
  717. {
  718. int err = WSAGetLastError();
  719. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  720. __TEXT("SocketOpen: setsockopt returned %s"),
  721. SocketErrorText1(err));
  722. SocketClose(pHws);
  723. return MAKE_WINSOCK_ERROR(err);
  724. }
  725. }
  726. // add an entry in the socket to instance map
  727. if(CreateSocketToPhysicalIdMapping(pHws->hws_Socket, pHws->hws_dwPhysicalId) != TRUE)
  728. {
  729. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_WARNING,
  730. __TEXT("SocketOpen: CreateSocketToPhysicalIdMapping() failed"));
  731. SocketClose(pHws);
  732. return(LINK_MEM_FAILURE);
  733. }
  734. return NOERROR;
  735. } // SocketOpen()
  736. static HRESULT
  737. SocketBind(PHWSINST pHws, CC_ADDR *pAddr)
  738. {
  739. HWSASSERT(pHws != NULL);
  740. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  741. HWSASSERT(pAddr != NULL);
  742. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketBind"));
  743. // Get a local address to bind the socket to
  744. pHws->hws_SockAddr.sin_family = AF_INET;
  745. pHws->hws_SockAddr.sin_port = GetPort(pAddr);
  746. pHws->hws_SockAddr.sin_addr.S_un.S_addr = GetIPAddress(pAddr);
  747. if ((pAddr->nAddrType == CC_IP_DOMAIN_NAME) &&
  748. (pHws->hws_SockAddr.sin_addr.S_un.S_addr == 0))
  749. {
  750. return LINK_UNKNOWN_ADDR;
  751. }
  752. // Bind the socket
  753. while (bind(pHws->hws_Socket, // s
  754. (const struct sockaddr *)&pHws->hws_SockAddr, // name
  755. sizeof(pHws->hws_SockAddr)) == SOCKET_ERROR) // namelen
  756. {
  757. // bind() failed
  758. int err = WSAGetLastError();
  759. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  760. __TEXT("SocketBind: bind() returned %s"),
  761. SocketErrorText1(err));
  762. if (err != WSAENOBUFS)
  763. {
  764. return MAKE_WINSOCK_ERROR(err);
  765. }
  766. Sleep(0);
  767. }
  768. return NOERROR;
  769. } // SocketBind()
  770. static void
  771. SocketConnect(PHWSINST pHws, int error)
  772. {
  773. HWSASSERT(pHws != NULL);
  774. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  775. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("SocketConnect"));
  776. if (error == 0)
  777. {
  778. pHws->hws_uState = HWS_CONNECTED;
  779. if (pHws->hws_h245ConnectCallback)
  780. {
  781. CC_ADDR LocalAddr;
  782. CC_ADDR PeerAddr;
  783. PCC_ADDR pLocalAddr = &LocalAddr;
  784. PCC_ADDR pPeerAddr = &PeerAddr;
  785. DWORD dwPhysicalId = pHws->hws_dwPhysicalId;
  786. HRESULT hr;
  787. hr = GetLocalAddr(pHws, pLocalAddr);
  788. if (FAILED(hr))
  789. {
  790. WARNING_OUT(("SocketConnect - failed to get local address w/ error 0x%08x", hr));
  791. pLocalAddr = NULL;
  792. }
  793. else
  794. {
  795. hr = GetPeerAddr(pHws, pPeerAddr);
  796. if (FAILED(hr))
  797. {
  798. WARNING_OUT(("SocketConnect - failed to get remote address w/ error 0x%08x", hr));
  799. pPeerAddr = NULL;
  800. }
  801. else
  802. {
  803. // All is OK
  804. hr = LINK_CONNECT_COMPLETE;
  805. }
  806. }
  807. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  808. hr, pLocalAddr, pPeerAddr);
  809. // Check to see if callback deallocated our instance - this can be done
  810. // by attempting a lock - which will now fail if the entry has been marked
  811. // for deletion. Thus, if the lock succeeds, then just unlock it (since we
  812. // already have a lock on it).
  813. if (gpInstanceTable->Validate(dwPhysicalId) == FALSE)
  814. return;
  815. }
  816. NotifyWrite(pHws);
  817. NotifyRead(pHws);
  818. }
  819. else
  820. {
  821. if (pHws->hws_h245ConnectCallback)
  822. {
  823. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  824. MAKE_WINSOCK_ERROR(error), NULL, NULL);
  825. }
  826. }
  827. } // SocketConnect()
  828. static HRESULT
  829. SocketAccept(PHWSINST pHwsListen, PHWSINST pHwsAccept)
  830. {
  831. SOCKET listen_socket = pHwsListen->hws_Socket;
  832. struct linger sockLinger;
  833. sockLinger.l_onoff = 1; // yes we want to linger (wait for FIN ACK after sending data and FIN)
  834. sockLinger.l_linger = 1; // linger for up to 1 second
  835. // Accept the connection.
  836. pHwsAccept->hws_uSockAddrLen = sizeof(pHwsAccept->hws_SockAddr);
  837. pHwsAccept->hws_Socket = accept(pHwsListen->hws_Socket,
  838. (struct sockaddr *)&pHwsAccept->hws_SockAddr,
  839. (int *)&pHwsAccept->hws_uSockAddrLen);
  840. if (pHwsAccept->hws_Socket == INVALID_SOCKET)
  841. {
  842. int err = WSAGetLastError();
  843. HWSTRACE1(pHwsAccept->hws_dwPhysicalId, HWS_WARNING,
  844. __TEXT("linkLayerAccept: accept() returned %s"),
  845. SocketErrorText1(err));
  846. SocketConnect(pHwsAccept, err);
  847. return MAKE_WINSOCK_ERROR(err);
  848. }
  849. if (pHwsListen == pHwsAccept)
  850. {
  851. HWSTRACE0(pHwsListen->hws_dwPhysicalId, HWS_TRACE,
  852. __TEXT("SocketClose: calling closesocket"));
  853. closesocket(listen_socket);
  854. RemoveSocketToPhysicalIdMapping(listen_socket);
  855. }
  856. // Set a linger structure for the socket so that closesocket will block for a period of time (until all
  857. // data is sent or the timeout value) before actually killing the connection.
  858. // This change is being made in order to get rid of the PeekMessage() loops in linklayerShutdown().
  859. if(setsockopt (pHwsAccept->hws_Socket,
  860. SOL_SOCKET,
  861. SO_LINGER,
  862. (const char*) &sockLinger,
  863. sizeof(sockLinger)) == SOCKET_ERROR)
  864. {
  865. int err = WSAGetLastError();
  866. HWSTRACE1(pHwsAccept->hws_dwPhysicalId, HWS_WARNING,
  867. __TEXT("SocketAccept: setsockopt returned %s"),
  868. SocketErrorText1(err));
  869. SocketClose(pHwsAccept);
  870. return MAKE_WINSOCK_ERROR(err);
  871. }
  872. // add the new socket to the socket to phys id map
  873. CreateSocketToPhysicalIdMapping(pHwsAccept->hws_Socket, pHwsAccept->hws_dwPhysicalId);
  874. SocketConnect(pHwsAccept, 0);
  875. return NOERROR;
  876. } // SocketAccept()
  877. /*++
  878. Description:
  879. Handles network events that may occur on a connected socket.
  880. The events handled by this function are FD_ACCEPT, FD_CLOSE, FD_READ, and
  881. FD_WRITE.
  882. Arguments:
  883. pHws - pointer to data for the connection on which the event happened.
  884. event - event that occurred
  885. error - error code accompanying the event
  886. Return Value:
  887. SUCCESS - The network event was successfully handled.
  888. LINK_FATAL_ERROR - Some kind of error occurred while handling the
  889. event, and the connection should be closed.
  890. LINK_RECV_CLOSED - The connection has been gracefully closed.
  891. --*/
  892. static void
  893. HandleNetworkEvent(PHWSINST pHws, int event, int error)
  894. {
  895. HWSASSERT(pHws != NULL);
  896. HWSASSERT(pHws->hws_dwMagic == HWSINST_MAGIC);
  897. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE, __TEXT("HandleNetworkEvent"));
  898. if (error == WSAENETDOWN)
  899. {
  900. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  901. __TEXT("HandleSocketEvent: Connection error"));
  902. pHws->hws_uState = HWS_CLOSED;
  903. return;
  904. }
  905. switch (event)
  906. {
  907. case FD_READ:
  908. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  909. __TEXT("HandleNetworkEvent: FD_READ %s"),
  910. SocketErrorText1(error));
  911. if (error == 0 && pHws->hws_uState <= HWS_CLOSING)
  912. {
  913. ProcessQueuedRecvs(pHws);
  914. }
  915. break;
  916. case FD_WRITE:
  917. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  918. __TEXT("HandleNetworkEvent: FD_WRITE %s"),
  919. SocketErrorText1(error));
  920. if (error == 0 && pHws->hws_uState <= HWS_CONNECTED)
  921. {
  922. ProcessQueuedSends(pHws);
  923. }
  924. break;
  925. case FD_OOB:
  926. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  927. __TEXT("HandleNetworkEvent: FD_OOB %s"),
  928. SocketErrorText1(error));
  929. break;
  930. case FD_ACCEPT:
  931. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  932. __TEXT("HandleNetworkEvent: FD_ACCEPT %s"),
  933. SocketErrorText1(error));
  934. if (pHws->hws_h245ConnectCallback != NULL)
  935. {
  936. if (error == 0)
  937. {
  938. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  939. LINK_CONNECT_REQUEST, NULL, NULL);
  940. }
  941. else
  942. {
  943. pHws->hws_h245ConnectCallback(pHws->hws_dwH245Instance,
  944. MAKE_WINSOCK_ERROR(error), NULL, NULL);
  945. }
  946. }
  947. else if (error == 0)
  948. {
  949. // If the client did not specify a callback, accept the call using the same physical
  950. // Id as the listen. This will result in the listen socket being closed.
  951. SocketAccept(pHws, pHws);
  952. }
  953. break;
  954. case FD_CONNECT:
  955. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  956. __TEXT("HandleNetworkEvent: FD_CONNECT %s"),
  957. SocketErrorText1(error));
  958. SocketConnect(pHws, error);
  959. break;
  960. case FD_CLOSE:
  961. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  962. __TEXT("HandleNetworkEvent: FD_CLOSE %s"),
  963. SocketErrorText1(error));
  964. SocketCloseEvent(pHws);
  965. break;
  966. }
  967. } // HandleNetworkEvent()
  968. LRESULT APIENTRY WndProc(
  969. HWND hWnd, /* window handle */
  970. UINT message, /* type of message */
  971. WPARAM wParam, /* additional information */
  972. LPARAM lParam) /* additional information */
  973. {
  974. PHWSINST pHws;
  975. DWORD dwPhysicalId;
  976. #ifdef FORCE_SERIALIZE_CALL_CONTROL
  977. CCLOCK_AcquireLock();
  978. #endif
  979. switch (message)
  980. {
  981. case WINSOCK_EVENT_MSG:
  982. if (((dwPhysicalId=SocketToPhysicalId((SOCKET)wParam)) == INVALID_PHYS_ID) ||
  983. ((pHws=gpInstanceTable->Lock(dwPhysicalId)) == NULL))
  984. {
  985. HWSTRACE1(0, HWS_WARNING,
  986. __TEXT("WndProc: Winsock event on unknown socket 0x%x"),
  987. wParam);
  988. break;
  989. }
  990. HandleNetworkEvent(pHws, WSAGETSELECTEVENT(lParam), WSAGETSELECTERROR(lParam));
  991. gpInstanceTable->Unlock(dwPhysicalId);
  992. break;
  993. default:
  994. {
  995. #ifdef FORCE_SERIALIZE_CALL_CONTROL
  996. CCLOCK_RelinquishLock();
  997. #endif
  998. return DefWindowProc(hWnd, message, wParam, lParam);
  999. }
  1000. }
  1001. #ifdef FORCE_SERIALIZE_CALL_CONTROL
  1002. CCLOCK_RelinquishLock();
  1003. #endif
  1004. return (0);
  1005. }
  1006. void NotifyRead(PHWSINST pHws)
  1007. {
  1008. PostMessage(window, WINSOCK_EVENT_MSG, (WPARAM)pHws->hws_Socket, (LPARAM)MAKELONG(FD_READ, 0));
  1009. }
  1010. void NotifyWrite(PHWSINST pHws)
  1011. {
  1012. PostMessage(window, WINSOCK_EVENT_MSG, (WPARAM)pHws->hws_Socket, (LPARAM)MAKELONG(FD_WRITE, 0));
  1013. }
  1014. /*++
  1015. Description:
  1016. Calls WSAStartup, makes sure we have a good version of WinSock
  1017. Arguments:
  1018. None.
  1019. Return Value:
  1020. 0 WinSock DLL successfully started up.
  1021. LINK_FATAL_ERROR Error starting up WinSock DLL.
  1022. --*/
  1023. static const TCHAR CLASS_NAME[] = __TEXT("H245WSWndClass");
  1024. int WinsockInitError = -1;
  1025. HRESULT InitializeStatus = LINK_INVALID_STATE;
  1026. LINKDLL VOID H245WSShutdown()
  1027. {
  1028. Uninitialize();
  1029. }
  1030. void Initialize()
  1031. {
  1032. WORD wVersion = MAKEWORD(1, 1);
  1033. WSADATA WsaData; // receives data from WSAStartup
  1034. WNDCLASS wndclass = { 0, WndProc, 0, 0, 0, 0, 0, 0, NULL, CLASS_NAME };
  1035. DWORD dwIndex;
  1036. // Caveat: We can't use WSAGetLastError() for WSAStartup failure!
  1037. if ((WinsockInitError = WSAStartup(wVersion, &WsaData)) != 0)
  1038. {
  1039. HWSTRACE0(0, HWS_WARNING, __TEXT("linkLayerInit: WSAStartup() failed"));
  1040. InitializeStatus = MAKE_WINSOCK_ERROR(WinsockInitError);
  1041. return;
  1042. }
  1043. if (LOBYTE(WsaData.wVersion) != 1 ||
  1044. HIBYTE(WsaData.wVersion) != 1)
  1045. {
  1046. HWSTRACE0(0, HWS_WARNING, __TEXT("linkLayerInit: Winsock version mismatch"));
  1047. InitializeStatus = MAKE_WINSOCK_ERROR(WSAVERNOTSUPPORTED);
  1048. return;
  1049. }
  1050. // Create window to receive Winsock messages
  1051. if (RegisterClass(&wndclass) == 0
  1052. || (window = CreateWindow(CLASS_NAME, __TEXT(""), WS_OVERLAPPED, 0, 0, 0, 0, 0, 0, 0, NULL)) == 0)
  1053. {
  1054. HWSTRACE0(0, HWS_WARNING, __TEXT("linkLayerInit: error creating window"));
  1055. InitializeStatus = HRESULT_FROM_WIN32(GetLastError());
  1056. return;
  1057. }
  1058. //
  1059. // LAURABU
  1060. // BOGUS BUGBUG
  1061. //
  1062. // This table code was never stressed by the people who wrote it. It
  1063. // totally falls apart when it completely fills up
  1064. // * Allocating the last item doesn't work
  1065. // * Freeing the last item doesn't work
  1066. // * Resizing larger doesn't work
  1067. //
  1068. // Since it doesn't take a lot of memory, a decent solution is to just
  1069. // allocate it maximum+1 sized, and leave the last item free.
  1070. //
  1071. gpInstanceTable = new TSTable <HWSINST> (257);
  1072. if(gpInstanceTable == NULL || gpInstanceTable->IsInitialized() == FALSE)
  1073. {
  1074. InitializeStatus = LINK_MEM_FAILURE;
  1075. return;
  1076. }
  1077. pSocketToHWSInstanceMap = new SOCKET_TO_INSTANCE[SOCK_TO_PHYSID_TABLE_SIZE];
  1078. if(pSocketToHWSInstanceMap == NULL)
  1079. {
  1080. InitializeStatus = LINK_MEM_FAILURE;
  1081. return;
  1082. }
  1083. InitializeCriticalSection(&SocketToHWSInstanceMapLock);
  1084. memset(pSocketToHWSInstanceMap, 0, sizeof(SOCKET_TO_INSTANCE) * SOCK_TO_PHYSID_TABLE_SIZE);
  1085. // Init the sockets to a bad value
  1086. for (dwIndex = 0; dwIndex < SOCK_TO_PHYSID_TABLE_SIZE; dwIndex++)
  1087. {
  1088. pSocketToHWSInstanceMap[dwIndex].socket = INVALID_SOCKET;
  1089. }
  1090. InitializeStatus = NOERROR;
  1091. bInitialized = TRUE;
  1092. }
  1093. void Uninitialize()
  1094. {
  1095. if(bInitialized)
  1096. {
  1097. if (WinsockInitError == 0)
  1098. {
  1099. if (window)
  1100. {
  1101. DestroyWindow(window);
  1102. window = 0;
  1103. UnregisterClass(CLASS_NAME, 0);
  1104. if (gpInstanceTable)
  1105. {
  1106. delete gpInstanceTable;
  1107. if (InitializeStatus == NOERROR)
  1108. {
  1109. EnterCriticalSection(&SocketToHWSInstanceMapLock);
  1110. delete pSocketToHWSInstanceMap;
  1111. LeaveCriticalSection(&SocketToHWSInstanceMapLock);
  1112. DeleteCriticalSection(&SocketToHWSInstanceMapLock);
  1113. }
  1114. }
  1115. }
  1116. WSACleanup();
  1117. }
  1118. bInitialized = FALSE;
  1119. }
  1120. }
  1121. /***************************************************************************
  1122. *
  1123. * External entry points
  1124. *
  1125. ***************************************************************************/
  1126. //MULTITHREAD => dwH245Instance is now an OUTPUT param not an INPUT param.
  1127. LINKDLL HRESULT linkLayerInit (DWORD *dwPhysicalId,
  1128. DWORD_PTR dwH245Instance,
  1129. H245SRCALLBACK cbReceiveComplete,
  1130. H245SRCALLBACK cbTransmitComplete)
  1131. {
  1132. register PHWSINST pHws;
  1133. *dwPhysicalId = INVALID_PHYS_ID; // Just in case...
  1134. // Put Initialize back in here so we know everything we need is up and
  1135. // running.
  1136. if (InitializeStatus == LINK_INVALID_STATE)
  1137. Initialize();
  1138. if (InitializeStatus != NOERROR)
  1139. return InitializeStatus;
  1140. pHws = (PHWSINST)MemAlloc(sizeof(*pHws));
  1141. if (pHws == NULL)
  1142. {
  1143. // couldn't allocate our context. Return
  1144. HWSTRACE0(INVALID_PHYS_ID, HWS_WARNING, __TEXT("linkLayerInit: could not allocate context"));
  1145. return LINK_MEM_FAILURE;
  1146. }
  1147. memset(pHws, 0, sizeof(*pHws));
  1148. pHws->hws_Socket = INVALID_SOCKET;
  1149. #if defined(_DEBUG)
  1150. pHws->hws_dwMagic = HWSINST_MAGIC;
  1151. #endif // (_DEBUG)
  1152. // Create and initialize the Receive queue
  1153. pHws->hws_pRecvQueue = QCreate();
  1154. if (pHws->hws_pRecvQueue == NULL)
  1155. {
  1156. HWSTRACE0(INVALID_PHYS_ID, HWS_WARNING, __TEXT("linkLayerInit: could not allocate Receive queue"));
  1157. MemFree(pHws);
  1158. return LINK_MEM_FAILURE;
  1159. }
  1160. // Create and initialize the Send queue
  1161. pHws->hws_pSendQueue = QCreate();
  1162. if (pHws->hws_pSendQueue == NULL)
  1163. {
  1164. HWSTRACE0(INVALID_PHYS_ID, HWS_WARNING, __TEXT("linkLayerInit: could not allocate Send queue"));
  1165. QFree(pHws->hws_pRecvQueue);
  1166. MemFree(pHws);
  1167. return LINK_MEM_FAILURE;
  1168. }
  1169. // Save intance identifiers and callback pointers
  1170. pHws->hws_uState = HWS_START;
  1171. pHws->hws_dwH245Instance = dwH245Instance;
  1172. pHws->hws_h245RecvCallback = cbReceiveComplete;
  1173. pHws->hws_h245SendCallback = cbTransmitComplete;
  1174. // Open Channel 0 for the Forward and Reverse Directions
  1175. // TBD
  1176. // Add instance to instance list
  1177. if(!gpInstanceTable->CreateAndLock(pHws, &pHws->hws_dwPhysicalId))
  1178. {
  1179. Q931HangupPendingCalls(NULL);
  1180. if(!gpInstanceTable->CreateAndLock(pHws, &pHws->hws_dwPhysicalId))
  1181. {
  1182. HWSTRACE0(INVALID_PHYS_ID, HWS_WARNING, __TEXT("linkLayerInit: could not add to instance table"));
  1183. QFree(pHws->hws_pSendQueue);
  1184. QFree(pHws->hws_pRecvQueue);
  1185. MemFree(pHws);
  1186. return LINK_INSTANCE_TABLE_FULL;
  1187. }
  1188. }
  1189. *dwPhysicalId = pHws->hws_dwPhysicalId;
  1190. gpInstanceTable->Unlock(pHws->hws_dwPhysicalId);
  1191. HWSTRACE2(*dwPhysicalId, HWS_TRACE,
  1192. __TEXT("linkLayerInit(%d, %d) succeeded"), dwPhysicalId, dwH245Instance);
  1193. return NOERROR;
  1194. } // linkLayerInit()
  1195. LINKDLL HRESULT linkLayerShutdown(DWORD dwPhysicalId)
  1196. {
  1197. register PHWSINST pHws;
  1198. UINT uRetryCount;
  1199. register PREQUEST pReq;
  1200. if (InitializeStatus != NOERROR)
  1201. return InitializeStatus;
  1202. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1203. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1204. {
  1205. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  1206. __TEXT("linkLayerShutdown: dwPhysicalId not found"));
  1207. return LINK_INVALID_INSTANCE;
  1208. }
  1209. // mark this instance as deleted so we don't process anymore messages for it -
  1210. // note: the FALSE indicates to the TSTable class to NOT do the deletion of memory
  1211. // once the last unlock has completed (which is at the end of this function)
  1212. gpInstanceTable->Delete(dwPhysicalId, FALSE);
  1213. RemoveSocketToPhysicalIdMapping(pHws->hws_Socket);
  1214. switch (pHws->hws_uState)
  1215. {
  1216. case HWS_START:
  1217. case HWS_LISTENING:
  1218. case HWS_CONNECTING:
  1219. break;
  1220. case HWS_CONNECTED:
  1221. // Try to send all messages waiting on send queue
  1222. HWSASSERT(pHws->hws_pSendQueue != NULL);
  1223. ProcessQueuedSends(pHws);
  1224. uRetryCount = 0;
  1225. while ( pHws->hws_uState == HWS_CONNECTED &&
  1226. IsQEmpty(pHws->hws_pSendQueue) == FALSE &&
  1227. ++uRetryCount <= 5)
  1228. {
  1229. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_NOTIFY,
  1230. __TEXT("linkLayerShutdown: Waiting for send %d"), uRetryCount);
  1231. ProcessQueuedSends(pHws);
  1232. Sleep(100);
  1233. }
  1234. if (pHws->hws_uState == HWS_CONNECTED)
  1235. {
  1236. HWSTRACE0(pHws->hws_dwPhysicalId, HWS_TRACE,
  1237. __TEXT("linkLayerShutdown: calling shutdown"));
  1238. if (shutdown(pHws->hws_Socket, 1) == SOCKET_ERROR)
  1239. {
  1240. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  1241. __TEXT("linkLayerShutdown: shutdown() returned %s"),
  1242. SocketErrorText());
  1243. }
  1244. pHws->hws_uState = HWS_CLOSING;
  1245. }
  1246. case HWS_CLOSING:
  1247. break;
  1248. case HWS_CLOSED:
  1249. break;
  1250. default:
  1251. HWSASSERT(FALSE);
  1252. } // switch
  1253. // Deallocate instance objects
  1254. SocketClose(pHws);
  1255. // Deallocate Receive queue
  1256. if (pHws->hws_pRecvQueue)
  1257. {
  1258. while ((pReq = (PREQUEST) QRemove(pHws->hws_pRecvQueue)) != NULL)
  1259. {
  1260. pHws->hws_h245RecvCallback(pHws->hws_dwH245Instance,
  1261. LINK_RECV_ABORT,
  1262. pReq->req_client_data,
  1263. 0);
  1264. MemFree(pReq);
  1265. }
  1266. QFree(pHws->hws_pRecvQueue);
  1267. pHws->hws_pRecvQueue = NULL;
  1268. }
  1269. // Deallocate Send queue
  1270. if (pHws->hws_pSendQueue)
  1271. {
  1272. while ((pReq = (PREQUEST) QRemove(pHws->hws_pSendQueue)) != NULL)
  1273. {
  1274. pHws->hws_h245SendCallback(pHws->hws_dwH245Instance,
  1275. LINK_SEND_ABORT,
  1276. pReq->req_client_data,
  1277. 0);
  1278. MemFree(pReq);
  1279. }
  1280. QFree(pHws->hws_pSendQueue);
  1281. pHws->hws_pSendQueue = NULL;
  1282. }
  1283. gpInstanceTable->Unlock(dwPhysicalId);
  1284. MemFree(pHws);
  1285. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerShutdown: succeeded"));
  1286. return NOERROR;
  1287. } // linkLayerShutdown
  1288. /***************************************************************************
  1289. *
  1290. * NAME
  1291. * linkLayerGetInstance - return instance id corresponding to physical id
  1292. *
  1293. * SYNOPSIS
  1294. * LINKDLL DWORD linkLayerGetInstance(DWORD dwPhysicalId);
  1295. *
  1296. * DESCRIPTION
  1297. * Returns the Instance identifier corresponding to dwPhysId.
  1298. *
  1299. * PARAMETERS
  1300. * dwPhysicalId Physical identifier to search for
  1301. *
  1302. * RETURN VALUE
  1303. //MULTITHREAD
  1304. * INVALID_PHYS_ID (-1)No instance corresponding to dwPhysicalId found
  1305. * n>0 Instance Id corresponding to dwPhysicalId
  1306. *
  1307. ***************************************************************************/
  1308. LINKDLL DWORD linkLayerGetInstance(DWORD dwPhysicalId)
  1309. {
  1310. if (InitializeStatus == NOERROR &&
  1311. dwPhysicalId != INVALID_PHYS_ID &&
  1312. gpInstanceTable->Lock(dwPhysicalId) != NULL)
  1313. {
  1314. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerGetInstance: succeeded"));
  1315. gpInstanceTable->Unlock(dwPhysicalId);
  1316. return dwPhysicalId;
  1317. }
  1318. HWSTRACE0(dwPhysicalId, HWS_ERROR, __TEXT("linkLayerGetInstance: failed"));
  1319. return INVALID_PHYS_ID; // return failure
  1320. } // linkLayerGetInstance()
  1321. /***************************************************************************
  1322. *
  1323. * NAME
  1324. * linkLayerFlushChannel - flush transmit and/or receive channels
  1325. *
  1326. * DESCRIPTION
  1327. * This is a dummy function required only for compatibility with the SRP API.
  1328. *
  1329. * RETURN VALUE
  1330. * 0 Function succeeded.
  1331. * n!=0 Link error code (see LINKAPI.H for definitions.)
  1332. *
  1333. ***************************************************************************/
  1334. LINKDLL HRESULT linkLayerFlushChannel(DWORD dwPhysicalId, DWORD dwDirectionMask)
  1335. {
  1336. if (InitializeStatus != NOERROR)
  1337. return InitializeStatus;
  1338. PHWSINST pHws;
  1339. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1340. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1341. {
  1342. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  1343. __TEXT("linkLayerFlushChannel: dwPhysicalId not found"));
  1344. return LINK_INVALID_INSTANCE;
  1345. }
  1346. switch (dwDirectionMask & (DATALINK_RECEIVE | DATALINK_TRANSMIT))
  1347. {
  1348. case DATALINK_TRANSMIT | DATALINK_RECEIVE:
  1349. // Flush both receive and transmit
  1350. // Caveat: H.245 expects us to flush receive first!
  1351. SocketFlushRecv(pHws);
  1352. // Fall through to next case
  1353. case DATALINK_TRANSMIT:
  1354. // Flush transmit
  1355. // SockFlushSend() just removes the entries from the queue - it doesn't send them.
  1356. // So instead, call ProcessQueuedSends() to actually empty the send queue.
  1357. // SocketFlushSend(pHws);
  1358. ProcessQueuedSends(pHws);
  1359. break;
  1360. case DATALINK_RECEIVE:
  1361. // Flush receive
  1362. SocketFlushRecv(pHws);
  1363. break;
  1364. } // switch
  1365. gpInstanceTable->Unlock(dwPhysicalId);
  1366. HWSTRACE2(dwPhysicalId, HWS_TRACE,
  1367. __TEXT("linkLayerFlushChannel(%d, 0x%X) succeeded"),
  1368. dwPhysicalId, dwDirectionMask);
  1369. return NOERROR;
  1370. } // linkLayerFlushChannel()
  1371. /***************************************************************************
  1372. *
  1373. * NAME
  1374. * linkLayerFlushAll - flush transmit and receive channels
  1375. *
  1376. * DESCRIPTION
  1377. * This is a dummy function required only for compatibility with the SRP API.
  1378. *
  1379. * RETURN VALUE
  1380. * 0 Function succeeded.
  1381. * n!=0 Link error code (see LINKAPI.H for definitions.)
  1382. *
  1383. ***************************************************************************/
  1384. LINKDLL HRESULT linkLayerFlushAll(DWORD dwPhysicalId)
  1385. {
  1386. if (InitializeStatus != NOERROR)
  1387. return InitializeStatus;
  1388. PHWSINST pHws;
  1389. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1390. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1391. {
  1392. HWSTRACE0(dwPhysicalId, HWS_ERROR,
  1393. __TEXT("linkLayerFlushAll: dwPhysicalId not found"));
  1394. return LINK_INVALID_INSTANCE;
  1395. }
  1396. // Flush both receive and transmit
  1397. // Caveat: H.245 expects us to flush receive first!
  1398. SocketFlushRecv(pHws);
  1399. SocketFlushSend(pHws);
  1400. gpInstanceTable->Unlock(dwPhysicalId);
  1401. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerFlushAll succeeded"));
  1402. return NOERROR;
  1403. } // linkLayerFlushAll()
  1404. /*++
  1405. Description:
  1406. Initiates a call to a remote node.
  1407. 1) Create a socket.
  1408. 2) Set the socket up for windows message notification of FD_CONNECT events.
  1409. 3) Attempt a connection
  1410. Arguments:
  1411. pHws - Pointer to context data from connection.
  1412. Return Value:
  1413. SUCCESS - A connection attempt was successfully initiated.
  1414. LINK_FATAL_ERROR - Error occurred while attempting to initiate a connection.
  1415. --*/
  1416. LINKDLL HRESULT linkLayerConnect(DWORD dwPhysicalId, CC_ADDR *pAddr, H245CONNECTCALLBACK callback)
  1417. {
  1418. register PHWSINST pHws;
  1419. CC_ADDR Addr;
  1420. HRESULT hr;
  1421. if (InitializeStatus != NOERROR)
  1422. return InitializeStatus;
  1423. HWSTRACE5(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerConnect: connecting to %d.%d.%d.%d/%d"),
  1424. GetIPAddress(pAddr) & 0xFF,
  1425. (GetIPAddress(pAddr) >> 8) & 0xFF,
  1426. (GetIPAddress(pAddr) >> 16) & 0xFF,
  1427. GetIPAddress(pAddr) >> 24,
  1428. ntohs(GetPort(pAddr)));
  1429. if ((dwPhysicalId == INVALID_PHYS_ID) ||
  1430. (!(pHws = gpInstanceTable->Lock(dwPhysicalId))))
  1431. {
  1432. HWSTRACE0(dwPhysicalId, HWS_ERROR, __TEXT("linkLayerConnect: dwPhysicalId not found"));
  1433. return LINK_INVALID_INSTANCE;
  1434. }
  1435. if (pHws->hws_uState != HWS_START)
  1436. {
  1437. HWSTRACE1(dwPhysicalId, HWS_ERROR, __TEXT("linkLayerConnect: State = %s"),
  1438. SocketStateText(pHws->hws_uState));
  1439. gpInstanceTable->Unlock(dwPhysicalId);
  1440. return LINK_INVALID_STATE;
  1441. }
  1442. pHws->hws_h245ConnectCallback = callback;
  1443. // Create a socket, bind to a local address and initiate a connection.
  1444. if ((hr = SocketOpen(pHws)) != NOERROR)
  1445. {
  1446. HWSTRACE0(dwPhysicalId, HWS_WARNING,
  1447. __TEXT("linkLayerConnect: SocketOpen() failed"));
  1448. pHws->hws_uState = HWS_START;
  1449. gpInstanceTable->Unlock(dwPhysicalId);
  1450. return hr;
  1451. }
  1452. Addr.nAddrType = CC_IP_BINARY;
  1453. Addr.bMulticast = FALSE;
  1454. Addr.Addr.IP_Binary.wPort = 0;
  1455. Addr.Addr.IP_Binary.dwAddr = 0;
  1456. if ((hr = SocketBind(pHws, &Addr)) != NOERROR)
  1457. {
  1458. HWSTRACE0(dwPhysicalId, HWS_WARNING,
  1459. __TEXT("linkLayerConnect: SocketBind() failed"));
  1460. pHws->hws_uState = HWS_START;
  1461. gpInstanceTable->Unlock(dwPhysicalId);
  1462. return hr;
  1463. }
  1464. // Reminder: WinSock requires that we pass a struct sockaddr *
  1465. // to connect; however, the service provider is free to
  1466. // interpret the pointer as an arbitrary chunk of data of size
  1467. // uSockAddrLen.
  1468. pHws->hws_SockAddr.sin_port = GetPort(pAddr);
  1469. pHws->hws_SockAddr.sin_addr.S_un.S_addr = GetIPAddress(pAddr);
  1470. if (connect(pHws->hws_Socket, // s
  1471. (const struct sockaddr *)&pHws->hws_SockAddr, // name
  1472. sizeof(pHws->hws_SockAddr)) == SOCKET_ERROR) // namelen
  1473. {
  1474. int err = WSAGetLastError();
  1475. switch (err)
  1476. {
  1477. case WSAEWOULDBLOCK:
  1478. break;
  1479. default:
  1480. HWSTRACE1(dwPhysicalId, HWS_WARNING,
  1481. __TEXT("linkLayerConnect: WSAConnect() returned %s"),
  1482. SocketErrorText1(err));
  1483. SocketClose(pHws);
  1484. pHws->hws_uState = HWS_START;
  1485. gpInstanceTable->Unlock(dwPhysicalId);
  1486. return MAKE_WINSOCK_ERROR(err);
  1487. } // switch
  1488. } // if
  1489. else
  1490. {
  1491. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("connect() succeeded"));
  1492. SocketConnect(pHws, 0);
  1493. gpInstanceTable->Unlock(dwPhysicalId);
  1494. return NOERROR;
  1495. } // else
  1496. pHws->hws_uState = HWS_CONNECTING;
  1497. HWSTRACE0(dwPhysicalId, HWS_TRACE, __TEXT("linkLayerConnect: succeeded"));
  1498. gpInstanceTable->Unlock(dwPhysicalId);
  1499. return NOERROR;
  1500. } // linkLayerConnect()
  1501. /***************************************************************************
  1502. *
  1503. * NAME
  1504. * linkLayerListen - start listen on connection
  1505. *
  1506. * DESCRIPTION
  1507. * This function creates a socket,
  1508. * binds to a local address, and listens on the created socket.
  1509. * The address being listened to is returned in the structure
  1510. * pointed to by pAddr.
  1511. *
  1512. * PARAMETERS
  1513. * dwPhysicalId Link layer identifier returned by linkLayerGetInstance().
  1514. * pAddr Pointer to address structure (defined in CALLCONT.H.)
  1515. *
  1516. * RETURN VALUE
  1517. * 0 Function succeeded.
  1518. * n!=0 Error code (see LINKAPI.H for definitions.)
  1519. *
  1520. ***************************************************************************/
  1521. //MULTITHREAD => dwPhysicalID was INPUT now it's OUTPUT
  1522. LINKDLL HRESULT linkLayerListen (DWORD *dwPhysicalId, DWORD_PTR dwH245Instance, CC_ADDR *pAddr, H245CONNECTCALLBACK callback)
  1523. {
  1524. HRESULT hr;
  1525. register PHWSINST pHws;
  1526. if (InitializeStatus == LINK_INVALID_STATE)
  1527. Initialize();
  1528. if (InitializeStatus != NOERROR)
  1529. return InitializeStatus;
  1530. if ((*dwPhysicalId == INVALID_PHYS_ID) ||
  1531. (!(pHws = gpInstanceTable->Lock(*dwPhysicalId))))
  1532. {
  1533. if ((hr = linkLayerInit(dwPhysicalId, dwH245Instance, NULL, NULL)) != NOERROR)
  1534. return hr;
  1535. pHws = gpInstanceTable->Lock(*dwPhysicalId);
  1536. HWSASSERT(pHws != NULL);
  1537. }
  1538. else
  1539. {
  1540. HWSASSERT(pHws->hws_dwH245Instance == dwH245Instance);
  1541. }
  1542. if (pHws->hws_uState != HWS_START)
  1543. {
  1544. HWSTRACE1(*dwPhysicalId, HWS_ERROR, __TEXT("linkLayerListen: State = %s"),
  1545. SocketStateText(pHws->hws_uState));
  1546. gpInstanceTable->Unlock(*dwPhysicalId);
  1547. return LINK_INVALID_STATE;
  1548. }
  1549. pHws->hws_h245ConnectCallback = callback;
  1550. if ((hr = SocketOpen(pHws, FALSE)) != NOERROR)
  1551. {
  1552. HWSTRACE0(*dwPhysicalId, HWS_WARNING, __TEXT("linkLayerListen: SocketBind() failed"));
  1553. pHws->hws_uState = HWS_START;
  1554. gpInstanceTable->Unlock(*dwPhysicalId);
  1555. return hr;
  1556. }
  1557. if ((hr = SocketBind(pHws, pAddr)) != NOERROR)
  1558. {
  1559. HWSTRACE0(*dwPhysicalId, HWS_WARNING, __TEXT("linkLayerListen: SocketBind() failed"));
  1560. pHws->hws_uState = HWS_START;
  1561. gpInstanceTable->Unlock(*dwPhysicalId);
  1562. return hr;
  1563. }
  1564. // Listen for incoming connection requests on the socket.
  1565. int nBacklog = SOMAXCONN;
  1566. while (listen(pHws->hws_Socket, nBacklog) == SOCKET_ERROR)
  1567. {
  1568. int err = WSAGetLastError();
  1569. HWSTRACE1(*dwPhysicalId,
  1570. HWS_WARNING,
  1571. __TEXT("linkLayerListen: listen() returned %s"),
  1572. SocketErrorText1(err));
  1573. if (nBacklog == SOMAXCONN)
  1574. nBacklog = 10;
  1575. if (err != WSAENOBUFS || --nBacklog == 0)
  1576. {
  1577. SocketClose(pHws);
  1578. pHws->hws_uState = HWS_START;
  1579. gpInstanceTable->Unlock(*dwPhysicalId);
  1580. return MAKE_WINSOCK_ERROR(err);
  1581. }
  1582. Sleep(0);
  1583. }
  1584. if ((hr = GetLocalAddr(pHws, pAddr)) != NOERROR)
  1585. {
  1586. // getsockname() failed
  1587. HWSTRACE1(pHws->hws_dwPhysicalId, HWS_WARNING,
  1588. __TEXT("linkLayerListen: getsockname() returned %s"),
  1589. SocketErrorText());
  1590. SocketClose(pHws);
  1591. pHws->hws_uState = HWS_START;
  1592. gpInstanceTable->Unlock(*dwPhysicalId);
  1593. return hr;
  1594. }
  1595. HWSTRACE5(*dwPhysicalId, HWS_TRACE, __TEXT("linkLayerListen: listening on %d.%d.%d.%d/%d"),
  1596. GetIPAddress(pAddr) & 0xFF,
  1597. (GetIPAddress(pAddr) >> 8) & 0xFF,
  1598. (GetIPAddress(pAddr) >> 16) & 0xFF,
  1599. GetIPAddress(pAddr) >> 24,
  1600. ntohs(GetPort(pAddr)));
  1601. pHws->hws_uState = HWS_LISTENING;
  1602. HWSTRACE0(*dwPhysicalId, HWS_TRACE, __TEXT("linkLayerListen: succeeded"));
  1603. gpInstanceTable->Unlock(*dwPhysicalId);
  1604. return NOERROR;
  1605. } // linkLayerListen()
  1606. LINKDLL HRESULT
  1607. linkLayerAccept(DWORD dwPhysicalIdListen, DWORD dwPhysicalIdAccept, H245CONNECTCALLBACK callback)
  1608. {
  1609. PHWSINST pHwsListen;
  1610. PHWSINST pHwsAccept;
  1611. HRESULT rc;
  1612. if (InitializeStatus != NOERROR)
  1613. return InitializeStatus;
  1614. HWSTRACE0(dwPhysicalIdAccept, HWS_TRACE, __TEXT("linkLayerAccept"));
  1615. if ((dwPhysicalIdListen == INVALID_PHYS_ID) ||
  1616. (!(pHwsListen = gpInstanceTable->Lock(dwPhysicalIdListen))))
  1617. {
  1618. HWSTRACE0(dwPhysicalIdListen, HWS_ERROR, __TEXT("linkLayerAccept: dwPhysicalIdListen not found"));
  1619. return LINK_INVALID_INSTANCE;
  1620. }
  1621. pHwsAccept = gpInstanceTable->Lock(dwPhysicalIdAccept);
  1622. if (pHwsAccept == NULL)
  1623. {
  1624. HWSTRACE0(dwPhysicalIdAccept, HWS_ERROR, __TEXT("linkLayerAccept: dwPhysicalIdAccept not found"));
  1625. gpInstanceTable->Unlock(dwPhysicalIdListen);
  1626. return LINK_INVALID_INSTANCE;
  1627. }
  1628. HWSASSERT(pHwsListen->hws_uState == HWS_LISTENING);
  1629. HWSASSERT(pHwsAccept == pHwsListen || pHwsAccept->hws_uState == HWS_START);
  1630. pHwsAccept->hws_h245ConnectCallback = callback;
  1631. rc = SocketAccept(pHwsListen, pHwsAccept);
  1632. gpInstanceTable->Unlock(dwPhysicalIdListen);
  1633. gpInstanceTable->Unlock(dwPhysicalIdAccept);
  1634. return rc;
  1635. }
  1636. /***************************************************************************
  1637. *
  1638. * NAME
  1639. * linkLayerReject - reject an incomming connection request
  1640. *
  1641. * DESCRIPTION
  1642. * This function accepts an incomming connection
  1643. * request then immediatly closes the new socket.
  1644. *
  1645. * PARAMETERS
  1646. * dwPhysicalId Link layer identifier of the listening socket
  1647. *
  1648. * RETURN VALUE
  1649. * 0 Function succeeded.
  1650. * n!=0 Error code (see LINKAPI.H for definitions.)
  1651. *
  1652. ***************************************************************************/
  1653. LINKDLL HRESULT
  1654. linkLayerReject(DWORD dwPhysicalIdListen)
  1655. {
  1656. HRESULT hr = NOERROR;
  1657. PHWSINST pHwsListen = NULL;
  1658. SOCKET sockReject = INVALID_SOCKET;
  1659. SOCKADDR_IN sockAddr;
  1660. INT sockAddrLen = sizeof(sockAddr);
  1661. // Lock the table to get the socket handle
  1662. pHwsListen = gpInstanceTable->Lock(dwPhysicalIdListen);
  1663. if(NULL != pHwsListen)
  1664. {
  1665. // Accept incoming conenction then immediately close it
  1666. sockReject = accept(pHwsListen->hws_Socket, (SOCKADDR *)&sockAddr, &sockAddrLen);
  1667. if(INVALID_SOCKET != sockReject)
  1668. {
  1669. closesocket(sockReject);
  1670. }
  1671. else
  1672. {
  1673. hr = MAKE_WINSOCK_ERROR(WSAGetLastError());
  1674. }
  1675. }
  1676. else
  1677. {
  1678. hr = LINK_INVALID_INSTANCE;
  1679. }
  1680. // Unlock the instance table
  1681. gpInstanceTable->Unlock(dwPhysicalIdListen);
  1682. return hr;
  1683. }
  1684. // Here is the corresponding redefinition of the __TEXT macro
  1685. #ifndef UNICODE_TRACE
  1686. #undef __TEXT
  1687. #define __TEXT(x) L##x
  1688. #endif
  1689. #if defined(__cplusplus)
  1690. }
  1691. #endif // (__cplusplus)