fix: MultiplexTransport GetMaxMessageSize NullReferenceException when called on server. And fixes potential exploits / out of sync issues where clients with different transports might see different game states because of different max message sizes. (#1332)

This commit is contained in:
vis2k 2019-12-21 15:09:33 +01:00 committed by Paul Pacheco
parent 9a0127aadc
commit b3127beb89
2 changed files with 28 additions and 6 deletions

View File

@ -104,11 +104,6 @@ public override bool ClientSend(int channelId, ArraySegment<byte> segment)
return available.ClientSend(channelId, segment); return available.ClientSend(channelId, segment);
} }
public override int GetMaxPacketSize(int channelId = 0)
{
return available.GetMaxPacketSize(channelId);
}
#endregion #endregion
#region Server #region Server
@ -239,6 +234,28 @@ public override void ServerStop()
} }
#endregion #endregion
public override int GetMaxPacketSize(int channelId = 0)
{
// finding the max packet size in a multiplex environment has to be
// done very carefully:
// * servers run multiple transports at the same time
// * different clients run different transports
// * there should only ever be ONE true max packet size for everyone,
// otherwise a spawn message might be sent to all tcp sockets, but
// be too big for some udp sockets. that would be a debugging
// nightmare and allow for possible exploits and players on
// different platforms seeing a different game state.
// => the safest solution is to use the smallest max size for all
// transports. that will never fail.
int mininumAllowedSize = int.MaxValue;
foreach (Transport transport in transports)
{
int size = transport.GetMaxPacketSize(channelId);
mininumAllowedSize = Mathf.Min(size, mininumAllowedSize);
}
return mininumAllowedSize;
}
public override void Shutdown() public override void Shutdown()
{ {
foreach (Transport transport in transports) foreach (Transport transport in transports)

View File

@ -177,8 +177,13 @@ public virtual bool GetConnectionInfo(int connectionId, out string address)
/// <summary> /// <summary>
/// The maximum packet size for a given channel. Unreliable transports /// The maximum packet size for a given channel. Unreliable transports
/// usually can only deliver small packets. Reliable fragmented channels /// usually can only deliver small packets. Reliable fragmented channels
/// can usually deliver large ones. /// can usually deliver large ones.
///
/// GetMaxPacketSize needs to return a value at all times. Even if the
/// Transport isn't running, or isn't Available(). This is because
/// Fallback and Multiplex transports need to find the smallest possible
/// packet size at runtime.
/// </summary> /// </summary>
/// <param name="channelId">channel id</param> /// <param name="channelId">channel id</param>
/// <returns>the size in bytes that can be sent via the provided channel</returns> /// <returns>the size in bytes that can be sent via the provided channel</returns>