/// <summary> /// Write out a handshake response. Mutate this writer to represent the position after the write. /// </summary> /// <returns>A copy of this writer (after the write has been applied)</returns> public PacketWriter WriteHandshakeResponse <TPeer>(uint session, ushort clientId, [NotNull] ClientIdCollection idMap, [NotNull] Dictionary <string, List <ClientInfo <TPeer> > > peersByRoom) { if (idMap == null) { throw new ArgumentNullException("idMap"); } if (peersByRoom == null) { throw new ArgumentNullException("peersByRoom"); } WriteMagic(); Write((byte)MessageTypes.HandshakeResponse); Write(session); //Assigned ID for this client Write(clientId); //Write ID map for all clients idMap.Serialize(ref this); //Room names list Write((ushort)peersByRoom.Count); foreach (var item in peersByRoom) { Write(item.Key); } //Channel count Write((ushort)peersByRoom.Count); //Write out list of peers in each channel (ugly enumerator instead of foreach because this doesn't box) using (var enumerator = peersByRoom.GetEnumerator()) { while (enumerator.MoveNext()) { var channel = enumerator.Current.Key.ToRoomId(); var peers = enumerator.Current.Value; Write((ushort)channel); //Write length prefixed list of peer IDs Write((byte)peers.Count); for (var i = 0; i < peers.Count; i++) { Write(peers[i].PlayerId); } } } return(this); }
/// <summary> /// Read the handshake response. Will totally overwrite the contents of outputRoomsToPeerId with a new state /// </summary> /// <param name="idMap"></param> /// <param name="outputRoomsToPeerId"></param> public void ReadHandshakeResponseBody([NotNull] ClientIdCollection idMap, [NotNull] Dictionary <string, List <ushort> > outputRoomsToPeerId) { if (idMap == null) { throw new ArgumentNullException("idMap"); } if (outputRoomsToPeerId == null) { throw new ArgumentNullException("outputRoomsToPeerId"); } //Read ID map for all clients idMap.Deserialize(ref this); // Read room name list, later in the packet we'll refer to rooms by their ID and we can look up their name in this list. // Only the name is in the packet, we can work out the ID locally. var roomNamesById = new Dictionary <ushort, string>(); var roomNameCount = ReadUInt16(); for (var i = 0; i < roomNameCount; i++) { var name = ReadString(); if (!Log.AssertAndLogWarn(name != null, "Read a null room name in handshake packet (potentially corrupt packet)")) { roomNamesById[name.ToRoomId()] = name; } } //Clear all the lists using (var enumerator = outputRoomsToPeerId.GetEnumerator()) while (enumerator.MoveNext()) { enumerator.Current.Value.Clear(); } //Read out lists per channel var channelCount = ReadUInt16(); for (var i = 0; i < channelCount; i++) { var channel = ReadUInt16(); var peerCount = ReadByte(); //Find room name string room; Log.AssertAndThrowPossibleBug(roomNamesById.TryGetValue(channel, out room), "C8E9EBED-2A46-4207-A050-0ABFE00BA9E8", "Could not find room name in handshake for ID:{0}", channel); //Get or create a list for this channel List <ushort> peers; if (!outputRoomsToPeerId.TryGetValue(room, out peers)) { peers = new List <ushort>(); outputRoomsToPeerId[room] = peers; } //Read out all the peers for this chanel for (var j = 0; j < peerCount; j++) { peers.Add(ReadUInt16()); } } }