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.

474 lines
12 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1994 **/
  4. /**********************************************************************/
  5. /*
  6. connect.cxx
  7. This module contains the connection accept routine called by the connection
  8. thread.
  9. FILE HISTORY:
  10. Johnl 08-Aug-1994 Lifted from FTP server
  11. */
  12. #include "w3p.hxx"
  13. //
  14. // Private prototypes.
  15. //
  16. BOOL
  17. CreateClient(
  18. IN PCLIENT_CONN_PARAMS ClientParam
  19. );
  20. BOOL
  21. SendError(
  22. SOCKET socket,
  23. DWORD ids
  24. );
  25. //
  26. // Private functions.
  27. //
  28. /*******************************************************************
  29. NAME: W3OnConnect
  30. SYNOPSIS: Handles the incoming connection indication from the
  31. connection thread
  32. ENTRY: sNew - New client socket
  33. HISTORY:
  34. KeithMo 09-Mar-1993 Created.
  35. Johnl 02-Aug-1994 Reworked from FTP server
  36. ********************************************************************/
  37. VOID W3OnConnect( SOCKET sNew,
  38. SOCKADDR_IN * psockaddr, //Should be SOCKADDR *
  39. PVOID pEndpointContext,
  40. PVOID pAtqEndpointObject )
  41. {
  42. PIIS_ENDPOINT pEndpoint = (PIIS_ENDPOINT)pEndpointContext;
  43. INT cbAddr = sizeof( sockaddr );
  44. CLIENT_CONN_PARAMS clientParams;
  45. SOCKADDR sockaddr;
  46. if ( !((W3_IIS_SERVICE*)g_pInetSvc)->GetReferenceCount() )
  47. {
  48. return;
  49. }
  50. W3_IIS_SERVICE::ReferenceW3Service( g_pInetSvc );
  51. DBG_ASSERT( sNew != INVALID_SOCKET );
  52. g_pW3Stats->IncrConnectionAttempts();
  53. IF_DEBUG( SOCKETS )
  54. {
  55. DBGPRINTF(( DBG_CONTEXT,
  56. "connect received from %s, socket = %d\n",
  57. inet_ntoa( psockaddr->sin_addr ),
  58. sNew ));
  59. }
  60. if ( getsockname( sNew,
  61. &sockaddr,
  62. &cbAddr ) != 0 )
  63. {
  64. //SendError( sNew, IDS_HTRESP_DENIED );
  65. goto error_exit;
  66. }
  67. //
  68. // We've got a new connection. Add this to the work list
  69. //
  70. clientParams.sClient = sNew;
  71. clientParams.pEndpointObject = pAtqEndpointObject;
  72. clientParams.pAtqContext = NULL;
  73. clientParams.pAddrLocal = &sockaddr;
  74. clientParams.pAddrRemote = (PSOCKADDR)psockaddr;
  75. clientParams.pvInitialBuff = NULL;
  76. clientParams.cbInitialBuff = 0;
  77. clientParams.pEndpoint = (PIIS_ENDPOINT)pEndpointContext;
  78. if ( CreateClient( &clientParams ) )
  79. {
  80. W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
  81. return;
  82. }
  83. error_exit:
  84. W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
  85. CloseSocket( sNew );
  86. } // W3OnConnect
  87. VOID
  88. W3OnConnectEx(
  89. VOID * patqContext,
  90. DWORD cbWritten,
  91. DWORD err,
  92. OVERLAPPED * lpo
  93. )
  94. {
  95. BOOL fAllowConnection = FALSE;
  96. PVOID pvBuff;
  97. SOCKADDR * psockaddrLocal;
  98. SOCKADDR * psockaddrRemote;
  99. SOCKET sNew;
  100. PIIS_ENDPOINT pEndpoint;
  101. PW3_SERVER_INSTANCE pInstance;
  102. CLIENT_CONN_PARAMS clientParams;
  103. if ( err || !lpo )
  104. {
  105. DBGPRINTF(( DBG_CONTEXT,
  106. "[W3OnConnectEx] Completion failed with error %d, Atq context %lx\n",
  107. err,
  108. patqContext ));
  109. AtqCloseSocket( (PATQ_CONTEXT) patqContext, FALSE );
  110. AtqFreeContext( (PATQ_CONTEXT) patqContext, TRUE );
  111. return;
  112. }
  113. if ( !((W3_IIS_SERVICE*)g_pInetSvc)->GetReferenceCount() )
  114. {
  115. return;
  116. }
  117. W3_IIS_SERVICE::ReferenceW3Service( g_pInetSvc );
  118. g_pW3Stats->IncrConnectionAttempts();
  119. IF_DEBUG( SOCKETS )
  120. {
  121. DBGPRINTF(( DBG_CONTEXT,
  122. "[W3OnConnectEx] connection received\n" ));
  123. }
  124. //
  125. // Get AcceptEx parameters
  126. //
  127. AtqGetAcceptExAddrs( (PATQ_CONTEXT) patqContext,
  128. &sNew,
  129. &pvBuff,
  130. (PVOID*)&pEndpoint,
  131. &psockaddrLocal,
  132. &psockaddrRemote );
  133. IF_DEBUG( CONNECTION )
  134. {
  135. DBGPRINTF(( DBG_CONTEXT,
  136. "[W3OnConnectEx] New connection, AtqCont = %lx, buf = %lx, endp %x written = %d\n",
  137. patqContext,
  138. pvBuff,
  139. pEndpoint,
  140. cbWritten ));
  141. }
  142. //
  143. // Set the timeout for future IOs on this context
  144. //
  145. AtqContextSetInfo( (PATQ_CONTEXT) patqContext,
  146. ATQ_INFO_TIMEOUT,
  147. W3_DEF_CONNECTION_TIMEOUT );
  148. //
  149. // We've got a new connection. Add this to the work list
  150. //
  151. clientParams.sClient = sNew;
  152. clientParams.pEndpointObject = NULL;
  153. clientParams.pAtqContext = (PATQ_CONTEXT)patqContext;
  154. clientParams.pAddrLocal = psockaddrLocal;
  155. clientParams.pAddrRemote = psockaddrRemote;
  156. clientParams.pvInitialBuff = pvBuff;
  157. clientParams.cbInitialBuff = cbWritten;
  158. clientParams.pEndpoint = pEndpoint;
  159. if ( CreateClient( &clientParams ) )
  160. {
  161. W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
  162. return;
  163. }
  164. //
  165. // This will also close the socket
  166. //
  167. DBG_REQUIRE( AtqCloseSocket( (PATQ_CONTEXT) patqContext, FALSE ));
  168. AtqFreeContext( (PATQ_CONTEXT) patqContext, TRUE );
  169. W3_IIS_SERVICE::DereferenceW3Service( g_pInetSvc );
  170. return;
  171. } // W3OnConnectEx
  172. /*******************************************************************
  173. NAME: CreateClient
  174. SYNOPSIS: Creates a new connection object that manages the
  175. client requests
  176. ENTRY: sNew - New client socket
  177. HISTORY:
  178. KeithMo 09-Mar-1993 Created.
  179. Johnl 02-Aug-1994 Reworked from FTP server
  180. ********************************************************************/
  181. BOOL
  182. CreateClient(
  183. IN PCLIENT_CONN_PARAMS ClientParam
  184. )
  185. {
  186. APIERR err = NO_ERROR;
  187. CLIENT_CONN * pConn = NULL;
  188. BOOL fGranted;
  189. PATQ_CONTEXT patqContext = ClientParam->pAtqContext;
  190. pConn = CLIENT_CONN::Alloc( ClientParam );
  191. if( pConn == NULL ||
  192. !pConn->IsValid() )
  193. {
  194. err = pConn ? GetLastError() : ERROR_NOT_ENOUGH_MEMORY;
  195. if ( patqContext )
  196. {
  197. DBG_REQUIRE( AtqCloseSocket( patqContext, TRUE ));
  198. }
  199. }
  200. else
  201. {
  202. //
  203. // We only have a context at this point if we're using AcceptEx
  204. //
  205. if ( patqContext )
  206. {
  207. //
  208. // Associate the Client connection object with this socket handle
  209. // for future completions
  210. //
  211. AtqContextSetInfo( patqContext,
  212. ATQ_INFO_COMPLETION_CONTEXT,
  213. (ULONG_PTR) pConn );
  214. IF_DEBUG( CONNECTION )
  215. {
  216. DBGPRINTF(( DBG_CONTEXT,
  217. "[CreateClient] Setting Atq context %lx context to Conn object %lx\n",
  218. patqContext,
  219. pConn ));
  220. }
  221. }
  222. //
  223. // Kickstart the process. This will do an async read to get the
  224. // client's header or it will start processing the receive buffer
  225. // if AcceptEx is being used.
  226. //
  227. ReferenceConn( pConn );
  228. DBG_REQUIRE( pConn->DoWork( 0,
  229. NO_ERROR,
  230. NULL ));
  231. DereferenceConn( pConn );
  232. return TRUE;
  233. }
  234. const CHAR * apszSubStrings[1];
  235. DBG_ASSERT( ClientParam->pAddrRemote->sa_family == AF_INET );
  236. apszSubStrings[0] = inet_ntoa( ((SOCKADDR_IN *)ClientParam->pAddrRemote)->sin_addr );
  237. g_pInetSvc->LogEvent( W3_EVENT_CANNOT_CREATE_CLIENT_CONN,
  238. 1,
  239. apszSubStrings,
  240. err );
  241. DBGPRINTF(( DBG_CONTEXT,
  242. "cannot create client object, error %lu\n",
  243. err ));
  244. if ( pConn )
  245. {
  246. CLIENT_CONN::Free( pConn );
  247. }
  248. return FALSE;
  249. } // CreateClient
  250. #if 0
  251. BOOL
  252. SendError(
  253. SOCKET socket,
  254. DWORD ids
  255. )
  256. {
  257. STR strResponse;
  258. if ( !strResponse.Resize( 512 ) ||
  259. !HTTP_REQ_BASE::BuildExtendedStatus( &strResponse,
  260. HT_FORBIDDEN,
  261. NO_ERROR,
  262. ids ))
  263. {
  264. DBGPRINTF((DBG_CONTEXT,
  265. "[SendError] Failed to build status (error %d)\n",
  266. GetLastError()));
  267. return FALSE;
  268. }
  269. //
  270. // Do a synchronous send
  271. //
  272. send( socket,
  273. strResponse.QueryStr(),
  274. strResponse.QueryCB(),
  275. 0 );
  276. return TRUE ;
  277. } // SendError
  278. #endif
  279. /*******************************************************************
  280. NAME: CloseSocket
  281. SYNOPSIS: Closes the specified socket. This is just a thin
  282. wrapper around the "real" closesocket() API.
  283. ENTRY: sock - The socket to close.
  284. RETURNS: SOCKERR - 0 if successful, !0 if not.
  285. HISTORY:
  286. KeithMo 26-Apr-1993 Created.
  287. ********************************************************************/
  288. SOCKERR CloseSocket( SOCKET sock )
  289. {
  290. SOCKERR serr = 0;
  291. //
  292. // Close the socket.
  293. //
  294. #if 0
  295. shutdown( sock, 1 ); // Davidtr sez not needed
  296. #endif
  297. if( closesocket( sock ) != 0 )
  298. {
  299. serr = WSAGetLastError();
  300. }
  301. IF_DEBUG( SOCKETS )
  302. {
  303. if( serr == 0 )
  304. {
  305. DBGPRINTF(( DBG_CONTEXT,
  306. "closed socket %d\n",
  307. sock ));
  308. }
  309. else
  310. {
  311. DBGPRINTF(( DBG_CONTEXT,
  312. "cannot close socket %d, error %d\n",
  313. sock,
  314. serr ));
  315. }
  316. }
  317. return serr;
  318. } // CloseSocket
  319. #ifdef DEBUG
  320. /*******************************************************************
  321. NAME: DBG_CHECK_UnbalancedThreadToken
  322. SYNOPSIS: Check for unbalanced Thread Token, this function will
  323. try to make a open thread token call, it should fail, otherwise,
  324. somebody forgets to release the thread token.
  325. ENTRY:
  326. RETURNS: NONE
  327. HISTORY:
  328. LeiJin 9/4/1997 Created.
  329. ********************************************************************/
  330. VOID DBG_CHECK_UnbalancedThreadToken(
  331. IN const char * pszFilePath,
  332. IN int nLineNum
  333. )
  334. {
  335. HANDLE hToken = (HANDLE)0;
  336. BOOL fRet = FALSE;
  337. fRet = OpenThreadToken(GetCurrentThread(),
  338. TOKEN_QUERY, // the very minimum operation on a thread token
  339. FALSE, // FALSE, the access check is performed using the
  340. // security context for the calling thread.
  341. &hToken);
  342. if (fRet == TRUE)
  343. {
  344. DBGPRINTF((DBG_CONTEXT, "File %s, Line %d, OpenThreadToken() succeeded, found a token.\n",
  345. pszFilePath,
  346. nLineNum));
  347. DBG_ASSERT(FALSE);
  348. CloseHandle(hToken);
  349. }
  350. else
  351. {
  352. DWORD err = GetLastError();
  353. if (err != ERROR_NO_TOKEN)
  354. {
  355. DBGPRINTF((DBG_CONTEXT, "File %s, Line %d, OpenThreadToken() failed, err = %lu.\n",
  356. pszFilePath,
  357. nLineNum));
  358. }
  359. }
  360. }
  361. #endif //debug