Retrieve the originating netdriver at any point in the stack

We are writing out analytics events on a listen server. These sort of calls are deep in application code here and there with no context passed through the callstack.

From our analytics plugin I would like to be able to tag the event with the player who initiated the request but I have been unable to find a way to do this without either passing it in all the way through various functions or by modifying engine code. Note that this is not a case where I am in an owned object such as a PC or a PS where I can get the connection directly from GetOwner(). In my case I might be in a different object or in some subsystem without a direct way to get to the owning connection.

A very simplified example might be:

[client] PC->ServerPressButton(Actor);

[server] Actor->PressButton();

[server] RecordEvent(“button_pressed”);

`RecordEvent` needs to know which PC initiated the action without having PC passed in.

Can you tell me if this is possible without modifications? Does the engine modification here make sense or is there already a way to get this information?

Attached is a small change I’ve made to `UNetDriver` which seems to get the job done. We haven’t tested this thoroughly and it’s quite possible we’re missing something.

// Added a method to retrieve the connection
UNetConnection* UNetDriver::GetCurrentDispatchConnection()
{
	return CurrentTickDispatchConnection.Get();
}
 
void UNetDriver::PostTickDispatch()
{
...
	TArray<UNetConnection*> ClientConnCopy = ClientConnections;
	for (UNetConnection* CurConn : ClientConnCopy)
	{
		if (IsValid(CurConn))
		{
			CurrentTickDispatchConnection = CurConn; // Added: Save the connection in our local state for lookup downstream
			CurConn->PostTickDispatch();
		}
	}
 
	CurrentTickDispatchConnection.Reset(); // Added: Remove it after we're done
...
}
 
// Now in my application code I can do something like this at any time.
if (UNetConnection* Conn = GetOwner()->GetNetDriver()->GetCurrentDispatchConnection())
{
	APlayerController* PC = Conn->PlayerController;
	UE_LOG(LogTemp, Log, TEXT("RPC called by %s"), *PC->GetName());
}

Hi,

Given your use case, I think making a change like this seems reasonable.

Generally, the NetConnection is retrieved by the owning actor, such as with the “NetConnection” property on the PlayerController. If you’re unable to pass that context information into the current scope, I don’t believe there’s any way to use the NetDriver to see if there’s a specific NetConnection that is being ticked or currently processing a packet.

While I’m not familiar with the details of your implementation, it does seem as though you may need to track the current connection in some other places as well, not just PostTickDispatch. For instance, a server RPC can be received and invoked from within UIpNetDriver::TickDispatch, which will call ReceivedRawPacket on the connection associated with the packet’s address.

Thanks,

Alex

Thank you Alex. I will take a look at the other callsites that I will need to patch.