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.

580 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. socket.h
  5. Abstract:
  6. This module contains declarations for socket-management.
  7. The routines declared here operate asynchronously on sockets
  8. associated with an I/O completion port. They are also integrated
  9. with the component-reference object, which may optionally be used
  10. by callers to control the number of outstanding entries into a component's
  11. address-space.
  12. This module contains declarations for maintaining reference-count
  13. on a component. It provides an asynchronous thread-safe means of
  14. handling cleanup in a module.
  15. The mechanism defined uses a locked reference count and cleanup-routine
  16. to manage the lifetime of the component. When the reference-count
  17. is dropped to zero, the associated cleanup-routine is invoked.
  18. Author:
  19. Abolade Gbadegesin (aboladeg) 2-Mar-1998
  20. Revision History:
  21. Abolade Gbadegesin (aboladeg) 23-May-1999
  22. Added support for stream sockets.
  23. --*/
  24. #pragma once
  25. typedef VOID (*PCOMPONENT_CLEANUP_ROUTINE)(VOID);
  26. //
  27. // Structure: COMPONENT_REFERENCE
  28. //
  29. // This structure must reside in memory for the lifetime of the component
  30. // to which it refers. It is used to synchronize the component's execution.
  31. //
  32. typedef struct _COMPONENT_REFERENCE
  33. {
  34. CRITICAL_SECTION Lock;
  35. ULONG ReferenceCount;
  36. BOOLEAN Deleted;
  37. PCOMPONENT_CLEANUP_ROUTINE CleanupRoutine;
  38. #if COMPREF_TRACKING
  39. struct _COMPREF_RECORD* RecordArray;
  40. ULONG RecordIndex;
  41. #endif
  42. } COMPONENT_REFERENCE, *PCOMPONENT_REFERENCE;
  43. #if COMPREF_TRACKING
  44. #define COMPREF_RECORD_COUNT (1024)
  45. typedef struct _COMPREF_RECORD
  46. {
  47. PCHAR File;
  48. USHORT Line;
  49. UCHAR ReferenceCount;
  50. enum
  51. {
  52. ComprefAcquireRecord,
  53. ComprefReleaseRecord
  54. } Type;
  55. } COMPREF_RECORD, *PCOMPREF_RECORD;
  56. #endif
  57. //
  58. // FUNCTION DECLARATIONS
  59. //
  60. __inline
  61. BOOLEAN
  62. AcquireComponentReference(
  63. PCOMPONENT_REFERENCE ComponentReference
  64. );
  65. VOID
  66. __inline
  67. DeleteComponentReference(
  68. PCOMPONENT_REFERENCE ComponentReference
  69. );
  70. ULONG
  71. __inline
  72. InitializeComponentReference(
  73. PCOMPONENT_REFERENCE ComponentReference,
  74. PCOMPONENT_CLEANUP_ROUTINE CleanupRoutine
  75. );
  76. #if COMPREF_TRACKING
  77. __inline
  78. BOOLEAN
  79. RecordComponentReference(
  80. PCOMPONENT_REFERENCE ComponentReference,
  81. PCHAR File,
  82. ULONG Line,
  83. UCHAR Type
  84. );
  85. #endif
  86. __inline
  87. BOOLEAN
  88. ReleaseComponentReference(
  89. PCOMPONENT_REFERENCE ComponentReference
  90. );
  91. __inline
  92. BOOLEAN
  93. ReleaseInitialComponentReference(
  94. PCOMPONENT_REFERENCE ComponentReference
  95. );
  96. __inline
  97. VOID
  98. ResetComponentReference(
  99. PCOMPONENT_REFERENCE ComponentReference
  100. );
  101. //
  102. // MACRO DECLARATIONS
  103. //
  104. #define RETURN_VOID
  105. #if COMPREF_TRACKING
  106. #define REFERENCE_COMPONENT(c) \
  107. RecordComponentReference(c, __FILE__, __LINE__, ComprefAcquireRecord)
  108. #define DEREFERENCE_COMPONENT(c) \
  109. RecordComponentReference(c, __FILE__, __LINE__, ComprefReleaseRecord)
  110. #define REFERENCE_COMPONENT_OR_RETURN(c,retcode) \
  111. if (!RecordComponentReference(c, __FILE__, __LINE__, ComprefAcquireRecord)) { return retcode; }
  112. #define DEREFERENCE_COMPONENT_AND_RETURN(c,retcode) \
  113. RecordComponentReference(c, __FILE__, __LINE__, ComprefReleaseRecord); \
  114. return retcode
  115. #else
  116. #define REFERENCE_COMPONENT(c) \
  117. AcquireComponentReference(c)
  118. #define DEREFERENCE_COMPONENT(c) \
  119. ReleaseComponentReference(c)
  120. #define REFERENCE_COMPONENT_OR_RETURN(c,retcode) \
  121. if (!AcquireComponentReference(c)) { return retcode; }
  122. #define DEREFERENCE_COMPONENT_AND_RETURN(c,retcode) \
  123. ReleaseComponentReference(c); return retcode
  124. #endif
  125. //
  126. // INLINE ROUTINE IMPLEMENTATIONS
  127. //
  128. __inline
  129. BOOLEAN
  130. AcquireComponentReference(
  131. PCOMPONENT_REFERENCE ComponentReference
  132. )
  133. /*++
  134. Routine Description:
  135. This routine is called to increment the reference-count to a component.
  136. The attempt may fail if the initial reference has been released
  137. and the component is therefore being deleted.
  138. Arguments:
  139. ComponentReference - the component to be referenced
  140. Return Value:
  141. BOOLEAN - TRUE if the component was referenced, FALSE otherwise.
  142. --*/
  143. {
  144. EnterCriticalSection(&ComponentReference->Lock);
  145. if (ComponentReference->Deleted) {
  146. LeaveCriticalSection(&ComponentReference->Lock);
  147. return FALSE;
  148. }
  149. ++ComponentReference->ReferenceCount;
  150. LeaveCriticalSection(&ComponentReference->Lock);
  151. return TRUE;
  152. } // AcquireComponentReference
  153. VOID
  154. __inline
  155. DeleteComponentReference(
  156. PCOMPONENT_REFERENCE ComponentReference
  157. )
  158. /*++
  159. Routine Description:
  160. This routine is called to destroy a component reference.
  161. It may only be called after the last reference to the component is released,
  162. i.e. after 'ReleaseComponentReference' has returned 'TRUE'.
  163. It may also be called from within the component's 'CleanupRoutine'.
  164. Arguments:
  165. ComponentReference - the component to be destroyed
  166. Return Value:
  167. none.
  168. --*/
  169. {
  170. DeleteCriticalSection(&ComponentReference->Lock);
  171. #if COMPREF_TRACKING
  172. HeapFree(GetProcessHeap(), 0, ComponentReference->RecordArray);
  173. #endif
  174. } // DeleteComponentReference
  175. ULONG
  176. __inline
  177. InitializeComponentReference(
  178. PCOMPONENT_REFERENCE ComponentReference,
  179. PCOMPONENT_CLEANUP_ROUTINE CleanupRoutine
  180. )
  181. /*++
  182. Routine Description:
  183. This routine is called to initialize a component reference.
  184. Arguments:
  185. ComponentReference - the component to be initialized
  186. CleanupRoutine - the routine to be called when the component
  187. is to be cleaned up (within the final 'ReleaseComponentReference').
  188. Return Value:
  189. none.
  190. --*/
  191. {
  192. __try {
  193. InitializeCriticalSection(&ComponentReference->Lock);
  194. }
  195. __except (EXCEPTION_EXECUTE_HANDLER) {
  196. return GetExceptionCode();
  197. }
  198. ComponentReference->Deleted = FALSE;
  199. ComponentReference->ReferenceCount = 1;
  200. ComponentReference->CleanupRoutine = CleanupRoutine;
  201. #if COMPREF_TRACKING
  202. ComponentReference->RecordIndex = 0;
  203. ComponentReference->RecordArray =
  204. HeapAlloc(
  205. GetProcessHeap(), 0, sizeof(COMPREF_RECORD) * COMPREF_RECORD_COUNT
  206. );
  207. #endif
  208. return NO_ERROR;
  209. } // InitializeComponentReference
  210. #if COMPREF_TRACKING
  211. __inline
  212. BOOLEAN
  213. RecordComponentReference(
  214. PCOMPONENT_REFERENCE ComponentReference,
  215. PCHAR File,
  216. ULONG Line,
  217. UCHAR Type
  218. )
  219. {
  220. BOOLEAN Success;
  221. ULONG i = InterlockedIncrement(&ComponentReference->RecordIndex);
  222. i %= COMPREF_RECORD_COUNT;
  223. ComponentReference->RecordArray[i].File = File;
  224. ComponentReference->RecordArray[i].Line = (USHORT)Line;
  225. ComponentReference->RecordArray[i].Type = Type;
  226. if (Type == ComprefAcquireRecord) {
  227. Success = AcquireComponentReference(ComponentReference);
  228. } else {
  229. Success = ReleaseComponentReference(ComponentReference);
  230. }
  231. ComponentReference->RecordArray[i].ReferenceCount =
  232. (UCHAR)ComponentReference->ReferenceCount;
  233. return Success;
  234. }
  235. #endif
  236. __inline
  237. BOOLEAN
  238. ReleaseComponentReference(
  239. PCOMPONENT_REFERENCE ComponentReference
  240. )
  241. /*++
  242. Routine Description:
  243. This routine is called to drop a reference to a component.
  244. If the reference drops to zero, cleanup is performed.
  245. Otherwise, cleanup occurs later when the last reference is released.
  246. Arguments:
  247. ComponentReference - the component to be referenced
  248. Return Value:
  249. BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
  250. --*/
  251. {
  252. EnterCriticalSection(&ComponentReference->Lock);
  253. if (--ComponentReference->ReferenceCount) {
  254. LeaveCriticalSection(&ComponentReference->Lock);
  255. return FALSE;
  256. }
  257. LeaveCriticalSection(&ComponentReference->Lock);
  258. ComponentReference->CleanupRoutine();
  259. return TRUE;
  260. } // ReleaseComponentReference
  261. __inline
  262. BOOLEAN
  263. ReleaseInitialComponentReference(
  264. PCOMPONENT_REFERENCE ComponentReference
  265. )
  266. /*++
  267. Routine Description:
  268. This routine is called to drop the initial reference to a component,
  269. and mark the component as deleted.
  270. If the reference drops to zero, cleanup is performed right away.
  271. Arguments:
  272. ComponentReference - the component to be referenced
  273. Return Value:
  274. BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
  275. --*/
  276. {
  277. EnterCriticalSection(&ComponentReference->Lock);
  278. if (ComponentReference->Deleted) {
  279. LeaveCriticalSection(&ComponentReference->Lock);
  280. return TRUE;
  281. }
  282. ComponentReference->Deleted = TRUE;
  283. if (--ComponentReference->ReferenceCount) {
  284. LeaveCriticalSection(&ComponentReference->Lock);
  285. return FALSE;
  286. }
  287. LeaveCriticalSection(&ComponentReference->Lock);
  288. ComponentReference->CleanupRoutine();
  289. return TRUE;
  290. } // ReleaseInitialComponentReference
  291. __inline
  292. VOID
  293. ResetComponentReference(
  294. PCOMPONENT_REFERENCE ComponentReference
  295. )
  296. /*++
  297. Routine Description:
  298. This routine is called to reset a component reference
  299. to an initial state.
  300. Arguments:
  301. ComponentReference - the component to be reset
  302. Return Value:
  303. none.
  304. --*/
  305. {
  306. EnterCriticalSection(&ComponentReference->Lock);
  307. ComponentReference->ReferenceCount = 1;
  308. ComponentReference->Deleted = FALSE;
  309. #if COMPREF_TRACKING
  310. ComponentReference->RecordIndex = 0;
  311. ZeroMemory(
  312. ComponentReference->RecordArray,
  313. sizeof(COMPREF_RECORD) * COMPREF_RECORD_COUNT
  314. );
  315. #endif
  316. LeaveCriticalSection(&ComponentReference->Lock);
  317. } // ReleaseComponentReference
  318. #ifndef _NATHLP_SOCKET_H_
  319. #define _NATHLP_SOCKET_H_
  320. ULONG
  321. MyHelperAcceptStreamSocket(
  322. PCOMPONENT_REFERENCE Component,
  323. SOCKET ListeningSocket,
  324. SOCKET AcceptedSocket OPTIONAL,
  325. PNH_BUFFER Bufferp OPTIONAL,
  326. PNH_COMPLETION_ROUTINE AcceptCompletionRoutine,
  327. PVOID Context,
  328. PVOID Context2
  329. );
  330. ULONG
  331. MyHelperConnectStreamSocket(
  332. PCOMPONENT_REFERENCE Component,
  333. SOCKET ConnectingSocket,
  334. ULONG Address,
  335. USHORT Port,
  336. PNH_BUFFER Bufferp OPTIONAL,
  337. PNH_COMPLETION_ROUTINE ConnectCompletionRoutine,
  338. PVOID Context,
  339. PVOID Context2
  340. );
  341. ULONG
  342. MyHelperCreateStreamSocket(
  343. ULONG Address OPTIONAL, // may be INADDR_NONE
  344. USHORT Port OPTIONAL,
  345. OUT SOCKET* Socketp
  346. );
  347. #define MyHelperDeleteStreamSocket(s) MyHelperDeleteSocket(s)
  348. VOID
  349. MyHelperDeleteSocket(
  350. SOCKET Socket
  351. );
  352. //
  353. // BOOLEAN
  354. // MyHelperIsFatalSocketError(
  355. // ULONG Error
  356. // );
  357. //
  358. // Determines whether a request may be reissued on a socket,
  359. // given the error-code from the previous issuance of the request.
  360. // This macro is arranged to branch on the most common error-codes first.
  361. //
  362. #define \
  363. MyHelperIsFatalSocketError( \
  364. _Error \
  365. ) \
  366. ((_Error) != ERROR_OPERATION_ABORTED && \
  367. ((_Error) == WSAEDISCON || \
  368. (_Error) == WSAECONNRESET || \
  369. (_Error) == WSAETIMEDOUT || \
  370. (_Error) == WSAENETDOWN || \
  371. (_Error) == WSAENOTSOCK || \
  372. (_Error) == WSAESHUTDOWN || \
  373. (_Error) == WSAECONNABORTED))
  374. VOID
  375. MyHelperQueryAcceptEndpoints(
  376. PUCHAR AcceptBuffer,
  377. PULONG LocalAddress OPTIONAL,
  378. PUSHORT LocalPort OPTIONAL,
  379. PULONG RemoteAddress OPTIONAL,
  380. PUSHORT RemotePort OPTIONAL
  381. );
  382. ULONG
  383. MyHelperQueryAddressSocket(
  384. SOCKET Socket
  385. );
  386. ULONG
  387. MyHelperQueryLocalEndpointSocket(
  388. SOCKET Socket,
  389. PULONG Address OPTIONAL,
  390. PUSHORT Port OPTIONAL
  391. );
  392. USHORT
  393. MyHelperQueryPortSocket(
  394. SOCKET Socket
  395. );
  396. ULONG
  397. MyHelperQueryRemoteEndpointSocket(
  398. SOCKET Socket,
  399. PULONG Address OPTIONAL,
  400. PUSHORT Port OPTIONAL
  401. );
  402. ULONG
  403. MyHelperReadStreamSocket(
  404. PCOMPONENT_REFERENCE Component,
  405. SOCKET Socket,
  406. PNH_BUFFER Bufferp OPTIONAL,
  407. ULONG Length,
  408. ULONG Offset,
  409. PNH_COMPLETION_ROUTINE CompletionRoutine,
  410. PVOID Context,
  411. PVOID Context2
  412. );
  413. ULONG
  414. MyHelperWriteStreamSocket(
  415. PCOMPONENT_REFERENCE Component,
  416. SOCKET Socket,
  417. PNH_BUFFER Bufferp,
  418. ULONG Length,
  419. ULONG Offset,
  420. PNH_COMPLETION_ROUTINE CompletionRoutine,
  421. PVOID Context,
  422. PVOID Context2
  423. );
  424. #endif // _NATHLP_SOCKET_H_