void CTCPStunThread::Reset() { _spPolling.ReleaseAndClear(); CloseListenSockets(); ClosePipes(); _fListenSocketsOnEpoll = false; memset(&_tsaListen, '\0', sizeof(_tsaListen)); _fNeedToExit = false; _spAuth.ReleaseAndClear(); _role = RolePP; memset(&_tsa, '\0', sizeof(_tsa)); _maxConnections = c_MaxNumberOfConnectionsDefault; _pthread = (pthread_t)-1; _fThreadIsValid = false; _connectionpool.Reset(); // the thread should have closed all the connections ASSERT(_hashConnections1.Size() == 0); ASSERT(_hashConnections2.Size() == 0); _hashConnections1.ResetTable(); _hashConnections2.ResetTable(); _pNewConnList = &_hashConnections1; _pOldConnList = &_hashConnections2; _timeLastSweep = time(NULL); }
VOID PrimaryAgentThreadProc( IN PPRIMARY Primary ) { BOOLEAN primaryAgentThreadExit = FALSE; ULONG listenSocketIndex; PKWAIT_BLOCK waitBlocks; SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: Start\n")); Primary->Agent.Flags |= PRIMARY_AGENT_INITIALIZING; // // Allocate wait block // waitBlocks = ExAllocatePool(NonPagedPool, sizeof(KWAIT_BLOCK) * MAXIMUM_WAIT_OBJECTS); if(waitBlocks == NULL) { ASSERT(LFS_REQUIRED); PsTerminateSystemThread(STATUS_INSUFFICIENT_RESOURCES); } for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++) KeInitializeEvent( &Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent, NotificationEvent, FALSE ); BindListenSockets( Primary ); Primary->Agent.Flags |= PRIMARY_AGENT_START; KeSetEvent(&Primary->Agent.ReadyEvent, IO_DISK_INCREMENT, FALSE); while(primaryAgentThreadExit == FALSE) { PKEVENT events[MAXIMUM_WAIT_OBJECTS]; LONG eventCnt; ULONG i; LARGE_INTEGER timeOut; NTSTATUS ntStatus; PLIST_ENTRY primaryAgentRequestEntry; ASSERT(MAX_SOCKETLPX_INTERFACE + 1 <= MAXIMUM_WAIT_OBJECTS); eventCnt = 0; events[eventCnt++] = &Primary->Agent.RequestEvent; if(!BooleanFlagOn(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN)) { for(i=0; i<MAX_SOCKETLPX_INTERFACE; i++) { if(Primary->Agent.ListenSocket[i].TdiListenContext.Irp && Primary->Agent.ListenSocket[i].Active) { events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent; } else { // events[eventCnt++] = NULL; // I wanna set NULL, But It's not Work events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent; } } ASSERT(eventCnt == MAX_SOCKETLPX_INTERFACE + 1); } timeOut.QuadPart = - 5 * HZ; ntStatus = KeWaitForMultipleObjects( eventCnt, events, WaitAny, Executive, KernelMode, TRUE, &timeOut, waitBlocks ); if(ntStatus == STATUS_TIMEOUT) { continue; } SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimaryAgentThreadProc: NTSTATUS:%lu\n", ntStatus)); if(!NT_SUCCESS(ntStatus) || ntStatus >= eventCnt) { ASSERT(LFS_UNEXPECTED); SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR); primaryAgentThreadExit = TRUE; continue; } KeClearEvent(events[ntStatus]); if(0 == ntStatus) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimaryAgentThreadProc: RequestEvent received\n")); while(primaryAgentRequestEntry = ExInterlockedRemoveHeadList( &Primary->Agent.RequestQueue, &Primary->Agent.RequestQSpinLock ) ) { PPRIMARY_AGENT_REQUEST primaryAgentRequest; primaryAgentRequest = CONTAINING_RECORD( primaryAgentRequestEntry, PRIMARY_AGENT_REQUEST, ListEntry ); switch(primaryAgentRequest->RequestType) { case PRIMARY_AGENT_REQ_DISCONNECT: { CloseListenSockets( Primary, FALSE ); break; } case PRIMARY_AGENT_REQ_SHUTDOWN: { CloseListenSockets( Primary, TRUE ); SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN); break; } case PRIMARY_AGENT_REQ_DOWN: primaryAgentThreadExit = TRUE; break; // // added to adapt network card changes. // case PRIMARY_AGENT_REQ_NIC_DISABLED: SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_DISABLED\n")); PrimaryAgentNICDisabled(Primary, &primaryAgentRequest->AddressList); break; case PRIMARY_AGENT_REQ_NIC_ENABLED: SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_ENABLED\n")); PrimaryAgentNICEnabled(Primary, &primaryAgentRequest->AddressList); break; default: ASSERT(LFS_BUG); SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR); break; } if(primaryAgentRequest->Synchronous == TRUE) KeSetEvent(&primaryAgentRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE); else DereferencePrimaryAgentRequest( primaryAgentRequest ); } continue; } ASSERT(1 <= ntStatus && ntStatus < eventCnt); // LpxEvent if( 1 <= ntStatus && ntStatus <= MAX_SOCKETLPX_INTERFACE ) // Connected { NTSTATUS tdiStatus; HANDLE listenFileHandle; PFILE_OBJECT listenFileObject; HANDLE connFileHandle; PFILE_OBJECT connFileObject; PPRIMARY_LISTEN_SOCKET listenSocket; LPX_ADDRESS remoteAddress; listenSocket = &Primary->Agent.ListenSocket[ntStatus-1]; // // retreive a connection file and remote address. // connFileHandle = listenSocket->ListenFileHandle; connFileObject = listenSocket->ListenFileObject; RtlCopyMemory(&remoteAddress, &listenSocket->TdiListenContext.RemoteAddress, sizeof(LPX_ADDRESS)); listenSocket->TdiListenContext.Irp = NULL; listenSocket->ListenFileHandle = NULL; listenSocket->ListenFileObject = NULL; KeClearEvent(&listenSocket->TdiListenContext.CompletionEvent); if(!listenSocket->Active) { SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("ListenSocket is not active. Maybe a NIC disabled.\n")); continue; } else if(listenSocket->TdiListenContext.Status != STATUS_SUCCESS) { LpxTdiCloseAddress ( listenSocket->AddressFileHandle, listenSocket->AddressFileObject ); listenSocket->Active = FALSE; Primary->Agent.ActiveListenSocketCount --; SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("Listen IRP #%d failed.\n", ntStatus)); continue; } SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: Connect from %02X:%02X:%02X:%02X:%02X:%02X 0x%4X\n", listenSocket->TdiListenContext.RemoteAddress.Node[0], listenSocket->TdiListenContext.RemoteAddress.Node[1], listenSocket->TdiListenContext.RemoteAddress.Node[2], listenSocket->TdiListenContext.RemoteAddress.Node[3], listenSocket->TdiListenContext.RemoteAddress.Node[4], listenSocket->TdiListenContext.RemoteAddress.Node[5], NTOHS(listenSocket->TdiListenContext.RemoteAddress.Port) )); // // Make a new listen connection first of all to get another connection. // It must be earlier than start a session that takes long time. // Primary cannot accept a connection before it creates a new listen object. // tdiStatus = MakeConnectionObject( listenSocket->AddressFileHandle, listenSocket->AddressFileObject, &listenFileHandle, &listenFileObject ); if(!NT_SUCCESS(tdiStatus)) { ASSERT(LPX_BUG); LpxTdiCloseAddress ( listenSocket->AddressFileHandle, listenSocket->AddressFileObject ); listenSocket->Active = FALSE; Primary->Agent.ActiveListenSocketCount --; goto start_session; } listenSocket->ListenFileHandle = listenFileHandle; listenSocket->ListenFileObject = listenFileObject; listenSocket->Flags = TDI_QUERY_ACCEPT; tdiStatus = LpxTdiListenWithCompletionEvent( listenSocket->ListenFileObject, &listenSocket->TdiListenContext, &listenSocket->Flags ); if(!NT_SUCCESS(tdiStatus)) { ASSERT(LPX_BUG); LpxTdiDisassociateAddress(listenFileObject); LpxTdiCloseConnection(listenFileHandle, listenFileObject); LpxTdiCloseAddress ( listenSocket->AddressFileHandle, listenSocket->AddressFileObject ); listenSocket->Active = FALSE; Primary->Agent.ActiveListenSocketCount --; } start_session: // // start a session. // Primary_AcceptConnection(Primary, connFileHandle, connFileObject, ntStatus-1, &remoteAddress); continue; } } for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++) KeClearEvent(&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent); // // Free wait blocks // ExFreePool(waitBlocks); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimaryAgentThreadProc: PsTerminateSystemThread\n")); Primary->Agent.Flags |= PRIMARY_AGENT_TERMINATED; PsTerminateSystemThread(STATUS_SUCCESS); }