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.

496 lines
22 KiB

  1. /****************************************************************************/
  2. // atdint.c
  3. //
  4. // Transport driver - portable internal functions.
  5. //
  6. // Copyright (C) 1997-1999 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <adcg.h>
  9. extern "C" {
  10. #define TRC_FILE "atdint"
  11. #define TRC_GROUP TRC_GROUP_NETWORK
  12. #include <atrcapi.h>
  13. #include <adcgfsm.h>
  14. }
  15. #include "autil.h"
  16. #include "td.h"
  17. #include "xt.h"
  18. #include "cd.h"
  19. #include "nl.h"
  20. #include "wui.h"
  21. /****************************************************************************/
  22. /* TD FSM TABLE */
  23. /* ============ */
  24. /* */
  25. /* EVENTS STATES */
  26. /* 0 TD_EVT_TDINIT 0 TD_ST_NOTINIT */
  27. /* 1 TD_EVT_TDTERM 1 TD_ST_DISCONNECTED */
  28. /* 2 TD_EVT_TDCONNECT_IP 2 TD_ST_WAITFORDNS */
  29. /* 3 TD_EVT_TDCONNECT_DNS 3 TD_ST_WAITFORSKT */
  30. /* 4 TD_EVT_TDDISCONNECT 4 TD_ST_CONNECTED */
  31. /* 5 TD_EVT_WMTIMER 5 TD_ST_WAITFORCLOSE */
  32. /* 6 TD_EVT_OK */
  33. /* 7 TD_EVT_ERROR */
  34. /* 8 TD_EVT_CONNECTWITHENDPOINT */
  35. /* */
  36. /* Stt | 0 1 2 3 4 5 */
  37. /* ==================================== */
  38. /* Evt | */
  39. /* 0 | 1A / / / / / (TD_EVT_TDINIT) */
  40. /* | */
  41. /* 1 | / 0X 0Z 0Z 0Z 0Z (TD_EVT_TDTERM) */
  42. /* | */
  43. /* 2 | / 3B / / / / (TD_EVT_TDCONNECT_IP) */
  44. /* | */
  45. /* 3 | / 2C / / / / (TD_EVT_TDCONNECT_DNS) */
  46. /* | */
  47. /* 4 | / / 1Y 1Y 5D 5- (TD_EVT_DISCONNECT) */
  48. /* | */
  49. /* 5 | 0- 1- 1Y 1Y 4- 1W (TD_EVT_WMTIMER) */
  50. /* | */
  51. /* 6 | 0- 1- 3B 4E 4- 1Y (TD_EVT_OK) */
  52. /* | */
  53. /* 7 | 0- 1- 1Y 1Y 1Y 1W (TD_EVT_ERROR) */
  54. /* */
  55. /* 8 | 0- Conn / / / / (ACT_CONNECTENDPOINT) */
  56. /* */
  57. /* 9 | / / 1W 1W 1W 1- (TD_EVT_DROPLINK) */
  58. /* */
  59. /* */
  60. /* */
  61. /* '/' = illegal event/state combination */
  62. /* '-' = no action */
  63. /* */
  64. /****************************************************************************/
  65. const FSM_ENTRY tdFSM[TD_FSM_INPUTS][TD_FSM_STATES] =
  66. /* TD_EVT_TDINIT */
  67. {{{TD_ST_DISCONNECTED, ACT_A},
  68. {STATE_INVALID, ACT_NO},
  69. {STATE_INVALID, ACT_NO},
  70. {STATE_INVALID, ACT_NO},
  71. {STATE_INVALID, ACT_NO},
  72. {STATE_INVALID, ACT_NO}},
  73. /* TD_EVT_TDTERM */
  74. {{STATE_INVALID, ACT_NO},
  75. {TD_ST_NOTINIT, ACT_X},
  76. {TD_ST_NOTINIT, ACT_Z},
  77. {TD_ST_NOTINIT, ACT_Z},
  78. {TD_ST_NOTINIT, ACT_Z},
  79. {TD_ST_NOTINIT, ACT_Z}},
  80. /* TD_EVT_TDCONNECT_IP */
  81. {{STATE_INVALID, ACT_NO},
  82. {TD_ST_WAITFORSKT, ACT_B},
  83. {STATE_INVALID, ACT_NO},
  84. {STATE_INVALID, ACT_NO},
  85. {STATE_INVALID, ACT_NO},
  86. {STATE_INVALID, ACT_NO}},
  87. /* TD_EVT_TDCONNECT_DNS */
  88. {{STATE_INVALID, ACT_NO},
  89. {TD_ST_WAITFORDNS, ACT_C},
  90. {STATE_INVALID, ACT_NO},
  91. {STATE_INVALID, ACT_NO},
  92. {STATE_INVALID, ACT_NO},
  93. {STATE_INVALID, ACT_NO}},
  94. /* TD_EVT_TDDISCONNECT */
  95. {{STATE_INVALID, ACT_NO},
  96. {TD_ST_DISCONNECTED, ACT_NO},
  97. {TD_ST_DISCONNECTED, ACT_Y},
  98. {TD_ST_DISCONNECTED, ACT_Y},
  99. {TD_ST_WAITFORCLOSE, ACT_D},
  100. {TD_ST_WAITFORCLOSE, ACT_NO}},
  101. /* TD_EVT_WMTIMER */
  102. {{TD_ST_NOTINIT, ACT_NO},
  103. {TD_ST_DISCONNECTED, ACT_NO},
  104. {TD_ST_DISCONNECTED, ACT_Y},
  105. {TD_ST_DISCONNECTED, ACT_Y},
  106. {TD_ST_CONNECTED, ACT_NO},
  107. {TD_ST_DISCONNECTED, ACT_W}},
  108. /* TD_EVT_OK */
  109. {{TD_ST_NOTINIT, ACT_NO},
  110. {TD_ST_DISCONNECTED, ACT_NO},
  111. {TD_ST_WAITFORSKT, ACT_B},
  112. {TD_ST_CONNECTED, ACT_E},
  113. {TD_ST_CONNECTED, ACT_NO},
  114. {TD_ST_DISCONNECTED, ACT_Y}},
  115. /* TD_EVT_ERROR */
  116. {{TD_ST_NOTINIT, ACT_NO},
  117. {TD_ST_DISCONNECTED, ACT_NO},
  118. {TD_ST_DISCONNECTED, ACT_Y},
  119. {TD_ST_DISCONNECTED, ACT_Y},
  120. {TD_ST_DISCONNECTED, ACT_Y},
  121. {TD_ST_DISCONNECTED, ACT_W}},
  122. /* TD_EVT_CONNECTWITHENDPOINT */
  123. {{STATE_INVALID, ACT_NO},
  124. {TD_ST_WAITFORSKT, ACT_CONNECTENDPOINT}, // TDBeginSktConnectWithConnectedEndpoint() will post
  125. {STATE_INVALID, ACT_NO}, // itself a FD_CONNECT message to setups rest of data
  126. {STATE_INVALID, ACT_NO},
  127. {STATE_INVALID, ACT_NO},
  128. {STATE_INVALID, ACT_NO}},
  129. /* TD_EVT_DROPLINK */
  130. {{STATE_INVALID, ACT_NO},
  131. {TD_ST_DISCONNECTED, ACT_NO},
  132. {TD_ST_DISCONNECTED, ACT_W},
  133. {TD_ST_DISCONNECTED, ACT_W},
  134. {TD_ST_DISCONNECTED, ACT_W},
  135. {TD_ST_DISCONNECTED, ACT_NO}},
  136. };
  137. /****************************************************************************/
  138. /* Name: TDConnectFSMProc */
  139. /* */
  140. /* Purpose: The TD connection FSM. */
  141. /* */
  142. /* Params: IN fsmEvent - an external event. */
  143. /* IN eventData - four bytes of event related data. */
  144. /****************************************************************************/
  145. DCVOID DCINTERNAL CTD::TDConnectFSMProc(DCUINT fsmEvent, ULONG_PTR eventData)
  146. {
  147. DCUINT action;
  148. DC_BEGIN_FN("TDConnectFSMProc");
  149. /************************************************************************/
  150. /* Run the FSM. */
  151. /************************************************************************/
  152. EXECUTE_FSM(tdFSM, fsmEvent, _TD.fsmState, action,tdEventText,tdStateText);
  153. TRC_NRM((TB, _T("eventData:%p"), eventData));
  154. /************************************************************************/
  155. /* Now perform the action. */
  156. /************************************************************************/
  157. switch (action)
  158. {
  159. case ACT_A:
  160. {
  161. /****************************************************************/
  162. /* Initialize _TD. Note that any errors in this function are */
  163. /* fatal and are handled by directly calling the UT fatal */
  164. /* error handler. */
  165. /****************************************************************/
  166. TDInit();
  167. }
  168. break;
  169. case ACT_CONNECTENDPOINT:
  170. {
  171. /****************************************************************/
  172. /* Socket connection pre-established */
  173. /****************************************************************/
  174. TDBeginSktConnectWithConnectedEndpoint();
  175. }
  176. break;
  177. case ACT_B:
  178. {
  179. /****************************************************************/
  180. /* Begin the socket connection process. */
  181. /****************************************************************/
  182. TDBeginSktConnect((u_long) eventData);
  183. }
  184. break;
  185. case ACT_C:
  186. {
  187. /****************************************************************/
  188. /* We need to perform a DNS lookup, so resolve the address and */
  189. /* call the state machine again to check the result of the */
  190. /* resolution call. */
  191. /****************************************************************/
  192. TDBeginDNSLookup((PDCACHAR) eventData);
  193. }
  194. break;
  195. case ACT_D:
  196. {
  197. /****************************************************************/
  198. /* Disconnect processing. First of all start the disconnect */
  199. /* timer. Normally the server will respond to our graceful */
  200. /* close attempt prior to this timer popping. However, just in */
  201. /* the case the server decides to take a hike, we have this */
  202. /* timer which ensures that we tidy up. */
  203. /****************************************************************/
  204. TDSetTimer(TD_DISCONNECTTIMEOUT);
  205. /****************************************************************/
  206. /* Set the flag to indicate that there is no more data */
  207. /* available in _TD. */
  208. /****************************************************************/
  209. _TD.dataInTD = FALSE;
  210. /****************************************************************/
  211. /* Decouple to the sender thread and clear the send queue. */
  212. /****************************************************************/
  213. _pCd->CD_DecoupleSyncNotification(CD_SND_COMPONENT, this,
  214. CD_NOTIFICATION_FUNC(CTD,TDClearSendQueue),
  215. 0);
  216. /****************************************************************/
  217. /* Initiate the graceful close by calling shutdown with */
  218. /* SD_SEND specified. This lets the server know that we've */
  219. /* finished sending. If it's feeling up to it, the server will */
  220. /* shortly get back to us with an FD_CLOSE which signifies that */
  221. /* the graceful close has completed. */
  222. /* */
  223. /* However just in case the server misses a beat, we've got a */
  224. /* timer running as well. If it pops before the server gets */
  225. /* back to us, we'll just pull everything down anyway. */
  226. /****************************************************************/
  227. TRC_NRM((TB, _T("Issue shutdown (SD_SEND)")));
  228. if (shutdown(_TD.hSocket, SD_SEND) != 0)
  229. {
  230. TRC_ALT((TB, _T("Shutdown error: %d"), WSAGetLastError()));
  231. }
  232. /****************************************************************/
  233. /* Now hang around waiting for the server to get back to us, */
  234. /* or the timer to pop. */
  235. /****************************************************************/
  236. }
  237. break;
  238. case ACT_E:
  239. {
  240. /****************************************************************/
  241. /* We're now connected - so get rid of the connection timeout */
  242. /* timer. */
  243. /****************************************************************/
  244. TDKillTimer();
  245. /****************************************************************/
  246. /* Set the required options on this socket. We do the */
  247. /* following: */
  248. /* */
  249. /* - set the receive buffer size to TD_WSRCVBUFSIZE */
  250. /* - set the send buffer size to TD_WSSNDBUFSIZE */
  251. /* - disable Keep Alives */
  252. /* */
  253. /* Note that these calls should not be made until the */
  254. /* connection is established. */
  255. /****************************************************************/
  256. #ifndef OS_WINCE
  257. TDSetSockOpt(SOL_SOCKET, SO_RCVBUF, TD_WSRCVBUFSIZE);
  258. TDSetSockOpt(SOL_SOCKET, SO_SNDBUF, TD_WSSNDBUFSIZE);
  259. #endif
  260. TDSetSockOpt(SOL_SOCKET, SO_KEEPALIVE, 0);
  261. _pXt->XT_OnTDConnected();
  262. }
  263. break;
  264. case ACT_W:
  265. {
  266. /****************************************************************/
  267. /* Disconnect has timed out or failed. Close the socket but */
  268. /* don't pass an error indication to the user. */
  269. /****************************************************************/
  270. TRC_NRM((TB, _T("Disconnection timeout / failure")));
  271. TDDisconnect();
  272. _pXt->XT_OnTDDisconnected(NL_DISCONNECT_LOCAL);
  273. }
  274. break;
  275. case ACT_X:
  276. {
  277. /****************************************************************/
  278. /* Termination action - reverse of Action A. Just call TDTerm. */
  279. /****************************************************************/
  280. TDTerm();
  281. }
  282. break;
  283. case ACT_Y:
  284. {
  285. /****************************************************************/
  286. /* Begin tidying up. */
  287. /****************************************************************/
  288. TDDisconnect();
  289. /****************************************************************/
  290. /* Now call the layer above to let it know that we've */
  291. /* disconnected. <eventData> contains the disconnect reason */
  292. /* code which must be non-zero. */
  293. /****************************************************************/
  294. TRC_ASSERT((eventData != 0), (TB, _T("eventData is zero")));
  295. TRC_ASSERT((HIWORD(eventData) == 0),
  296. (TB, _T("disconnect reason code unexpectedly using 32 bits")));
  297. _pXt->XT_OnTDDisconnected((DCUINT)eventData);
  298. }
  299. break;
  300. case ACT_Z:
  301. {
  302. /****************************************************************/
  303. /* Termination action. First of all tidy up. Then call */
  304. /* TDTerm. */
  305. /****************************************************************/
  306. TDDisconnect();
  307. TDTerm();
  308. }
  309. break;
  310. case ACT_NO:
  311. {
  312. TRC_NRM((TB, _T("No action required")));
  313. }
  314. break;
  315. default:
  316. {
  317. TRC_ABORT((TB, _T("Unknown action:%u"), action));
  318. }
  319. }
  320. DC_END_FN();
  321. } /* TDConnectFSMProc */
  322. /****************************************************************************/
  323. /* Name: TDAllocBuf */
  324. /* */
  325. /* Purpose: This function allocates the memory for a send buffer and then */
  326. /* stores a pointer to this memory in the buffer information */
  327. /* structure. */
  328. /* */
  329. /* Params: IN pSndBufInf - a pointer to send buffer info structure. */
  330. /* IN size - the size of the buffer to allocate. */
  331. /****************************************************************************/
  332. DCVOID DCINTERNAL CTD::TDAllocBuf(PTD_SNDBUF_INFO pSndBufInf, DCUINT size)
  333. {
  334. DC_BEGIN_FN("TDAllocBuf");
  335. /************************************************************************/
  336. /* Allocate the memory for the send buffer. */
  337. /************************************************************************/
  338. pSndBufInf->pBuffer = (PDCUINT8) UT_Malloc( _pUt, size);
  339. pSndBufInf->size = size;
  340. /************************************************************************/
  341. /* Check that the memory allocation succeeded. */
  342. /************************************************************************/
  343. if (NULL == pSndBufInf->pBuffer)
  344. {
  345. TRC_ERR((TB, _T("Failed to allocate %u bytes of memory"),
  346. size));
  347. _pUi->UI_FatalError(DC_ERR_OUTOFMEMORY);
  348. }
  349. TRC_NRM((TB, _T("SndBufInf:%p size:%u buffer:%p"),
  350. pSndBufInf,
  351. pSndBufInf->size,
  352. pSndBufInf->pBuffer));
  353. DC_END_FN();
  354. } /* TDAllocBuf */
  355. /****************************************************************************/
  356. /* Name: TDInitBufInfo */
  357. /* */
  358. /* Purpose: This function initializes a buffer. */
  359. /* */
  360. /* Params: IN pSndBufInf - a pointer to send buffer info structure. */
  361. /****************************************************************************/
  362. DCVOID DCINTERNAL CTD::TDInitBufInfo(PTD_SNDBUF_INFO pSndBufInf)
  363. {
  364. DC_BEGIN_FN("TDInitBufInfo");
  365. TRC_ASSERT((NULL != pSndBufInf), (TB, _T("pSndBufInf is NULL")));
  366. /************************************************************************/
  367. /* Initialize the buffer fields. */
  368. /************************************************************************/
  369. pSndBufInf->pNext = 0;
  370. pSndBufInf->inUse = FALSE;
  371. pSndBufInf->pDataLeftToSend = NULL;
  372. pSndBufInf->bytesLeftToSend = 0;
  373. DC_END_FN();
  374. } /* TDInitBufInfo */
  375. /****************************************************************************/
  376. // TDClearSendQueue
  377. //
  378. // Called on sender context (via direct or decoupled call) to clear the
  379. // send queue on disconnect.
  380. /****************************************************************************/
  381. void DCINTERNAL CTD::TDClearSendQueue(ULONG_PTR unused)
  382. {
  383. DCUINT i;
  384. DC_BEGIN_FN("TDClearSendQueue");
  385. DC_IGNORE_PARAMETER(unused);
  386. TRC_NRM((TB, _T("Clearing the send queue - initial buffers:")));
  387. TD_TRACE_SENDINFO(TRC_LEVEL_NRM);
  388. _TD.pFQBuf = NULL;
  389. // Buffers can get taken from the pool, but not added to the
  390. // send queue. This happens when the call goes down between
  391. // the get and the send. Answer? Mark all the buffers in the
  392. // pools as not in use.
  393. for (i = 0; i < TD_SNDBUF_PUBNUM; i++) {
  394. TRC_DBG((TB, _T("Tidying pub buf:%u inUse:%s size:%u"),
  395. i,
  396. _TD.pubSndBufs[i].inUse ? "TRUE" : "FALSE",
  397. _TD.pubSndBufs[i].size));
  398. _TD.pubSndBufs[i].pNext = NULL;
  399. _TD.pubSndBufs[i].inUse = FALSE;
  400. _TD.pubSndBufs[i].bytesLeftToSend = 0;
  401. _TD.pubSndBufs[i].pDataLeftToSend = NULL;
  402. }
  403. for (i = 0; i < TD_SNDBUF_PRINUM; i++) {
  404. TRC_DBG((TB, _T("Tidying pri buf:%u inUse:%s size:%u"),
  405. i,
  406. _TD.priSndBufs[i].inUse ? "TRUE" : "FALSE",
  407. _TD.priSndBufs[i].size));
  408. _TD.priSndBufs[i].pNext = NULL;
  409. _TD.priSndBufs[i].inUse = FALSE;
  410. _TD.priSndBufs[i].bytesLeftToSend = 0;
  411. _TD.priSndBufs[i].pDataLeftToSend = NULL;
  412. }
  413. TRC_NRM((TB, _T("Send queue cleared - final buffers:")));
  414. TD_TRACE_SENDINFO(TRC_LEVEL_NRM);
  415. DC_END_FN();
  416. }
  417. /****************************************************************************/
  418. // TDSendError
  419. //
  420. // Called on receive thread (possibly decoupled) to notify a send error.
  421. /****************************************************************************/
  422. void DCINTERNAL CTD::TDSendError(ULONG_PTR unused)
  423. {
  424. DC_BEGIN_FN("TDSendError");
  425. DC_IGNORE_PARAMETER(unused);
  426. // Call the FSM with an error.
  427. TDConnectFSMProc(TD_EVT_ERROR,
  428. NL_MAKE_DISCONNECT_ERR(NL_ERR_TDONCALLTOSEND));
  429. DC_END_FN();
  430. }