/// <summary> /// Processes incomming initial packet and creates or halts a connection. /// </summary> /// <param name="packet">Initial Packet</param> /// <param name="endPoint">Peer's endpoint</param> /// <returns></returns> private QuicConnection ProcessInitialPacket(Packet packet, IPEndPoint endPoint) { QuicConnection result = null; byte[] data; // Unsupported version. Version negotiation packet is sent only on initial connection. All other packets are dropped. (5.2.2 / 16th draft) if (packet.Version != QuicVersion.CurrentVersion || !QuicVersion.SupportedVersions.Contains(packet.Version)) { var vnp = _packetCreator.CreateVersionNegotiationPacket(); data = vnp.Encode(); _client.Send(data, data.Length, endPoint); return(null); } if (!(packet is InitialPacket cast)) { throw new ArgumentNullException(nameof(cast)); } var ip = _packetCreator.CreateInitialPacket(0, cast.SourceConnectionId); // Protocol violation if the initial packet is smaller than the PMTU. (pt. 14 / 16th draft) if (cast.Encode().Length < QuicSettings.Pmtu) { ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.PROTOCOL_VIOLATION, "PMTU have not been reached.")); } else if (ConnectionPool.AddConnection(new ConnectionData(_pwt, cast.SourceConnectionId, 0), out var availableConnectionId)) { // Tell the peer the available connection id ip.SourceConnectionId = (byte)availableConnectionId; // We're including the maximum possible stream id during the connection handshake. (4.5 / 16th draft) ip.AttachFrame(new MaxStreamsFrame(QuicSettings.MaximumStreamId, StreamType.ServerBidirectional)); // Set the return result result = ConnectionPool.Find(availableConnectionId); } else { // Not accepting connections. Send initial packet with CONNECTION_CLOSE frame. // TODO: Buffering. The server might buffer incomming 0-RTT packets in anticipation of late delivery InitialPacket. // Maximum buffer size should be set in QuicSettings. ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.SERVER_BUSY, "The server is too busy to process your request.")); } data = ip.Encode(); var dataSent = _client.Send(data, data.Length, endPoint); if (dataSent > 0) { return(result); } return(null); }
/// <summary> /// Processes incomming initial packet and creates or halts a connection. /// </summary> /// <param name="packet">Initial Packet</param> /// <param name="endPoint">Peer's endpoint</param> /// <returns></returns> private QuicConnection ProcessInitialPacket(Packet packet, IPEndPoint endPoint) { QuicConnection result = null; UInt64 availableConnectionId; byte[] data; // Unsupported version. Version negotiation packet is sent only on initial connection. All other packets are dropped. (5.2.2 / 16th draft) if (packet.Version != QuicVersion.CurrentVersion || !QuicVersion.SupportedVersions.Contains(packet.Version)) { VersionNegotiationPacket vnp = _packetCreator.CreateVersionNegotiationPacket(); data = vnp.Encode(); _client.Send(data, data.Length, endPoint); return(null); } InitialPacket cast = packet as InitialPacket; InitialPacket ip = _packetCreator.CreateInitialPacket(0, cast.SourceConnectionId); // Protocol violation if the initial packet is smaller than the PMTU. (pt. 14 / 16th draft) if (cast.Encode().Length < QuicSettings.PMTU) { ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.PROTOCOL_VIOLATION, 0x00, ErrorConstants.PMTUNotReached)); } else if (ConnectionPool.AddConnection(new ConnectionData(new PacketWireTransfer(_client, endPoint), cast.SourceConnectionId, 0), out availableConnectionId) == true) { // Tell the peer the available connection id ip.SourceConnectionId = (byte)availableConnectionId; // We're including the maximum possible stream id during the connection handshake. (4.5 / 16th draft) ip.AttachFrame(new MaxStreamsFrame(QuicSettings.MaximumStreamId, StreamType.ServerBidirectional)); // Set the return result result = ConnectionPool.Find(availableConnectionId); } else { // Not accepting connections. Send initial packet with CONNECTION_CLOSE frame. // TODO: Buffering. The server might buffer incomming 0-RTT packets in anticipation of late delivery InitialPacket. // Maximum buffer size should be set in QuicSettings. ip.AttachFrame(new ConnectionCloseFrame(ErrorCode.CONNECTION_REFUSED, 0x00, ErrorConstants.ServerTooBusy)); } data = ip.Encode(); int dataSent = _client.Send(data, data.Length, endPoint); if (dataSent > 0) { return(result); } return(null); }
private void ProcessShortHeaderPacket(Packet packet) { ShortHeaderPacket shp = (ShortHeaderPacket)packet; QuicConnection connection = ConnectionPool.Find(shp.DestinationConnectionId); if (connection == null) { return; // TODO: Figure out if the packet should be discarded in that case? } connection.ProcessFrames(shp.GetFrames()); }
/// <summary> /// Processes short header packet, by distributing the frames towards connections. /// </summary> /// <param name="packet"></param> private void ProcessShortHeaderPacket(Packet packet) { ShortHeaderPacket shp = (ShortHeaderPacket)packet; QuicConnection connection = ConnectionPool.Find(shp.DestinationConnectionId); // No suitable connection found. Discard the packet. if (connection == null) { return; } connection.ProcessFrames(shp.GetFrames()); }