581 lines
12 KiB
C
581 lines
12 KiB
C
/*++
|
||
|
||
Copyright (c) 1998, Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
socket.h
|
||
|
||
Abstract:
|
||
|
||
This module contains declarations for socket-management.
|
||
The routines declared here operate asynchronously on sockets
|
||
associated with an I/O completion port. They are also integrated
|
||
with the component-reference object, which may optionally be used
|
||
by callers to control the number of outstanding entries into a component's
|
||
address-space.
|
||
|
||
This module contains declarations for maintaining reference-count
|
||
on a component. It provides an asynchronous thread-safe means of
|
||
handling cleanup in a module.
|
||
|
||
The mechanism defined uses a locked reference count and cleanup-routine
|
||
to manage the lifetime of the component. When the reference-count
|
||
is dropped to zero, the associated cleanup-routine is invoked.
|
||
|
||
Author:
|
||
|
||
Abolade Gbadegesin (aboladeg) 2-Mar-1998
|
||
|
||
Revision History:
|
||
|
||
Abolade Gbadegesin (aboladeg) 23-May-1999
|
||
|
||
Added support for stream sockets.
|
||
|
||
--*/
|
||
|
||
|
||
#pragma once
|
||
|
||
|
||
typedef VOID (*PCOMPONENT_CLEANUP_ROUTINE)(VOID);
|
||
|
||
|
||
|
||
//
|
||
// Structure: COMPONENT_REFERENCE
|
||
//
|
||
// This structure must reside in memory for the lifetime of the component
|
||
// to which it refers. It is used to synchronize the component's execution.
|
||
//
|
||
|
||
typedef struct _COMPONENT_REFERENCE
|
||
{
|
||
CRITICAL_SECTION Lock;
|
||
ULONG ReferenceCount;
|
||
BOOLEAN Deleted;
|
||
PCOMPONENT_CLEANUP_ROUTINE CleanupRoutine;
|
||
#if COMPREF_TRACKING
|
||
struct _COMPREF_RECORD* RecordArray;
|
||
ULONG RecordIndex;
|
||
#endif
|
||
|
||
} COMPONENT_REFERENCE, *PCOMPONENT_REFERENCE;
|
||
|
||
|
||
|
||
#if COMPREF_TRACKING
|
||
#define COMPREF_RECORD_COUNT (1024)
|
||
|
||
typedef struct _COMPREF_RECORD
|
||
{
|
||
PCHAR File;
|
||
USHORT Line;
|
||
UCHAR ReferenceCount;
|
||
enum
|
||
{
|
||
ComprefAcquireRecord,
|
||
ComprefReleaseRecord
|
||
} Type;
|
||
|
||
} COMPREF_RECORD, *PCOMPREF_RECORD;
|
||
|
||
#endif
|
||
|
||
|
||
//
|
||
// FUNCTION DECLARATIONS
|
||
//
|
||
|
||
__inline
|
||
BOOLEAN
|
||
AcquireComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
);
|
||
|
||
VOID
|
||
__inline
|
||
DeleteComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
);
|
||
|
||
ULONG
|
||
__inline
|
||
InitializeComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference,
|
||
PCOMPONENT_CLEANUP_ROUTINE CleanupRoutine
|
||
);
|
||
|
||
#if COMPREF_TRACKING
|
||
__inline
|
||
BOOLEAN
|
||
RecordComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference,
|
||
PCHAR File,
|
||
ULONG Line,
|
||
UCHAR Type
|
||
);
|
||
#endif
|
||
|
||
__inline
|
||
BOOLEAN
|
||
ReleaseComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
);
|
||
|
||
__inline
|
||
BOOLEAN
|
||
ReleaseInitialComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
);
|
||
|
||
__inline
|
||
VOID
|
||
ResetComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
);
|
||
|
||
//
|
||
// MACRO DECLARATIONS
|
||
//
|
||
|
||
#define RETURN_VOID
|
||
|
||
#if COMPREF_TRACKING
|
||
|
||
#define REFERENCE_COMPONENT(c) \
|
||
RecordComponentReference(c, __FILE__, __LINE__, ComprefAcquireRecord)
|
||
|
||
#define DEREFERENCE_COMPONENT(c) \
|
||
RecordComponentReference(c, __FILE__, __LINE__, ComprefReleaseRecord)
|
||
|
||
#define REFERENCE_COMPONENT_OR_RETURN(c,retcode) \
|
||
if (!RecordComponentReference(c, __FILE__, __LINE__, ComprefAcquireRecord)) { return retcode; }
|
||
|
||
#define DEREFERENCE_COMPONENT_AND_RETURN(c,retcode) \
|
||
RecordComponentReference(c, __FILE__, __LINE__, ComprefReleaseRecord); \
|
||
return retcode
|
||
|
||
#else
|
||
|
||
#define REFERENCE_COMPONENT(c) \
|
||
AcquireComponentReference(c)
|
||
|
||
#define DEREFERENCE_COMPONENT(c) \
|
||
ReleaseComponentReference(c)
|
||
|
||
#define REFERENCE_COMPONENT_OR_RETURN(c,retcode) \
|
||
if (!AcquireComponentReference(c)) { return retcode; }
|
||
|
||
#define DEREFERENCE_COMPONENT_AND_RETURN(c,retcode) \
|
||
ReleaseComponentReference(c); return retcode
|
||
|
||
#endif
|
||
|
||
|
||
//
|
||
// INLINE ROUTINE IMPLEMENTATIONS
|
||
//
|
||
|
||
__inline
|
||
BOOLEAN
|
||
AcquireComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to increment the reference-count to a component.
|
||
The attempt may fail if the initial reference has been released
|
||
and the component is therefore being deleted.
|
||
|
||
Arguments:
|
||
|
||
ComponentReference - the component to be referenced
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if the component was referenced, FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
EnterCriticalSection(&ComponentReference->Lock);
|
||
if (ComponentReference->Deleted) {
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
return FALSE;
|
||
}
|
||
++ComponentReference->ReferenceCount;
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
return TRUE;
|
||
|
||
} // AcquireComponentReference
|
||
|
||
|
||
VOID
|
||
__inline
|
||
DeleteComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to destroy a component reference.
|
||
It may only be called after the last reference to the component is released,
|
||
i.e. after 'ReleaseComponentReference' has returned 'TRUE'.
|
||
It may also be called from within the component's 'CleanupRoutine'.
|
||
|
||
Arguments:
|
||
|
||
ComponentReference - the component to be destroyed
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
DeleteCriticalSection(&ComponentReference->Lock);
|
||
#if COMPREF_TRACKING
|
||
HeapFree(GetProcessHeap(), 0, ComponentReference->RecordArray);
|
||
#endif
|
||
|
||
} // DeleteComponentReference
|
||
|
||
|
||
ULONG
|
||
__inline
|
||
InitializeComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference,
|
||
PCOMPONENT_CLEANUP_ROUTINE CleanupRoutine
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to initialize a component reference.
|
||
|
||
Arguments:
|
||
|
||
ComponentReference - the component to be initialized
|
||
|
||
CleanupRoutine - the routine to be called when the component
|
||
is to be cleaned up (within the final 'ReleaseComponentReference').
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
__try {
|
||
InitializeCriticalSection(&ComponentReference->Lock);
|
||
}
|
||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
return GetExceptionCode();
|
||
}
|
||
ComponentReference->Deleted = FALSE;
|
||
ComponentReference->ReferenceCount = 1;
|
||
ComponentReference->CleanupRoutine = CleanupRoutine;
|
||
#if COMPREF_TRACKING
|
||
ComponentReference->RecordIndex = 0;
|
||
ComponentReference->RecordArray =
|
||
HeapAlloc(
|
||
GetProcessHeap(), 0, sizeof(COMPREF_RECORD) * COMPREF_RECORD_COUNT
|
||
);
|
||
#endif
|
||
return NO_ERROR;
|
||
|
||
} // InitializeComponentReference
|
||
|
||
|
||
|
||
#if COMPREF_TRACKING
|
||
__inline
|
||
BOOLEAN
|
||
RecordComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference,
|
||
PCHAR File,
|
||
ULONG Line,
|
||
UCHAR Type
|
||
)
|
||
{
|
||
BOOLEAN Success;
|
||
ULONG i = InterlockedIncrement(&ComponentReference->RecordIndex);
|
||
i %= COMPREF_RECORD_COUNT;
|
||
ComponentReference->RecordArray[i].File = File;
|
||
ComponentReference->RecordArray[i].Line = (USHORT)Line;
|
||
ComponentReference->RecordArray[i].Type = Type;
|
||
if (Type == ComprefAcquireRecord) {
|
||
Success = AcquireComponentReference(ComponentReference);
|
||
} else {
|
||
Success = ReleaseComponentReference(ComponentReference);
|
||
}
|
||
ComponentReference->RecordArray[i].ReferenceCount =
|
||
(UCHAR)ComponentReference->ReferenceCount;
|
||
return Success;
|
||
}
|
||
|
||
#endif
|
||
|
||
__inline
|
||
BOOLEAN
|
||
ReleaseComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to drop a reference to a component.
|
||
If the reference drops to zero, cleanup is performed.
|
||
Otherwise, cleanup occurs later when the last reference is released.
|
||
|
||
Arguments:
|
||
|
||
ComponentReference - the component to be referenced
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
EnterCriticalSection(&ComponentReference->Lock);
|
||
if (--ComponentReference->ReferenceCount) {
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
return FALSE;
|
||
}
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
ComponentReference->CleanupRoutine();
|
||
return TRUE;
|
||
} // ReleaseComponentReference
|
||
|
||
|
||
__inline
|
||
BOOLEAN
|
||
ReleaseInitialComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to drop the initial reference to a component,
|
||
and mark the component as deleted.
|
||
If the reference drops to zero, cleanup is performed right away.
|
||
|
||
Arguments:
|
||
|
||
ComponentReference - the component to be referenced
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE if the component was cleaned up, FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
EnterCriticalSection(&ComponentReference->Lock);
|
||
if (ComponentReference->Deleted) {
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
return TRUE;
|
||
}
|
||
ComponentReference->Deleted = TRUE;
|
||
if (--ComponentReference->ReferenceCount) {
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
return FALSE;
|
||
}
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
ComponentReference->CleanupRoutine();
|
||
return TRUE;
|
||
} // ReleaseInitialComponentReference
|
||
|
||
|
||
|
||
|
||
__inline
|
||
VOID
|
||
ResetComponentReference(
|
||
PCOMPONENT_REFERENCE ComponentReference
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to reset a component reference
|
||
to an initial state.
|
||
|
||
Arguments:
|
||
|
||
ComponentReference - the component to be reset
|
||
|
||
Return Value:
|
||
|
||
none.
|
||
|
||
--*/
|
||
|
||
{
|
||
EnterCriticalSection(&ComponentReference->Lock);
|
||
ComponentReference->ReferenceCount = 1;
|
||
ComponentReference->Deleted = FALSE;
|
||
#if COMPREF_TRACKING
|
||
ComponentReference->RecordIndex = 0;
|
||
ZeroMemory(
|
||
ComponentReference->RecordArray,
|
||
sizeof(COMPREF_RECORD) * COMPREF_RECORD_COUNT
|
||
);
|
||
#endif
|
||
LeaveCriticalSection(&ComponentReference->Lock);
|
||
} // ReleaseComponentReference
|
||
|
||
|
||
|
||
|
||
|
||
#ifndef _NATHLP_SOCKET_H_
|
||
#define _NATHLP_SOCKET_H_
|
||
|
||
|
||
|
||
|
||
|
||
|
||
ULONG
|
||
MyHelperAcceptStreamSocket(
|
||
PCOMPONENT_REFERENCE Component,
|
||
SOCKET ListeningSocket,
|
||
SOCKET AcceptedSocket OPTIONAL,
|
||
PNH_BUFFER Bufferp OPTIONAL,
|
||
PNH_COMPLETION_ROUTINE AcceptCompletionRoutine,
|
||
PVOID Context,
|
||
PVOID Context2
|
||
);
|
||
|
||
ULONG
|
||
MyHelperConnectStreamSocket(
|
||
PCOMPONENT_REFERENCE Component,
|
||
SOCKET ConnectingSocket,
|
||
ULONG Address,
|
||
USHORT Port,
|
||
PNH_BUFFER Bufferp OPTIONAL,
|
||
PNH_COMPLETION_ROUTINE ConnectCompletionRoutine,
|
||
PVOID Context,
|
||
PVOID Context2
|
||
);
|
||
|
||
|
||
ULONG
|
||
MyHelperCreateStreamSocket(
|
||
ULONG Address OPTIONAL, // may be INADDR_NONE
|
||
USHORT Port OPTIONAL,
|
||
OUT SOCKET* Socketp
|
||
);
|
||
|
||
|
||
#define MyHelperDeleteStreamSocket(s) MyHelperDeleteSocket(s)
|
||
|
||
VOID
|
||
MyHelperDeleteSocket(
|
||
SOCKET Socket
|
||
);
|
||
|
||
//
|
||
// BOOLEAN
|
||
// MyHelperIsFatalSocketError(
|
||
// ULONG Error
|
||
// );
|
||
//
|
||
// Determines whether a request may be reissued on a socket,
|
||
// given the error-code from the previous issuance of the request.
|
||
// This macro is arranged to branch on the most common error-codes first.
|
||
//
|
||
|
||
#define \
|
||
MyHelperIsFatalSocketError( \
|
||
_Error \
|
||
) \
|
||
((_Error) != ERROR_OPERATION_ABORTED && \
|
||
((_Error) == WSAEDISCON || \
|
||
(_Error) == WSAECONNRESET || \
|
||
(_Error) == WSAETIMEDOUT || \
|
||
(_Error) == WSAENETDOWN || \
|
||
(_Error) == WSAENOTSOCK || \
|
||
(_Error) == WSAESHUTDOWN || \
|
||
(_Error) == WSAECONNABORTED))
|
||
|
||
|
||
VOID
|
||
MyHelperQueryAcceptEndpoints(
|
||
PUCHAR AcceptBuffer,
|
||
PULONG LocalAddress OPTIONAL,
|
||
PUSHORT LocalPort OPTIONAL,
|
||
PULONG RemoteAddress OPTIONAL,
|
||
PUSHORT RemotePort OPTIONAL
|
||
);
|
||
|
||
ULONG
|
||
MyHelperQueryAddressSocket(
|
||
SOCKET Socket
|
||
);
|
||
|
||
ULONG
|
||
MyHelperQueryLocalEndpointSocket(
|
||
SOCKET Socket,
|
||
PULONG Address OPTIONAL,
|
||
PUSHORT Port OPTIONAL
|
||
);
|
||
|
||
USHORT
|
||
MyHelperQueryPortSocket(
|
||
SOCKET Socket
|
||
);
|
||
|
||
ULONG
|
||
MyHelperQueryRemoteEndpointSocket(
|
||
SOCKET Socket,
|
||
PULONG Address OPTIONAL,
|
||
PUSHORT Port OPTIONAL
|
||
);
|
||
|
||
|
||
ULONG
|
||
MyHelperReadStreamSocket(
|
||
PCOMPONENT_REFERENCE Component,
|
||
SOCKET Socket,
|
||
PNH_BUFFER Bufferp OPTIONAL,
|
||
ULONG Length,
|
||
ULONG Offset,
|
||
PNH_COMPLETION_ROUTINE CompletionRoutine,
|
||
PVOID Context,
|
||
PVOID Context2
|
||
);
|
||
|
||
|
||
ULONG
|
||
MyHelperWriteStreamSocket(
|
||
PCOMPONENT_REFERENCE Component,
|
||
SOCKET Socket,
|
||
PNH_BUFFER Bufferp,
|
||
ULONG Length,
|
||
ULONG Offset,
|
||
PNH_COMPLETION_ROUTINE CompletionRoutine,
|
||
PVOID Context,
|
||
PVOID Context2
|
||
);
|
||
|
||
#endif // _NATHLP_SOCKET_H_
|