1
0
KF2-Dev-Scripts/IpDrv/Classes/MeshBeaconClient.uc
2020-12-13 18:01:13 +03:00

373 lines
15 KiB
Ucode

/**
* Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
*/
/**
* This class is used to connect to a host mesh beacon in order to
* establish a connected mesh network.
*/
class MeshBeaconClient extends MeshBeacon
native;
/**
* Holds a reference to the data that is used to reach the potential host
* while a connection is being established for this client
*/
var const OnlineGameSearchResult HostPendingRequest;
/** Used to send the initial client connection request to the host */
struct native ClientConnectionRequest
{
/** Net Id of primary player on this client */
var UniqueNetId PlayerNetId;
/** NAT Type for this client */
var ENatType NatType;
/** TRUE if the client is able to host a vs match */
var bool bCanHostVs;
/** Ratio of successful vs unsuccessful matches hosted by this client in the past */
var float GoodHostRatio;
/** History of bandwidth results from previous tests. Saved/loaded in the player's profile */
var array<ConnectionBandwidthStats> BandwidthHistory;
/** Elapsed time in minutes since the last bandwidth test */
var int MinutesSinceLastTest;
};
/** Active connection request that is pending for this client */
var const ClientConnectionRequest ClientPendingRequest;
/** Keeps track of all data needed for the current upstream bandwidth test */
struct native ClientBandwidthTestData
{
/** Type of test current being done */
var EMeshBeaconBandwidthTestType TestType;
/** State of the bandwidth test for the client */
var EMeshBeaconBandwidthTestState CurrentState;
/** Total bytes expected to be sent in order to complete this test */
var int NumBytesToSendTotal;
/** Tally of bytes that have been sent so far for the test */
var int NumBytesSentTotal;
/** Size of last buffer that was sent for the test */
var int NumBytesSentLast;
/** Time since test was started */
var float ElapsedTestTime;
};
/** The upstream test state for the client */
var ClientBandwidthTestData CurrentBandwidthTest;
/** Used to drive the client state machine */
enum EMeshBeaconClientState
{
// Inactive or unknown
MBCS_None,
// A connection request is outstanding with host
MBCS_Connecting,
// Connected to the host and is ready to send
MBCS_Connected,
// Failed to establish a connection
MBCS_ConnectionFailed,
// Client has sent to the host and is awaiting for replies
MBCS_AwaitingResponse,
// The client has closed the connection
MBCS_Closed
};
/** The state of the client beacon as it establishes a connection to the host */
var EMeshBeaconClientState ClientBeaconState;
/** The pending request to be sent */
var EMeshBeaconPacketType ClientBeaconRequestType;
/** Indicates how long the client should wait for a connection response before timing out */
var config float ConnectionRequestTimeout;
/** Used to track how long we've been waiting for a connection response */
var float ConnectionRequestElapsedTime;
/** Name of the class to use for address resolving and registering */
var config string ResolverClassName;
/** Class to use for address resolving and registering */
var class<ClientBeaconAddressResolver> ResolverClass;
/** Platform specific address resolver for this beacon. Instantiated using the ResolverClass type. */
var ClientBeaconAddressResolver Resolver;
/** TRUE if address was registered with the beacon address resolver */
var transient bool bUsingRegisteredAddr;
cpptext
{
/**
* Ticks the network layer to see if there are any requests or responses to requests
*
* @param DeltaTime the amount of time that has elapsed since the last tick
*/
virtual void Tick(FLOAT DeltaTime);
/**
* Loads the class specified for the Resolver and constructs it if needed
*/
void InitResolver(void);
/**
* Creates a beacon that will send requests to remote hosts
*
* @param Addr the address that we are connecting to (needs to be resolved)
* @return true if the beacon was created successfully, false otherwise
*/
UBOOL InitClientBeacon(const FInternetIpAddr& Addr);
/**
* Unregisters the address and zeros the members involved to prevent multiple releases
*/
void CleanupAddress(void);
/**
* Handles checking for the transition from connecting to connected (socket established)
*/
void CheckConnectionStatus(void);
/**
* Sends all the data for a new client connection on the host.
* Client data includes the player net id, cient NAT type, and previous bandwidth history.
* Assumes that a connection has successfully been established with the host.
*/
void SendClientConnectionRequest(void);
/**
* Checks the socket for a response from the host and processes if present
*/
void ReadHostData(void);
/**
* Processes a packet that was received from the host
*
* @param Packet the packet that the host sent
* @param PacketSize the size of the packet to process
*/
void ProcessHostPacket(BYTE* Packet,INT PacketSize);
/**
* Routes the response packet received from a host to the correct handler based on its type.
*
* @param HostPacketType packet ID from EMeshBeaconPacketType that represents a host response to this client
* @param FromBuffer the packet serializer to read from
* @return TRUE if the data packet type was processed
*/
UBOOL HandleHostPacketByType(BYTE HostPacketType,FNboSerializeFromBuffer& FromBuffer);
/**
* Common routine for notifying of a timeout trying to talk to host
*/
void ProcessHostTimeout(void);
/**
* Processes a heartbeat update, sends a heartbeat back, and clears the timer
*/
void ProcessHeartbeat(void);
/**
* Update a bandwidth test that is currently in progress for this client.
* All other host packets are ignored until the current test finishes or timeout occurs.
*/
void ProcessInProgressBandwidthTest(void);
/**
* Reads the host response to the client's connection request.
* Triggers a delegate.
*
* @param FromBuffer the packet serializer to read from
*/
void ProcessHostResponseConnectionRequest(FNboSerializeFromBuffer& FromBuffer);
/**
* Handles a new bandwidth test request initiated by the host for this client.
* Triggers a delegate.
*
* @param FromBuffer the packet serializer to read from
*/
void ProcessHostRequestBandwidthTest(FNboSerializeFromBuffer& FromBuffer);
/**
* Handles a host response that all upstream bandwidth data was received by the host.
* Triggers a delegate.
*
* @param FromBuffer the packet serializer to read from
*/
void ProcessHostFinishedBandwidthTest(FNboSerializeFromBuffer& FromBuffer);
/**
* Processes a travel request packet that was received from the host
*
* @param FromBuffer the packet serializer to read from
*/
void ProcessHostTravelRequest(FNboSerializeFromBuffer& FromBuffer);
/**
* Processes a request packet that was received from the host to create a new game session
*
* @param FromBuffer the packet serializer to read from
*/
void ProcessHostCreateNewSessionRequest(FNboSerializeFromBuffer& FromBuffer);
}
/**
* Stops listening for requests/responses and releases any allocated memory
*/
native event DestroyBeacon();
/**
* Request a connection to be established to the remote host. As part of the
* connection request also send the NAT type and bandwidth history data for the client.
* Note this request is async and the results will be sent via the delegate
*
* @param DesiredHost the server that the connection will be made to
* @param ClientRequest the client data that is going to be sendt with the request
* @param bRegisterSecureAddress if TRUE then then key exchange is required to connect with the host
* @return TRUE if the request async task started ok, false if it failed to send
*/
native function bool RequestConnection(const out OnlineGameSearchResult DesiredHost,const out ClientConnectionRequest ClientRequest,bool bRegisterSecureAddress);
/**
* Have this client start a bandwidth test on the connected host by sending a start packet
* and then streaming as many dummy packets as possible before timeout (MaxBandwidthTestSendTime).
*
* @param TestType test to run based on enum of EMeshBeaconBandwidthTestType supported bandwidth test types
* @param TestBufferSize size in bytes of total data to be sent for the bandwidth test
* @return TRUE if the test was successfully started
*/
native function bool BeginBandwidthTest(EMeshBeaconBandwidthTestType TestType,INT TestBufferSize);
/**
* Delegate called by the client mesh beacon when a connection request has been responded to by the destination host
*
* @param ConnectionResult whether the connection request was successful
*/
delegate OnConnectionRequestResult(EMeshBeaconConnectionResult ConnectionResult);
/**
* Delegate called by the client mesh beacon when a new bandwidth test request has been received from the host.
*
* @param TestType test to run based on enum of EMeshBeaconBandwidthTestType supported bandwidth test types
*/
delegate OnReceivedBandwidthTestRequest(EMeshBeaconBandwidthTestType TestType);
/**
* Delegate called by the client mesh beacon when bandwidth testing has completed on the host
* and the results have been sent back to this client.
*
* @param TestType test that completed based on enum of EMeshBeaconBandwidthTestType supported bandwidth test types
* @param TestResult overall result from running the test
* @param BandwidthStats statistics and timing information from running the test
*/
delegate OnReceivedBandwidthTestResults(
EMeshBeaconBandwidthTestType TestType,
EMeshBeaconBandwidthTestResult TestResult,
const out ConnectionBandwidthStats BandwidthStats);
/**
* Delegate called by the client mesh beacon when the host sends a request for all clients to travel to
* the destination included in the packet.
*
* @param SessionName the name of the session to register
* @param SearchClass the search that should be populated with the session
* @param PlatformSpecificInfo the binary data to place in the platform specific areas
*/
delegate OnTravelRequestReceived(name SessionName,class<OnlineGameSearch> SearchClass,const out byte PlatformSpecificInfo[80]);
/**
* Delegate called by the client mesh beacon when the host sends a request for a client to create a new game session.
* Used during game session migration to a new host.
*
* @param SessionName the name of the session to register
* @param SearchClass the search that should be populated with the session
* @param Players list of players to register on the newly created session
*/
delegate OnCreateNewSessionRequestReceived(name SessionName,class<OnlineGameSearch> SearchClass,const out array<PlayerMember> Players);
/**
* Notify host of a newly created game session by this client. Host can decide to use/discard the new game session.
*
* @param bSuccess TRUE if the session was created successfully
* @param SessionName the name of the session that was created
* @param SearchClass the search that should be populated with the session
* @param PlatformSpecificInfo the binary data to place in the platform specific areas
*/
native function bool SendHostNewGameSessionResponse(bool bSuccess,name SessionName,class<OnlineGameSearch> SearchClass,const out byte PlatformSpecificInfo[80]);
`if(`notdefined(FINAL_RELEASE))
/**
* Render debug info about the client mesh beacon
*/
function DumpInfo()
{
local int HistoryIdx;
`Log("Debug info for Beacon: "$BeaconName,,'DevBeacon');
`Log("",,'DevBeacon');
`Log("Client entry: ",,'DevBeacon');
`Log(" PlayerNetId: "$class'OnlineSubsystem'.static.UniqueNetIdToString(ClientPendingRequest.PlayerNetId),,'DevBeacon');
`Log(" NatType: "$ClientPendingRequest.NatType,,'DevBeacon');
`Log(" GoodHostRatio: "$ClientPendingRequest.GoodHostRatio,,'DevBeacon');
`Log(" bCanHostVs: "$ClientPendingRequest.bCanHostVs,,'DevBeacon');
`Log(" MinutesSinceLastTest: "$ClientPendingRequest.MinutesSinceLastTest,,'DevBeacon');
`Log(" BandwidthTest.CurrentState: "$CurrentBandwidthTest.CurrentState,,'DevBeacon');
`Log(" BandwidthTest.TestType: "$CurrentBandwidthTest.TestType,,'DevBeacon');
`Log(" Bandwidth History: "$ClientPendingRequest.BandwidthHistory.Length,,'DevBeacon');
for (HistoryIdx=0; HistoryIdx < ClientPendingRequest.BandwidthHistory.Length; HistoryIdx++)
{
`Log(" "
$" Upstream bytes/sec: "$ClientPendingRequest.BandwidthHistory[HistoryIdx].UpstreamRate
$" Downstream bytes/sec: "$ClientPendingRequest.BandwidthHistory[HistoryIdx].DownstreamRate
$" Roundrtrip msec: "$ClientPendingRequest.BandwidthHistory[HistoryIdx].RoundtripLatency,,'DevBeacon');
}
}
/**
* Render debug info about the client mesh beacon
*
* @param Canvas canvas object to use for rendering debug info
*/
function DebugRender(Canvas Canvas)
{
local int HistoryIdx;
local float XL,YL;
local float Offset;
Offset = 50;
Canvas.Font = class'Engine'.Static.GetTinyFont();
Canvas.StrLen("============================================================",XL,YL);
Canvas.SetPos(Offset,Offset);
Canvas.SetDrawColor(0,0,255,64);
Canvas.DrawTile(Canvas.DefaultTexture,XL,Canvas.SizeY-(Offset*2),0,0,1,1);
Canvas.SetPos(Offset,Offset);
Canvas.SetDrawColor(255,255,255);
Canvas.DrawText("Debug info for Beacon: "$BeaconName);
Canvas.DrawText("");
Canvas.DrawText("Client entry: ");
Canvas.StrLen("============================================================",XL,YL);
Canvas.SetPos(Canvas.CurX+10,Canvas.CurY);
Canvas.DrawText("PlayerNetId: "$class'OnlineSubsystem'.static.UniqueNetIdToString(ClientPendingRequest.PlayerNetId));
Canvas.DrawText("NatType: "$ClientPendingRequest.NatType);
Canvas.DrawText("GoodHostRatio: "$ClientPendingRequest.GoodHostRatio);
Canvas.DrawText("bCanHostVs: "$ClientPendingRequest.bCanHostVs);
Canvas.DrawText("MinutesSinceLastTest: "$ClientPendingRequest.MinutesSinceLastTest);
Canvas.DrawText("Current BandwidthTest: ");
Canvas.SetPos(Canvas.CurX+10,Canvas.CurY);
Canvas.DrawText("CurrentState: "$CurrentBandwidthTest.CurrentState);
Canvas.DrawText("TestType: "$CurrentBandwidthTest.TestType);
Canvas.DrawText("NumBytesToSendTotal: "$CurrentBandwidthTest.NumBytesToSendTotal);
Canvas.DrawText("NumBytesSentTotal: "$CurrentBandwidthTest.NumBytesSentTotal);
Canvas.SetPos(Canvas.CurX-10,Canvas.CurY);
Canvas.DrawText("Bandwidth History: "$ClientPendingRequest.BandwidthHistory.Length);
Canvas.SetPos(Canvas.CurX+10,Canvas.CurY);
for (HistoryIdx=0; HistoryIdx < ClientPendingRequest.BandwidthHistory.Length; HistoryIdx++)
{
Canvas.DrawText(" Upstream bytes/sec: "$ClientPendingRequest.BandwidthHistory[HistoryIdx].UpstreamRate
$" Roundrtrip msec: "$ClientPendingRequest.BandwidthHistory[HistoryIdx].RoundtripLatency);
}
}
`endif