// note: original HLAPI HandleBytes function handled >1 message in a while loop, but this wasn't necessary // anymore because NetworkServer/NetworkClient Update both use while loops to handle >1 data events per // frame already. // -> in other words, we always receive 1 message per Receive call, never two. // -> can be tested easily with a 1000ms send delay and then logging amount received in while loops here // and in NetworkServer/Client Update. HandleBytes already takes exactly one. /// <summary> /// This function allows custom network connection classes to process data from the network before it is passed to the application. /// </summary> /// <param name="buffer">The data received.</param> internal void TransportReceive(ArraySegment <byte> buffer, int channelId) { // unpack message using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(buffer)) { try { int msgType = MessagePacker.UnpackId(networkReader); if (msgType == MessagePacker.GetId <NotifyPacket>()) { // this is a notify message, send to the notify receive NotifyPacket notifyPacket = networkReader.ReadNotifyPacket(); ReceiveNotify(notifyPacket, networkReader, channelId); } else { // try to invoke the handler for that message InvokeHandler(msgType, networkReader, channelId); } } catch (InvalidDataException ex) { logger.Log(ex.ToString()); } catch (Exception ex) { logger.LogError("Closed connection: " + this + ". Invalid message " + ex); Connection?.Disconnect(); } } }
public void HandleMessage(INetworkPlayer player, ArraySegment <byte> packet) { using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(packet)) { // set ObjectLocator so that message can use NetworkIdentity networkReader.ObjectLocator = objectLocator; // protect against attackers trying to send invalid data packets // exception could be throw if: // - invalid headers // - invalid message ids // - invalid data causing exceptions // - negative ReadBytesAndSize prefixes // - invalid utf8 strings // - etc. // // if exception is caught, disconnect the attacker to stop any further attacks try { int msgType = MessagePacker.UnpackId(networkReader); InvokeHandler(player, msgType, networkReader); } catch (Exception e) { string disconnectMessage = disconnectOnException ? $", Closed connection: {player}" : ""; logger.LogError($"{e.GetType()} in Message handler (see stack below){disconnectMessage}\n{e}"); if (disconnectOnException) { player.Disconnect(); } } } }
internal void ReceiveNotify(NotifyPacket notifyPacket, NetworkReader networkReader, int channelId) { int sequenceDistance = (int)sequencer.Distance(notifyPacket.Sequence, receiveSequence); // sequence is so far out of bounds we can't save, just kick him (or her!) if (Math.Abs(sequenceDistance) > WINDOW_SIZE) { connection?.Disconnect(); return; } // this message is old, we already received // a newer or duplicate packet. Discard it if (sequenceDistance <= 0) { return; } receiveSequence = notifyPacket.Sequence; if (sequenceDistance >= ACK_MASK_BITS) { receiveMask = 1; } else { receiveMask = (receiveMask << sequenceDistance) | 1; } AckPackets(notifyPacket.ReceiveSequence, notifyPacket.AckMask); int msgType = MessagePacker.UnpackId(networkReader); InvokeHandler(msgType, networkReader, channelId); if (Time.unscaledTime - lastNotifySentTime > NOTIFY_ACK_TIMEOUT) { SendNotify(new NotifyAck(), null, channelId); } }