Пример #1
0
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);
}
Пример #2
0
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);
}