2025-11-28 00:35:46 +09:00

184 lines
4.8 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (C) 2004 Microsoft Corporation. All Rights Reserved.
//
// Module Name: sockinfo.cpp
//
// Description:
//
// This sample illustrates an IFS based LSP which implements basic proxying
// capabilities.
//
// This file contains routines associated with the SOCKET_CONTEXT structure. This
// structure maintains the mapping between the upper layer's socket and the
// corresponding lower layer's socket. The routines in this file are for allocating,
// linked list management, etc.
//
#include "lspdef.h"
//
// Function: FindAndRefSocketContext
//
// Description:
// This routine grabs the LSP critical seciton to lookup the socket context
// and increase its ref count. Any operation on the socket context holds
// the critical section so that it cannot be freed while its state changes.
//
SOCKET_CONTEXT *
FindSocketContext(
SOCKET s,
BOOL Remove
)
{
SOCKET_CONTEXT *SocketContext = NULL,
*info = NULL;
LIST_ENTRY *lptr = NULL;
int i;
EnterCriticalSection( &gCriticalSection );
for(i=0; i < gLayerCount ;i++)
{
EnterCriticalSection( &gLayerInfo[ i ].ProviderCritSec );
for(lptr = gLayerInfo[ i ].SocketList.Flink ;
lptr != &gLayerInfo[ i ].SocketList ;
lptr = lptr->Flink )
{
info = CONTAINING_RECORD( lptr, SOCKET_CONTEXT, Link );
if ( s == info->Socket )
{
SocketContext = info;
if ( TRUE == Remove )
{
RemoveEntryList( &info->Link );
}
break;
}
}
LeaveCriticalSection( &gLayerInfo[ i ].ProviderCritSec );
if ( NULL != SocketContext )
break;
}
LeaveCriticalSection( &gCriticalSection );
return SocketContext;
}
//
// Function: CreateSockInfo
//
// Description:
// Allocates a new socket info context structure and initializes the fields
// except for the LayeredSocket field. The context must be allocated first,
// then the layered socket is created (with the SOCKET_CONTEXT structure as the
// context information), and then the LayeredSocket field is set. If
// the Inherit context is provided, information is copied to the new socket
// context structure (such as with WSPAccept). If the Insert flag is TRUE
// then the context is automatically inserted into the list of sockets
// for the given provider. If not then the caller must insert the context
// (WSPAccept does this to ensure all fields of the context are valid
// including LayeredSocket before insertion so that the async thread
// handler will work properly).
//
SOCKET_CONTEXT *
CreateSocketContext(
PROVIDER *Provider,
SOCKET Socket,
int *lpErrno
)
{
SOCKET_CONTEXT *newContext = NULL;
newContext = (SOCKET_CONTEXT *) LspAlloc(
sizeof( SOCKET_CONTEXT ),
lpErrno
);
if ( NULL == newContext )
{
dbgprint("CreateSocketContext: LspAlloc failed: %d", *lpErrno );
goto cleanup;
}
newContext->Socket = Socket;
newContext->Provider = Provider;
newContext->Proxied = FALSE;
EnterCriticalSection( &Provider->ProviderCritSec );
InsertHeadList( &Provider->SocketList, &newContext->Link );
LeaveCriticalSection( &Provider->ProviderCritSec );
return newContext;
cleanup:
return NULL;
}
//
// Function: FreeSockInfo
//
// Description:
// This routine frees the socket context structure.
//
void
FreeSocketContext(
PROVIDER *Provider,
SOCKET_CONTEXT *Context
)
{
EnterCriticalSection( &Provider->ProviderCritSec );
RemoveEntryList( &Context->Link );
LspFree( Context );
LeaveCriticalSection( &Provider->ProviderCritSec );
return;
}
//
// Function: CloseAndFreeSocketInfo
//
// Description:
// Closes all sockets belonging to the specified provider and frees
// the context information. If the lower provider socket is still
// valid, set an abortive linger, and close the socket.
//
void
FreeSocketContextList(
PROVIDER *provider
)
{
LIST_ENTRY *lptr = NULL;
SOCKET_CONTEXT *context = NULL;
ASSERT( provider );
// Walk the list of sockets
while ( !IsListEmpty( &provider->SocketList ) )
{
lptr = RemoveHeadList( &provider->SocketList );
ASSERT( lptr );
context = CONTAINING_RECORD( lptr, SOCKET_CONTEXT, Link );
// Context is already removed so just free it
LspFree( context );
}
return;
}