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.

679 lines
17 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. q931obj.cpp
  5. Abstract:
  6. Functionality for accepting the Q931 connections.
  7. Author:
  8. Nikhil Bobde (NikhilB)
  9. Revision History:
  10. --*/
  11. #include "globals.h"
  12. #include "q931obj.h"
  13. #include "line.h"
  14. #include "q931pdu.h"
  15. #include "winbase.h"
  16. #include "ras.h"
  17. class Q931_BUFFER_CACHE
  18. {
  19. private:
  20. enum { RECV_BUFFER_LIST_COUNT_MAX = 0x10 };
  21. CRITICAL_SECTION m_CriticalSection;
  22. LIST_ENTRY m_FreeRecvBufferList;
  23. DWORD m_FreeRecvBufferListCount;
  24. private:
  25. void Lock (void) { EnterCriticalSection (&m_CriticalSection); }
  26. void Unlock (void) { LeaveCriticalSection (&m_CriticalSection); }
  27. public:
  28. Q931_BUFFER_CACHE (void);
  29. ~Q931_BUFFER_CACHE (void);
  30. BOOL AllocRecvBuffer (
  31. OUT RECVBUF ** ReturnRecvBuffer);
  32. void FreeRecvBuffer (
  33. IN RECVBUF * RecvBuffer);
  34. void FreeAll (void);
  35. };
  36. // global data
  37. Q931_LISTENER Q931Listener;
  38. static Q931_BUFFER_CACHE Q931BufferCache;
  39. HRESULT
  40. Q931AcceptStart (void)
  41. {
  42. return Q931Listener.Start();
  43. }
  44. void
  45. Q931AcceptStop (void)
  46. {
  47. H323DBG(( DEBUG_LEVEL_TRACE, "Q931AcceptStop entered." ));
  48. Q931Listener.Stop();
  49. Q931Listener.WaitIo();
  50. H323DBG(( DEBUG_LEVEL_TRACE, "Q931AcceptStop exited." ));
  51. }
  52. void
  53. Q931FreeRecvBuffer (
  54. IN RECVBUF * RecvBuffer)
  55. {
  56. Q931BufferCache.FreeRecvBuffer (RecvBuffer);
  57. }
  58. BOOL
  59. Q931AllocRecvBuffer (
  60. OUT RECVBUF ** ReturnRecvBuffer)
  61. {
  62. return Q931BufferCache.AllocRecvBuffer (ReturnRecvBuffer);
  63. }
  64. // Q931_LISTENER ---------------------------------------------------------
  65. Q931_LISTENER::Q931_LISTENER (void)
  66. {
  67. // No need to check the result of this one since this object is
  68. // not allocated on heap, right when the DLL is loaded
  69. InitializeCriticalSectionAndSpinCount( &m_CriticalSection, 0x80000000 );
  70. m_ListenSocket = INVALID_SOCKET;
  71. InitializeListHead (&m_AcceptPendingList);
  72. H225ASN_Module_Startup();
  73. H4503PP_Module_Startup();
  74. _ASSERTE( H225ASN_Module );
  75. _ASSERTE( H4503PP_Module );
  76. m_StopNotifyEvent = H323CreateEvent (NULL, TRUE, TRUE,
  77. _T( "H323TSP_StopIncomingCallNotify" ) );
  78. if( m_StopNotifyEvent == NULL )
  79. {
  80. H323DBG(( DEBUG_LEVEL_ERROR,
  81. "Q931: failed to create stop notify event -- will be unable to accept Q.931 connections" ));
  82. }
  83. }
  84. Q931_LISTENER::~Q931_LISTENER (void)
  85. {
  86. DeleteCriticalSection (&m_CriticalSection);
  87. _ASSERTE( m_ListenSocket == INVALID_SOCKET );
  88. _ASSERTE( IsListEmpty (&m_AcceptPendingList) );
  89. if (m_StopNotifyEvent)
  90. {
  91. CloseHandle (m_StopNotifyEvent);
  92. m_StopNotifyEvent = NULL;
  93. }
  94. if( H225ASN_Module )
  95. {
  96. H225ASN_Module_Cleanup();
  97. }
  98. if( H4503PP_Module )
  99. {
  100. H4503PP_Module_Cleanup();
  101. }
  102. }
  103. HRESULT Q931_LISTENER::Start (void)
  104. {
  105. HRESULT hr;
  106. Lock();
  107. hr = StartLocked();
  108. if (hr != S_OK)
  109. {
  110. if (m_ListenSocket != INVALID_SOCKET)
  111. {
  112. closesocket (m_ListenSocket);
  113. m_ListenSocket = INVALID_SOCKET;
  114. }
  115. }
  116. Unlock();
  117. return hr;
  118. }
  119. HRESULT Q931_LISTENER::StartLocked (void)
  120. {
  121. INT SocketAddressLength;
  122. if( m_ListenSocket != INVALID_SOCKET )
  123. {
  124. return S_OK;
  125. }
  126. m_ListenSocket = WSASocket(
  127. AF_INET,
  128. SOCK_STREAM,
  129. IPPROTO_TCP,
  130. NULL,
  131. 0,
  132. WSA_FLAG_OVERLAPPED );
  133. if (m_ListenSocket == INVALID_SOCKET)
  134. {
  135. H323DBG(( DEBUG_LEVEL_ERROR, "Q931: failed to create listen socket" ));
  136. DumpError (GetLastError());
  137. return GetLastResult();
  138. }
  139. m_SocketAddress.sin_family = AF_INET;
  140. m_SocketAddress.sin_addr.s_addr = htonl (INADDR_ANY);
  141. m_SocketAddress.sin_port =
  142. htons( (WORD)g_RegistrySettings.dwQ931ListenPort );
  143. if( bind( m_ListenSocket,
  144. (SOCKADDR *)&m_SocketAddress,
  145. sizeof (SOCKADDR_IN) )
  146. == SOCKET_ERROR)
  147. {
  148. H323DBG(( DEBUG_LEVEL_ERROR,
  149. "Q931: failed to bind to requested port (%d), will try to use dynamic port.",
  150. g_RegistrySettings.dwQ931ListenPort));
  151. //ReportTSPEvent( _T("Q931 listen socket failed to bind to port 1720") );
  152. if( g_RegistrySettings.fIsGKEnabled )
  153. {
  154. m_SocketAddress.sin_port = htons (0);
  155. if( bind( m_ListenSocket, (SOCKADDR *)&m_SocketAddress,
  156. sizeof (SOCKADDR_IN) ) == SOCKET_ERROR )
  157. {
  158. H323DBG ((DEBUG_LEVEL_ERROR,"Q931: failed to request dynamic "
  159. "port for Q.931-cannot accept Q.931 connections" ));
  160. return E_FAIL;
  161. }
  162. }
  163. }
  164. SocketAddressLength = sizeof (SOCKADDR_IN);
  165. if( getsockname( m_ListenSocket,
  166. (SOCKADDR *)&m_SocketAddress,
  167. &SocketAddressLength) )
  168. {
  169. H323DBG(( DEBUG_LEVEL_WARNING,
  170. "Q931: failed to query socket address from TCP -- unexpected behavior"));
  171. return E_FAIL;
  172. }
  173. if( listen( m_ListenSocket, Q931_CONN_QUEUE_LEN) == SOCKET_ERROR )
  174. {
  175. H323DBG ((DEBUG_LEVEL_ERROR, "Q931: failed to begin listening on socket:%d",
  176. WSAGetLastError() ));
  177. return E_FAIL;
  178. }
  179. if( !H323BindIoCompletionCallback( (HANDLE)m_ListenSocket,
  180. Q931_LISTENER::IoCompletionCallback, 0) )
  181. {
  182. H323DBG ((DEBUG_LEVEL_ERROR,
  183. "Q931: failed to bind listen socket to i/o completion callback" ));
  184. return E_FAIL;
  185. }
  186. H323DBG(( DEBUG_LEVEL_TRACE,
  187. "Q931: listen socket created, bound, and ready to receive connections" ));
  188. // all looks good
  189. // issue initial accept buffer(s)
  190. AllocIssueAccept();
  191. AllocIssueAccept();
  192. AllocIssueAccept();
  193. AllocIssueAccept();
  194. return S_OK;
  195. }
  196. void
  197. Q931_LISTENER::Stop(void)
  198. {
  199. Lock();
  200. if (m_ListenSocket != INVALID_SOCKET)
  201. {
  202. // this implicitly cancels all outstanding I/O against this socket
  203. closesocket (m_ListenSocket);
  204. m_ListenSocket = INVALID_SOCKET;
  205. }
  206. Unlock();
  207. }
  208. void
  209. Q931_LISTENER::WaitIo(void)
  210. {
  211. WaitForSingleObject (m_StopNotifyEvent, INFINITE);
  212. }
  213. WORD
  214. Q931_LISTENER::GetListenPort(void)
  215. {
  216. SOCKADDR_IN socketAddress;
  217. int SocketAddressLength = sizeof (SOCKADDR_IN);
  218. ZeroMemory( (PVOID)&socketAddress, sizeof(SOCKADDR_IN) );
  219. Lock();
  220. if( getsockname( m_ListenSocket,
  221. (SOCKADDR *)&socketAddress,
  222. &SocketAddressLength) )
  223. {
  224. H323DBG(( DEBUG_LEVEL_WARNING,
  225. "Q931: failed to query socket address from TCP -- unexpected behavior"));
  226. Unlock();
  227. return 0;
  228. }
  229. Unlock();
  230. return ntohs(socketAddress.sin_port);
  231. }
  232. void
  233. Q931_LISTENER::HandleRegistryChange()
  234. {
  235. if( g_pH323Line -> GetState() == H323_LINESTATE_LISTENING )
  236. {
  237. if( g_RegistrySettings.dwQ931ListenPort != GetListenPort() )
  238. {
  239. Q931AcceptStop();
  240. Q931AcceptStart();
  241. }
  242. }
  243. }
  244. HRESULT
  245. Q931_LISTENER::AllocIssueAccept (void)
  246. {
  247. Q931_ACCEPT_OVERLAPPED * AcceptOverlapped;
  248. HRESULT hr;
  249. _ASSERTE( m_ListenSocket != INVALID_SOCKET );
  250. AcceptOverlapped = new Q931_ACCEPT_OVERLAPPED;
  251. if( AcceptOverlapped != NULL )
  252. {
  253. hr = IssueAccept (AcceptOverlapped);
  254. if (hr != S_OK)
  255. {
  256. delete AcceptOverlapped;
  257. }
  258. }
  259. else
  260. {
  261. H323DBG(( DEBUG_LEVEL_ERROR,
  262. "Q931: failed to allocate connection accept buffer" ));
  263. hr = E_OUTOFMEMORY;
  264. }
  265. return hr;
  266. }
  267. HRESULT
  268. Q931_LISTENER::IssueAccept (
  269. IN Q931_ACCEPT_OVERLAPPED * AcceptOverlapped
  270. )
  271. {
  272. HRESULT hr;
  273. _ASSERTE( m_ListenSocket != INVALID_SOCKET );
  274. ZeroMemory (AcceptOverlapped, sizeof (Q931_ACCEPT_OVERLAPPED));
  275. AcceptOverlapped -> ParentObject = this;
  276. AcceptOverlapped -> Socket = WSASocket (
  277. AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
  278. if (AcceptOverlapped -> Socket == INVALID_SOCKET)
  279. {
  280. H323DBG ((DEBUG_LEVEL_ERROR, "Q931: failed to create new accept socket"));
  281. DumpLastError();
  282. return GetLastResult();
  283. }
  284. if (!AcceptEx (m_ListenSocket,
  285. AcceptOverlapped -> Socket,
  286. AcceptOverlapped -> DataBuffer,
  287. 0,
  288. sizeof (SOCKADDR_IN) + 0x10,
  289. sizeof (SOCKADDR_IN) + 0x10,
  290. &AcceptOverlapped -> BytesTransferred,
  291. &AcceptOverlapped -> Overlapped)
  292. && GetLastError() != ERROR_IO_PENDING)
  293. {
  294. hr = GetLastResult();
  295. H323DBG ((DEBUG_LEVEL_ERROR, "Q931: failed to issue accept on new socket"));
  296. DumpLastError();
  297. closesocket (AcceptOverlapped -> Socket);
  298. return hr;
  299. }
  300. if (IsListEmpty (&m_AcceptPendingList))
  301. {
  302. ResetEvent (m_StopNotifyEvent);
  303. }
  304. InsertTailList (&m_AcceptPendingList, &AcceptOverlapped -> ListEntry);
  305. H323DBG ((DEBUG_LEVEL_TRACE,
  306. "Q931: created new accept socket (%08XH), issued accept request.",
  307. (DWORD) AcceptOverlapped -> Socket));
  308. return S_OK;
  309. }
  310. // static
  311. void
  312. Q931_LISTENER::IoCompletionCallback (
  313. IN DWORD dwStatus,
  314. IN DWORD BytesTransferred,
  315. IN OVERLAPPED * Overlapped
  316. )
  317. {
  318. Q931_ACCEPT_OVERLAPPED * AcceptOverlapped;
  319. _ASSERTE( Overlapped );
  320. #if _WIN64
  321. _ASSERTE( (DWORD_PTR) Overlapped != 0xfeeefeeefeeefeee);
  322. _ASSERTE( (DWORD_PTR) Overlapped != 0xbaadf00dbaadf00d);
  323. #else
  324. _ASSERTE( (DWORD) Overlapped != 0xfeeefeee);
  325. _ASSERTE( (DWORD) Overlapped != 0xbaadf00d);
  326. #endif
  327. AcceptOverlapped = CONTAINING_RECORD(Overlapped,
  328. Q931_ACCEPT_OVERLAPPED, Overlapped);
  329. AcceptOverlapped -> BytesTransferred = BytesTransferred;
  330. AcceptOverlapped -> ParentObject -> CompleteAccept( dwStatus, AcceptOverlapped );
  331. }
  332. void
  333. Q931_LISTENER::CompleteAccept(
  334. IN DWORD dwStatus,
  335. IN Q931_ACCEPT_OVERLAPPED * AcceptOverlapped
  336. )
  337. {
  338. SOCKET Socket = INVALID_SOCKET;
  339. SOCKADDR_IN RemoteAddress;
  340. SOCKADDR_IN * RemoteAddressPointer;
  341. INT RemoteAddressLength;
  342. SOCKADDR_IN LocalAddress;
  343. SOCKADDR_IN * LocalAddressPointer;
  344. INT LocalAddressLength;
  345. HRESULT hr;
  346. DWORD dwEnable = 1;
  347. Lock();
  348. _ASSERTE( IsInList (&m_AcceptPendingList, &AcceptOverlapped -> ListEntry) );
  349. RemoveEntryList (&AcceptOverlapped -> ListEntry);
  350. if (IsListEmpty (&m_AcceptPendingList))
  351. {
  352. SetEvent (m_StopNotifyEvent);
  353. }
  354. if (m_ListenSocket != INVALID_SOCKET)
  355. {
  356. if (dwStatus == ERROR_SUCCESS)
  357. {
  358. // extract parameters from accepted socket, copy to local stack frame.
  359. // this is necessary, because we will recycle AcceptOverlapped (with
  360. // a newly allocated socket) and process the new client later.
  361. // this gives a high degree of concurrency.
  362. RemoteAddressPointer = NULL;
  363. LocalAddressPointer = NULL;
  364. RemoteAddressLength = sizeof RemoteAddress;
  365. LocalAddressLength = sizeof LocalAddress;
  366. GetAcceptExSockaddrs (AcceptOverlapped -> DataBuffer,
  367. 0, sizeof (SOCKADDR_IN), sizeof (SOCKADDR_IN),
  368. (SOCKADDR **) &RemoteAddressPointer,
  369. &RemoteAddressLength,
  370. (SOCKADDR **) &LocalAddressPointer,
  371. &LocalAddressLength);
  372. _ASSERTE( RemoteAddressPointer );
  373. _ASSERTE( LocalAddressPointer );
  374. if( (RemoteAddressPointer == NULL) || (LocalAddressPointer == NULL) )
  375. {
  376. return;
  377. }
  378. RemoteAddress = *RemoteAddressPointer;
  379. LocalAddress = *LocalAddressPointer;
  380. Socket = AcceptOverlapped -> Socket;
  381. if( setsockopt( AcceptOverlapped -> Socket,
  382. SOL_SOCKET,
  383. SO_UPDATE_ACCEPT_CONTEXT,
  384. reinterpret_cast <char *> (&m_ListenSocket),
  385. sizeof m_ListenSocket))
  386. {
  387. H323DBG(( DEBUG_LEVEL_WARNING,
  388. "Q931: successfully accepted socket, but SO_UPDATE_ACCEPT_CONTEXT"
  389. "failed -- future operations will fail" ));
  390. // don't fail here
  391. }
  392. if( setsockopt( Socket, IPPROTO_TCP, TCP_NODELAY, (char*)&dwEnable,
  393. sizeof(DWORD) ) == SOCKET_ERROR )
  394. {
  395. H323DBG(( DEBUG_LEVEL_WARNING,
  396. "Couldn't set NODELAY option on outgoing call socket:%d, %p",
  397. WSAGetLastError(), this ));
  398. }
  399. }
  400. else
  401. {
  402. H323DBG ((DEBUG_LEVEL_ERROR, "Q931: failed to accept connection"));
  403. DumpError (dwStatus);
  404. Socket = INVALID_SOCKET;
  405. // we will allocate a new socket in IssueAccept
  406. // if we hit an error accepting on this socket,
  407. // it can't hurt to use a new socket, anyway.
  408. closesocket (AcceptOverlapped -> Socket);
  409. }
  410. // post the accept context for a new receive
  411. hr = IssueAccept (AcceptOverlapped);
  412. if (hr != S_OK)
  413. {
  414. H323DBG(( DEBUG_LEVEL_WARNING, "Q931: failed to issue accept on "
  415. "buffer -- reception of new Q.931 connections may stall" ));
  416. delete AcceptOverlapped;
  417. }
  418. }
  419. else
  420. {
  421. // future accept requests are denied -- module is shutting down.
  422. if( AcceptOverlapped -> Socket != INVALID_SOCKET )
  423. {
  424. closesocket( AcceptOverlapped -> Socket );
  425. AcceptOverlapped -> Socket = INVALID_SOCKET;
  426. }
  427. delete AcceptOverlapped;
  428. }
  429. Unlock();
  430. if (Socket != INVALID_SOCKET)
  431. {
  432. H323DBG(( DEBUG_LEVEL_TRACE, "Q931: accepted connection, remote address %08XH:%04X.",
  433. SOCKADDR_IN_PRINTF (&RemoteAddress)));
  434. // hand the newly accepted connection off to the call processing code.
  435. CallProcessIncomingCall (Socket, &LocalAddress, &RemoteAddress);
  436. }
  437. }
  438. // Q931_BUFFER_CACHE ----------------------------------------------------
  439. Q931_BUFFER_CACHE::Q931_BUFFER_CACHE (void)
  440. {
  441. // No need to check the result of this one since this object is
  442. // not allocated on heap, right when the DLL is loaded
  443. InitializeCriticalSectionAndSpinCount( &m_CriticalSection, 0x80000000 );
  444. InitializeListHead (&m_FreeRecvBufferList);
  445. m_FreeRecvBufferListCount = 0;
  446. }
  447. Q931_BUFFER_CACHE::~Q931_BUFFER_CACHE (void)
  448. {
  449. Q931BufferCache.FreeAll();
  450. DeleteCriticalSection( &m_CriticalSection );
  451. }
  452. BOOL Q931_BUFFER_CACHE::AllocRecvBuffer (
  453. OUT RECVBUF ** ReturnRecvBuffer
  454. )
  455. {
  456. LIST_ENTRY * ListEntry;
  457. RECVBUF * RecvBuffer;
  458. Lock();
  459. if (m_FreeRecvBufferListCount > 0)
  460. {
  461. m_FreeRecvBufferListCount--;
  462. _ASSERTE( IsListEmpty (&m_FreeRecvBufferList) == FALSE );
  463. ListEntry = RemoveHeadList (&m_FreeRecvBufferList);
  464. RecvBuffer = CONTAINING_RECORD (ListEntry, RECVBUF, ListEntry);
  465. }
  466. else
  467. {
  468. // perform global heap allocation after unlocking (better concurrency)
  469. RecvBuffer = NULL;
  470. }
  471. Unlock();
  472. if( RecvBuffer == NULL )
  473. {
  474. RecvBuffer = new RECVBUF;
  475. }
  476. *ReturnRecvBuffer = RecvBuffer;
  477. return !!RecvBuffer;
  478. }
  479. void
  480. Q931_BUFFER_CACHE::FreeRecvBuffer (
  481. IN RECVBUF * RecvBuffer
  482. )
  483. {
  484. Lock();
  485. _ASSERTE( !IsInList (&m_FreeRecvBufferList, &RecvBuffer -> ListEntry));
  486. if (m_FreeRecvBufferListCount < RECV_BUFFER_LIST_COUNT_MAX)
  487. {
  488. InsertHeadList (&m_FreeRecvBufferList, &RecvBuffer -> ListEntry);
  489. m_FreeRecvBufferListCount++;
  490. RecvBuffer = NULL;
  491. }
  492. Unlock();
  493. if( RecvBuffer )
  494. {
  495. delete RecvBuffer;
  496. }
  497. }
  498. void
  499. Q931_BUFFER_CACHE::FreeAll (void)
  500. {
  501. LIST_ENTRY * ListEntry;
  502. RECVBUF * RecvBuffer;
  503. Lock();
  504. while( IsListEmpty(&m_FreeRecvBufferList) == FALSE )
  505. {
  506. _ASSERTE( m_FreeRecvBufferListCount > 0 );
  507. m_FreeRecvBufferListCount--;
  508. ListEntry = RemoveHeadList (&m_FreeRecvBufferList);
  509. RecvBuffer = CONTAINING_RECORD (ListEntry, RECVBUF, ListEntry);
  510. delete RecvBuffer;
  511. }
  512. _ASSERTE( m_FreeRecvBufferListCount == 0 );
  513. Unlock();
  514. }