/* This function removes a given sockinfo structure from the given list and frees the memory also. */ void DeleteSockInfoFromList(PSOCK_INFO *ppHead, PSOCK_INFO pDelSockInfo) { // make the previous and the next nodes to point to each other, // insteade of pointing to pDelSockInfo. if (pDelSockInfo->prev != NULL) pDelSockInfo->prev->next = pDelSockInfo->next; if (pDelSockInfo->next != NULL) pDelSockInfo->next->prev = pDelSockInfo->prev; // if the head node is being deleted, make the next node as the head. if (*ppHead == pDelSockInfo) *ppHead = pDelSockInfo->next; // now, pDelSockInfo can be safely deleted as nobody points to it. FreeSockInfo(pDelSockInfo); printf("Deleted and freed SockInfo %p\n", pDelSockInfo); return; }
// // Function: DerefSocketContext // // Description: // This routine holds the LSP critical section and decrements the ref count // by one. It also checks if the socket has been closed while holding the // ref count. This can happen if two threads are accessing a socket simultaneously // and one calls closesocket. We don't want to remove the context from under // the second thread so it is marked as closing instead. // void DerefSocketContext( SOCK_INFO *context, int *lpErrno ) { LONG newval; int ret = NO_ERROR; EnterCriticalSection(&GlobalVars::gCriticalSection); // Decrement the ref count and see if someone closed this socket (from another thread) newval = InterlockedDecrement(&context->RefCount); if ( ( 0 == newval ) && ( 0 == context->dwOutstandingAsync ) && ( TRUE == context->bClosing ) ) { ASSERT( GlobalVars::gMainUpCallTable.lpWPUCloseSocketHandle ); // Socket has been closed so close the handle and free associated resources ret = GlobalVars::gMainUpCallTable.lpWPUCloseSocketHandle(context->LayeredSocket, lpErrno); if ( SOCKET_ERROR == ret ) { dbgprint("DerefSocketContext: WPUCloseSocketHandle() failed: %d", *lpErrno); } context->LayeredSocket = INVALID_SOCKET; RemoveSocketInfo(context->Provider, context); dbgprint("Closing socket %d Bytes Sent [%lu] Bytes Recv [%lu]", context->LayeredSocket, context->BytesSent, context->BytesRecv); FreeSockInfo( context ); context = NULL; } LeaveCriticalSection( &GlobalVars::gCriticalSection ); }
// // 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 CloseAndFreeSocketInfo( PROVIDER *provider, BOOL processDetach ) { LIST_ENTRY *entry = NULL; SOCK_INFO *si = NULL; struct linger linger; int Error, ret; ASSERT( provider ); linger.l_onoff = 1; linger.l_linger = 0; // Walk the list of sockets while ( !IsListEmpty( &provider->SocketList ) ) { entry = RemoveHeadList( &provider->SocketList ); ASSERT( entry ); si = CONTAINING_RECORD( entry, SOCK_INFO, Link ); if ( ( !processDetach ) || ( provider->NextProvider.ProtocolChain.ChainLen == BASE_PROTOCOL ) ) { ASSERT( provider->NextProcTable.lpWSPSetSockOpt ); // Set the abortive linger ret = provider->NextProcTable.lpWSPSetSockOpt( si->ProviderSocket, SOL_SOCKET, SO_LINGER, (char *) &linger, sizeof(linger), &Error ); if ( SOCKET_ERROR != ret ) { ASSERT( provider->NextProcTable.lpWSPCloseSocket ); // Close the lower provider socket ret = provider->NextProcTable.lpWSPCloseSocket( si->ProviderSocket, &Error ); if ( SOCKET_ERROR == ret ) { dbgprint("WSPCloseSocket() on handle %d failed: %d", si->ProviderSocket, Error); } #ifdef DEBUG else { dbgprint("Successfully closed socket %d", si->ProviderSocket); } #endif } #ifdef DEBUG else { dbgprint("WSPSetSockOpt(SO_LINGER) failed: %d", Error); } #endif } ASSERT( GlobalVars::gMainUpCallTable.lpWPUCloseSocketHandle ); // Close the layered handle GlobalVars::gMainUpCallTable.lpWPUCloseSocketHandle( si->LayeredSocket, &Error ); // Free the context structure FreeSockInfo( si ); } return; }