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.

348 lines
8.1 KiB

  1. /*************************************************************************
  2. *
  3. * watchdog.c
  4. *
  5. * IPX Transport Driver - Watch Dog Rouines
  6. *
  7. * Copyright 1998, Microsoft
  8. *
  9. *************************************************************************/
  10. #include <ntddk.h>
  11. #include <tdi.h>
  12. /*
  13. * The following defines are necessary since they are referenced in
  14. * afd.h but defined in sdk/inc/winsock2.h, which we can't include here.
  15. */
  16. #define SG_UNCONSTRAINED_GROUP 0x01
  17. #define SG_CONSTRAINED_GROUP 0x02
  18. #include <afd.h>
  19. #include <isnkrnl.h>
  20. #include <ndis.h>
  21. #include <wsnwlink.h>
  22. #include <winstaw.h>
  23. #define _DEFCHARINFO_
  24. #include <icadd.h>
  25. #include <ctxdd.h>
  26. #include <icaipx.h>
  27. //#include <cxstatus.h>
  28. #include <sdapi.h>
  29. #include <td.h>
  30. #include "tdtdi.h"
  31. #include "tdipx.h"
  32. /*=============================================================================
  33. == External Functions Defined
  34. =============================================================================*/
  35. NTSTATUS InitializeWatchDog( PTD );
  36. VOID WatchDogTimer( PTD, PVOID );
  37. /*=============================================================================
  38. == Internel Functions Defined
  39. =============================================================================*/
  40. VOID _GetTimeoutValue( PTD, ULONG, PULONG );
  41. /*=============================================================================
  42. == External Functions used
  43. =============================================================================*/
  44. NTSTATUS _DoTdiAction( PFILE_OBJECT, ULONG, PCHAR, ULONG );
  45. NTSTATUS
  46. _TdiSendDatagram(
  47. IN PTD pTd,
  48. IN PIRP Irp OPTIONAL,
  49. IN PFILE_OBJECT FileObject,
  50. IN PDEVICE_OBJECT DeviceObject,
  51. IN PTRANSPORT_ADDRESS pRemoteAddress,
  52. IN ULONG RemoteAddressLength,
  53. IN PVOID pBuffer,
  54. IN ULONG BufferLength
  55. );
  56. /*******************************************************************************
  57. *
  58. * InitializeWatchDog
  59. *
  60. * Initialize watch dog
  61. *
  62. * ENTRY:
  63. * pTd (input)
  64. * Pointer to td data structure
  65. *
  66. * EXIT:
  67. * STATUS_SUCCESS - no error, non-error match found
  68. *
  69. ******************************************************************************/
  70. NTSTATUS
  71. InitializeWatchDog( PTD pTd )
  72. {
  73. ULONG Timeout;
  74. NTSTATUS Status;
  75. PTDIPX pTdIpx;
  76. TRACE(( pTd->pContext, TC_TD, TT_API1, "TDIPX: InitializeWatchDog\n" ));
  77. /*
  78. * Get pointer to IPX structure
  79. */
  80. pTdIpx = (PTDIPX) pTd->pPrivate;
  81. /*
  82. * If we really want a timer.
  83. */
  84. if ( !pTdIpx->AliveTime )
  85. return( STATUS_SUCCESS );
  86. /*
  87. * Create watch dog
  88. */
  89. ASSERT( pTdIpx->pAliveTimer == NULL );
  90. Status = IcaTimerCreate( pTd->pContext, &pTdIpx->pAliveTimer );
  91. if ( !NT_SUCCESS(Status) )
  92. goto badtimer;
  93. /*
  94. * Arm timer
  95. */
  96. _GetTimeoutValue( pTd, pTdIpx->AliveTime, &Timeout );
  97. IcaTimerStart( pTdIpx->pAliveTimer,
  98. WatchDogTimer,
  99. NULL,
  100. Timeout,
  101. ICALOCK_DRIVER );
  102. badtimer:
  103. TRACE(( pTd->pContext, TC_TD, TT_API1, "TDIPX: InitializeWatchDog %u, Status=0x%x\n", Timeout, Status ));
  104. return( Status );
  105. }
  106. /*******************************************************************************
  107. *
  108. * _GetTimeoutValue
  109. *
  110. * algorithm to calculate the poll timeout value
  111. *
  112. *
  113. * ENTRY:
  114. * pTd (input)
  115. * pointer to TD data structure
  116. * PollTime (input)
  117. * time gap between two pollings (msec)
  118. * pTimeOut (output)
  119. * timeout value for next poll (msec)
  120. *
  121. ******************************************************************************/
  122. VOID
  123. _GetTimeoutValue( PTD pTd, ULONG PollTime, PULONG pTimeOut )
  124. {
  125. LARGE_INTEGER CurrentTime;
  126. LARGE_INTEGER Ticks;
  127. ULONG Time;
  128. ULONG Remain;
  129. KeQuerySystemTime( &CurrentTime );
  130. /* The currentTime is in 100nsec units and need convert to msec units. */
  131. Ticks = RtlExtendedLargeIntegerDivide( CurrentTime, 10000, &Remain );
  132. RtlExtendedLargeIntegerDivide( Ticks, PollTime, &Remain );
  133. *pTimeOut = PollTime - Remain;
  134. TRACE(( pTd->pContext, TC_TD, TT_API3, "TDIPX: _GetTimeoutValue %u -> %u\n",
  135. PollTime, *pTimeOut));
  136. }
  137. /*******************************************************************************
  138. *
  139. * WatchDogTimer
  140. *
  141. *
  142. * ENTRY:
  143. * pTd (input)
  144. * pointer to TD data structure
  145. * pParam (input)
  146. * not used
  147. *
  148. * EXIT:
  149. * nothing
  150. *
  151. ******************************************************************************/
  152. VOID
  153. WatchDogTimer( PTD pTd, PVOID pParam )
  154. {
  155. ICA_CHANNEL_COMMAND Command;
  156. CHAR ptype;
  157. ULONG Timeout;
  158. BYTE Buffer[1];
  159. NTSTATUS Status;
  160. PTDIPX pTdIpx;
  161. PTDTDI pTdTdi;
  162. PTD_ENDPOINT pEndpoint;
  163. /*
  164. * Get the connection endpoint for the remote system.
  165. * If there is none, then the endpoint must have been closed
  166. * so there is nothing to do.
  167. */
  168. pTdTdi = (PTDTDI)pTd->pAfd;
  169. if ( (pEndpoint = pTdTdi->pConnectionEndpoint) == NULL )
  170. return;
  171. ASSERT( pEndpoint->EndpointType == TdiConnectionDatagram );
  172. /*
  173. * Get pointer to IPX structure
  174. */
  175. pTdIpx = (PTDIPX) pTd->pPrivate;
  176. ASSERT( pTdIpx );
  177. TRACE(( pTd->pContext, TC_TD, TT_API4, "TDIPX: WatchDogTimer\n" ));
  178. /*
  179. * Get time for next watchdog event
  180. */
  181. _GetTimeoutValue( pTd, pTdIpx->AliveTime, &Timeout );
  182. /*
  183. * Check if client has sent data recently
  184. */
  185. if ( pTdIpx->fClientAlive )
  186. goto clientok;
  187. /*
  188. * Check the poll count
  189. */
  190. if ( pTdIpx->AlivePoll ) {
  191. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TDIPX: no response for %u pings\n",
  192. pTdIpx->AlivePoll ));
  193. /*
  194. * Check timeout retry count
  195. */
  196. if ( pTdIpx->AlivePoll > 6 ) {
  197. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TDIPX: client declared dead\n" ));
  198. /*
  199. * Report broken connection
  200. */
  201. Command.Header.Command = ICA_COMMAND_BROKEN_CONNECTION;
  202. Command.BrokenConnection.Reason = Broken_Unexpected;
  203. (void) IcaChannelInput( pTd->pContext,
  204. Channel_Command,
  205. 0,
  206. NULL,
  207. (PCHAR) &Command,
  208. sizeof(Command) );
  209. /*
  210. * Do not re-arm timer
  211. */
  212. return;
  213. }
  214. /*
  215. * Make timeout 10 seconds
  216. */
  217. Timeout = 10 * 1000;
  218. }
  219. /*
  220. * Check for valid file object
  221. */
  222. if ( pTd->pFileObject == NULL )
  223. goto badopen;
  224. ObReferenceObject(pTd->pFileObject); //Fix 416142
  225. /*
  226. * Set up the default packet send type to be control
  227. */
  228. ptype = IPX_TYPE_CONTROL;
  229. Status = _DoTdiAction( pTd->pFileObject, MIPX_SETSENDPTYPE, &ptype, 1 );
  230. ASSERT( Status == STATUS_SUCCESS );
  231. if ( !NT_SUCCESS( Status ) )
  232. goto badtype;
  233. /*
  234. * Write ping to network
  235. */
  236. Buffer[0] = IPX_CTRL_PACKET_PING;
  237. Status = _TdiSendDatagram(
  238. pTd,
  239. NULL, // Irp
  240. pTd->pFileObject,
  241. pTd->pDeviceObject,
  242. pEndpoint->SendInfo.RemoteAddress,
  243. pEndpoint->SendInfo.RemoteAddressLength,
  244. Buffer,
  245. 1
  246. );
  247. ASSERT( Status == STATUS_SUCCESS || Status == STATUS_CTX_CLOSE_PENDING );
  248. TRACEBUF(( pTd->pContext, TC_TD, TT_ORAW, Buffer, 1 ));
  249. /*
  250. * Reset address endpoint to send data packets
  251. */
  252. ptype = IPX_TYPE_DATA;
  253. Status = _DoTdiAction( pTd->pFileObject, MIPX_SETSENDPTYPE, &ptype, 1 );
  254. ASSERT( Status == STATUS_SUCCESS );
  255. /*
  256. * Dereference the TDI file object and close the handle
  257. */
  258. ObDereferenceObject(pTd->pFileObject); //Fix 416142
  259. badtype:
  260. /*
  261. * Increment counter
  262. */
  263. pTdIpx->AlivePoll++;
  264. /*
  265. * Increment number of byte written
  266. */
  267. pTd->pStatus->Output.Bytes++;
  268. /*
  269. * Reset alive bit
  270. */
  271. clientok:
  272. pTdIpx->fClientAlive = FALSE;
  273. /*
  274. * Re-arm timer
  275. */
  276. badopen:
  277. IcaTimerStart( pTdIpx->pAliveTimer,
  278. WatchDogTimer,
  279. NULL,
  280. Timeout,
  281. ICALOCK_DRIVER );
  282. }