static void ParseShouldSucceed(string text) { Assert.IsTrue(IPv4EndPoint.TryParse(text, out IPv4EndPoint actual)); IPEndPoint expected = IPEndPoint.Parse(text); Assert.AreEqual(expected, actual); Assert.AreEqual(expected.ToString(), actual.ToString()); }
internal TCPConnection(IPv4Address remoteIP, UInt16 remotePort, IPv4Address localIP, UInt16 localPort, UInt32 initialSeqNumber, State initialState) { this.remoteEndpoint = new IPv4EndPoint(remoteIP, remotePort); this.localEndpoint = new IPv4EndPoint(localIP, localPort); this.remoteSeqNumber = initialSeqNumber; this.localSeqNumber = 0x3040; this.state = initialState; // TODO: have socket be a hash key we can use to find connections quickly this.socket = remotePort; }
private async void MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) { try { // accessing the properties of args seems to throw exceptions if (args.RemoteAddress.Type != HostNameType.Ipv4) { // TODO support other types once the rest of Falcon does Log(LogLevel.Warning, String.Format("Dropped Message - Remote peer: {0} unsupported type: {1}.", args.RemoteAddress.RawName, args.RemoteAddress.Type)); return; } if (args.RemoteAddress.RawName.StartsWith("127.") && args.RemotePort == localPortAsString) { Log(LogLevel.Warning, "Dropped Message received from self."); return; } IPv4EndPoint lastRemoteEndPoint = new IPv4EndPoint(args.RemoteAddress.RawName, args.RemotePort); // careful todo this within the lock so doesn't get re-assigned while we are using it DataReader dr = args.GetDataReader(); int size = (int)dr.UnconsumedBufferLength; if (size == 0) { // peer has closed TryRemovePeer(lastRemoteEndPoint); return; } else if (size < Const.NORMAL_HEADER_SIZE || size > Const.MAX_DATAGRAM_SIZE) { Log(LogLevel.Error, String.Format("Message dropped from peer: {0}, bad size: {0}", lastRemoteEndPoint, size)); return; } byte seq = dr.ReadByte(); byte packetInfo = dr.ReadByte(); // parse packet info byte HeaderPayloadSizeType hpst = (HeaderPayloadSizeType)(packetInfo & Const.PAYLOAD_SIZE_TYPE_MASK); SendOptions opts = (SendOptions)(packetInfo & Const.SEND_OPTS_MASK); PacketType type = (PacketType)(packetInfo & Const.PACKET_TYPE_MASK); // check the header makes sense if (!Enum.IsDefined(Const.HEADER_PAYLOAD_SIZE_TYPE_TYPE, hpst) || !Enum.IsDefined(Const.SEND_OPTIONS_TYPE, opts) || !Enum.IsDefined(Const.PACKET_TYPE_TYPE, type)) { Log(LogLevel.Warning, String.Format("Message dropped from peer: {0}, bad header.", lastRemoteEndPoint)); return; } // parse payload size int payloadSize; if (hpst == HeaderPayloadSizeType.Byte) { payloadSize = dr.ReadByte(); } else { if (size < Const.LARGE_HEADER_SIZE) { Log(LogLevel.Error, String.Format("Message with large header dropped from peer: {0}, size: {1}.", lastRemoteEndPoint, size)); return; } payloadSizeBytes[0] = dr.ReadByte(); payloadSizeBytes[1] = dr.ReadByte(); payloadSize = BitConverter.ToUInt16(payloadSizeBytes, 0); } // validate payload size if (payloadSize != dr.UnconsumedBufferLength) { Log(LogLevel.Error, String.Format("Message dropped from peer: {0}, payload size: {1}, not as specefied: {2}", lastRemoteEndPoint, dr.UnconsumedBufferLength, payloadSize)); return; } // copy the payload byte[] payload = null; if (payloadSize > 0) { payload = new byte[payloadSize]; dr.ReadBytes(payload); } RemotePeer rp; if (!peersByIp.TryGetValue(lastRemoteEndPoint, out rp)) { // Could be the peer has not been added yet and is requesting to be added. // Or it could be we are asking to be added and peer is accepting! if (type == PacketType.AddPeer) { string pass = null; if (payloadSize > 0) pass = Settings.TextEncoding.GetString(payload, 0, payloadSize); if (pass != networkPass) // TODO something else? { // TODO send reject and reason Log(LogLevel.Info, String.Format("Join request dropped from peer: {0}, bad pass.", lastRemoteEndPoint)); } else if (peersByIp.ContainsKey(lastRemoteEndPoint)) { // TODO send reject and reason Log(LogLevel.Warning, String.Format("Join request dropped from peer: {0}, peer is already added!", lastRemoteEndPoint)); } else { rp = await TryAddPeerAsync(lastRemoteEndPoint); if(rp != null) rp.BeginSend(SendOptions.Reliable, PacketType.AcceptJoin, null, null); } } else if (type == PacketType.AcceptJoin) { AwaitingAcceptDetail detail; if (!TryGetAndRemoveWaitingAcceptDetail(lastRemoteEndPoint, out detail)) { // Possible reasons we do not have detail are: // 1) Accept is too late, // 2) Accept duplicated and we have already removed it, or // 3) Accept was unsolicited. Log(LogLevel.Warning, String.Format("Accept dropped from peer: {0}, join request not found.", lastRemoteEndPoint)); } else { // create the new peer, add the datagram to send ACK, call the callback rp = await TryAddPeerAsync(lastRemoteEndPoint); if (rp != null) { rp.AddReceivedPacket(seq, opts, type, payload); TryResult tr = new TryResult(true, null, null, rp.Id); detail.Callback(tr); } } } else { Log(LogLevel.Warning, String.Format("Message dropped from peer: {0}, peer unknown.", lastRemoteEndPoint)); } } else { rp.AddReceivedPacket(seq, opts, type, payload); } } catch (Exception ex) { Log(LogLevel.Error, String.Format("Exception in MessageReceived handler: {0}.", ex.Message)); } }