void AOnlineBeaconHost::NotifyControlMessage(UNetConnection* Connection, uint8 MessageType, class FInBunch& Bunch) { if(NetDriver->ServerConnection == NULL) { bool bCloseConnection = false; // We are the server. #if !(UE_BUILD_SHIPPING && WITH_EDITOR) UE_LOG(LogNet, Verbose, TEXT("Beacon: Host received: %s"), FNetControlMessageInfo::GetName(MessageType)); #endif switch (MessageType) { case NMT_Hello: { UE_LOG(LogNet, Log, TEXT("Beacon Hello")); uint8 IsLittleEndian; int32 RemoteMinVer, RemoteVer; FGuid RemoteGameGUID; FNetControlMessage<NMT_Hello>::Receive(Bunch, IsLittleEndian, RemoteMinVer, RemoteVer, RemoteGameGUID); if (!IsNetworkCompatible(Connection->Driver->RequireEngineVersionMatch, RemoteVer, RemoteMinVer)) { FNetControlMessage<NMT_Upgrade>::Send(Connection, GEngineMinNetVersion, GEngineNetVersion); bCloseConnection = true; } else { Connection->NegotiatedVer = FMath::Min(RemoteVer, GEngineNetVersion); // Make sure the server has the same GameGUID as we do if( RemoteGameGUID != GetDefault<UGeneralProjectSettings>()->ProjectID ) { FString ErrorMsg = NSLOCTEXT("NetworkErrors", "ServerHostingDifferentGame", "Incompatible game connection.").ToString(); FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg); bCloseConnection = true; break; } Connection->Challenge = FString::Printf(TEXT("%08X"), FPlatformTime::Cycles()); FNetControlMessage<NMT_BeaconWelcome>::Send(Connection); Connection->FlushNet(); } break; } case NMT_Netspeed: { int32 Rate; FNetControlMessage<NMT_Netspeed>::Receive(Bunch, Rate); Connection->CurrentNetSpeed = FMath::Clamp(Rate, 1800, NetDriver->MaxClientRate); UE_LOG(LogNet, Log, TEXT("Beacon: Client netspeed is %i"), Connection->CurrentNetSpeed); break; } case NMT_BeaconJoin: { FString ErrorMsg; FString BeaconType; FNetControlMessage<NMT_BeaconJoin>::Receive(Bunch, BeaconType); UE_LOG(LogNet, Log, TEXT("Beacon Join %s"), *BeaconType); if (Connection->ClientWorldPackageName == NAME_None) { AOnlineBeaconClient* ClientActor = GetClientActor(Connection); if (ClientActor == NULL) { UWorld* World = GetWorld(); Connection->ClientWorldPackageName = World->GetOutermost()->GetFName(); AOnlineBeaconClient* NewClientActor = SpawnBeaconActor(); if (NewClientActor && BeaconType == NewClientActor->GetBeaconType()) { FNetworkGUID NetGUID = Connection->PackageMap->AssignNewNetGUID(NewClientActor); NewClientActor->SetNetConnection(Connection); Connection->OwningActor = NewClientActor; NewClientActor->Role = ROLE_None; NewClientActor->SetReplicates(false); ClientActors.Add(NewClientActor); FNetControlMessage<NMT_BeaconAssignGUID>::Send(Connection, NetGUID); } else { ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnFailureError", "Join failure, Couldn't spawn beacon.").ToString(); } } else { ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnExistingActorError", "Join failure, existing beacon actor.").ToString();; } } else { ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnClientWorldPackageNameError", "Join failure, existing ClientWorldPackageName.").ToString();; } if (!ErrorMsg.IsEmpty()) { UE_LOG(LogNet, Log, TEXT("%s"), *ErrorMsg); FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg); bCloseConnection = true; } break; } case NMT_BeaconNetGUIDAck: { FString BeaconType; FNetControlMessage<NMT_BeaconNetGUIDAck>::Receive(Bunch, BeaconType); AOnlineBeaconClient* ClientActor = GetClientActor(Connection); if (ClientActor && BeaconType == ClientActor->GetBeaconType()) { ClientActor->Role = ROLE_Authority; ClientActor->SetReplicates(true); ClientActor->SetAutonomousProxy(true); // Send an RPC to the client to open the actor channel and guarantee RPCs will work ClientActor->ClientOnConnected(); UE_LOG(LogNet, Log, TEXT("Beacon Handshake complete!")); FOnBeaconConnected* OnBeaconConnectedDelegate = OnBeaconConnectedMapping.Find(FName(*BeaconType)); if (OnBeaconConnectedDelegate) { OnBeaconConnectedDelegate->ExecuteIfBound(ClientActor, Connection); } } else { // Failed to connect. FString ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnNetGUIDAckError", "Join failure, no actor at NetGUIDAck.").ToString(); UE_LOG(LogNet, Log, TEXT("%s"), *ErrorMsg); FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg); bCloseConnection = true; } break; } case NMT_BeaconWelcome: case NMT_BeaconAssignGUID: default: { FString ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnUnexpectedError", "Join failure, unexpected control message.").ToString(); UE_LOG(LogNet, Log, TEXT("%s"), *ErrorMsg); FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg); bCloseConnection = true; } break; } if (bCloseConnection) { AOnlineBeaconClient* ClientActor = GetClientActor(Connection); if (ClientActor) { RemoveClientActor(ClientActor); } Connection->FlushNet(true); Connection->Close(); } } }
void AOnlineBeaconHost::NotifyControlMessage(UNetConnection* Connection, uint8 MessageType, class FInBunch& Bunch) { if(NetDriver->ServerConnection == nullptr) { bool bCloseConnection = false; // We are the server. #if !(UE_BUILD_SHIPPING && WITH_EDITOR) UE_LOG(LogBeacon, Verbose, TEXT("%s[%s] Host received: %s"), *GetName(), Connection ? *Connection->GetName() : TEXT("Invalid"), FNetControlMessageInfo::GetName(MessageType)); #endif switch (MessageType) { case NMT_Hello: { UE_LOG(LogBeacon, Log, TEXT("Beacon Hello")); uint8 IsLittleEndian; uint32 RemoteNetworkVersion = 0; uint32 LocalNetworkVersion = FNetworkVersion::GetLocalNetworkVersion(); FNetControlMessage<NMT_Hello>::Receive(Bunch, IsLittleEndian, RemoteNetworkVersion); if (!FNetworkVersion::IsNetworkCompatible(LocalNetworkVersion, RemoteNetworkVersion)) { UE_LOG(LogBeacon, Log, TEXT("Client not network compatible %s"), *Connection->GetName()); FNetControlMessage<NMT_Upgrade>::Send(Connection, LocalNetworkVersion); bCloseConnection = true; } else { Connection->Challenge = FString::Printf(TEXT("%08X"), FPlatformTime::Cycles()); FNetControlMessage<NMT_BeaconWelcome>::Send(Connection); Connection->FlushNet(); } break; } case NMT_Netspeed: { int32 Rate; FNetControlMessage<NMT_Netspeed>::Receive(Bunch, Rate); Connection->CurrentNetSpeed = FMath::Clamp(Rate, 1800, NetDriver->MaxClientRate); UE_LOG(LogBeacon, Log, TEXT("Client netspeed is %i"), Connection->CurrentNetSpeed); break; } case NMT_BeaconJoin: { FString ErrorMsg; FString BeaconType; FUniqueNetIdRepl UniqueId; FNetControlMessage<NMT_BeaconJoin>::Receive(Bunch, BeaconType, UniqueId); UE_LOG(LogBeacon, Log, TEXT("Beacon Join %s %s"), *BeaconType, *UniqueId.ToDebugString()); if (Connection->ClientWorldPackageName == NAME_None) { AOnlineBeaconClient* ClientActor = GetClientActor(Connection); if (ClientActor == nullptr) { UWorld* World = GetWorld(); Connection->ClientWorldPackageName = World->GetOutermost()->GetFName(); AOnlineBeaconClient* NewClientActor = nullptr; FOnBeaconSpawned* OnBeaconSpawnedDelegate = OnBeaconSpawnedMapping.Find(BeaconType); if (OnBeaconSpawnedDelegate && OnBeaconSpawnedDelegate->IsBound()) { NewClientActor = OnBeaconSpawnedDelegate->Execute(Connection); } if (NewClientActor && BeaconType == NewClientActor->GetBeaconType()) { NewClientActor->SetConnectionState(EBeaconConnectionState::Pending); FNetworkGUID NetGUID = Connection->Driver->GuidCache->AssignNewNetGUID_Server(NewClientActor); NewClientActor->SetNetConnection(Connection); Connection->PlayerId = UniqueId; Connection->OwningActor = NewClientActor; NewClientActor->Role = ROLE_Authority; NewClientActor->SetReplicates(false); check(NetDriverName == NetDriver->NetDriverName); NewClientActor->SetNetDriverName(NetDriverName); ClientActors.Add(NewClientActor); FNetControlMessage<NMT_BeaconAssignGUID>::Send(Connection, NetGUID); } else { ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnFailureError", "Join failure, Couldn't spawn beacon.").ToString(); } } else { ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnExistingActorError", "Join failure, existing beacon actor.").ToString(); } } else { ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnClientWorldPackageNameError", "Join failure, existing ClientWorldPackageName.").ToString(); } if (!ErrorMsg.IsEmpty()) { UE_LOG(LogBeacon, Log, TEXT("%s: %s"), *Connection->GetName(), *ErrorMsg); FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg); bCloseConnection = true; } break; } case NMT_BeaconNetGUIDAck: { FString ErrorMsg; FString BeaconType; FNetControlMessage<NMT_BeaconNetGUIDAck>::Receive(Bunch, BeaconType); AOnlineBeaconClient* ClientActor = GetClientActor(Connection); if (ClientActor && BeaconType == ClientActor->GetBeaconType()) { FOnBeaconConnected* OnBeaconConnectedDelegate = OnBeaconConnectedMapping.Find(BeaconType); if (OnBeaconConnectedDelegate) { ClientActor->SetReplicates(true); ClientActor->SetAutonomousProxy(true); ClientActor->SetConnectionState(EBeaconConnectionState::Open); // Send an RPC to the client to open the actor channel and guarantee RPCs will work ClientActor->ClientOnConnected(); UE_LOG(LogBeacon, Log, TEXT("Handshake complete for %s!"), *ClientActor->GetName()); OnBeaconConnectedDelegate->ExecuteIfBound(ClientActor, Connection); } else { // Failed to connect. ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnNetGUIDAckError1", "Join failure, no host object at NetGUIDAck.").ToString(); } } else { // Failed to connect. ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnNetGUIDAckError2", "Join failure, no actor at NetGUIDAck.").ToString(); } if (!ErrorMsg.IsEmpty()) { UE_LOG(LogBeacon, Log, TEXT("%s: %s"), *Connection->GetName(), *ErrorMsg); FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg); bCloseConnection = true; } break; } case NMT_BeaconWelcome: case NMT_BeaconAssignGUID: default: { FString ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnUnexpectedError", "Join failure, unexpected control message.").ToString(); UE_LOG(LogBeacon, Log, TEXT("%s: %s"), *Connection->GetName(), *ErrorMsg); FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg); bCloseConnection = true; } break; } if (bCloseConnection) { UE_LOG(LogBeacon, Verbose, TEXT("Closing connection %s: %s"), *Connection->GetName(), *Connection->PlayerId.ToDebugString()); AOnlineBeaconClient* ClientActor = GetClientActor(Connection); if (ClientActor) { UE_LOG(LogBeacon, Verbose, TEXT("- BeaconActor: %s %s"), *ClientActor->GetName(), *ClientActor->GetBeaconType()); AOnlineBeaconHostObject* BeaconHostObject = GetHost(ClientActor->GetBeaconType()); if (BeaconHostObject) { UE_LOG(LogBeacon, Verbose, TEXT("- HostObject: %s"), *BeaconHostObject->GetName()); BeaconHostObject->NotifyClientDisconnected(ClientActor); } RemoveClientActor(ClientActor); } Connection->FlushNet(true); Connection->Close(); UE_LOG(LogBeacon, Verbose, TEXT("--------------------------------")); } } }