Example #1
0
        public TcpConnection(Ethernet ethHeader,
                             IPv4 ipHeader,
                             Network.Header.Tcp tcpHeader,
                             TTransmitter packetTransmitter,
                             PipeScheduler readScheduler,
                             PipeScheduler writeScheduler,
                             MemoryPool <byte> memoryPool,
                             IConnectionDispatcher connectionDispatcher)
        {
            _packetTransmitter      = packetTransmitter;
            _connectionDispatcher   = connectionDispatcher;
            _remoteAddress          = ipHeader.SourceAddress;
            _localAddress           = ipHeader.DestinationAddress;
            _outboundEthernetHeader = new Ethernet()
            {
                Destination = ethHeader.Source, Ethertype = EtherType.IPv4, Source = ethHeader.Destination
            };
            var pseudo = new TcpV4PseudoHeader()
            {
                Destination = _remoteAddress, Source = _localAddress, ProtocolNumber = Internet.Ip.ProtocolNumber.Tcp, Reserved = 0
            };

            _pseudoPartialSum = Checksum.PartialCalculate(ref Unsafe.As <TcpV4PseudoHeader, byte>(ref pseudo), Unsafe.SizeOf <TcpV4PseudoHeader>());

            LocalAddress  = new System.Net.IPAddress(_localAddress.Address);
            RemoteAddress = new System.Net.IPAddress(_remoteAddress.Address);
            RemotePort    = tcpHeader.SourcePort;
            LocalPort     = tcpHeader.DestinationPort;

            OutputReaderScheduler = readScheduler ?? throw new ArgumentNullException(nameof(readScheduler));
            InputWriterScheduler  = writeScheduler ?? throw new ArgumentNullException(nameof(writeScheduler));
            MemoryPool            = memoryPool ?? throw new ArgumentNullException(nameof(memoryPool));

            ConnectionClosed = _closedToken.Token;
        }
Example #2
0
        public void ProcessPacket(TcpHeaderWithOptions header, ReadOnlySpan <byte> data)
        {
            // If there is backpressure just drop the packet
            if (!_flushTask.IsCompleted)
            {
                return;
            }

            _echoTimestamp = header.TimeStamp;
            switch (_state)
            {
            case TcpConnectionState.Listen:
                _maxSegmentSize        = header.MaximumSegmentSize <= 50 || header.MaximumSegmentSize > 1460 ? 1460 : header.MaximumSegmentSize;
                _sendSequenceNumber    = GetRandomSequenceStart();
                _receiveSequenceNumber = header.Header.SequenceNumber;
                // We know we checked for syn in the upper layer so we can ignore that for now
                _partialTcpHeader = Network.Header.Tcp.Create((ushort)LocalPort, (ushort)RemotePort);
                WriteSyncAckPacket();
                _state = TcpConnectionState.Syn_Rcvd;
                break;

            case TcpConnectionState.Syn_Rcvd:
                if (header.Header.SYN)
                {
                    //Console.WriteLine("Another Syn made");
                    return;
                }
                _connectionDispatcher.OnConnection(this);
                var ignore = TransmitLoop();
                _state = TcpConnectionState.Established;
                break;

            case TcpConnectionState.Established:
                if (header.Header.FIN)
                {
                    _receiveSequenceNumber++;
                    _state = TcpConnectionState.Fin_Wait_1;
                    return;
                }
                if (header.Header.RST)
                {
                    //Console.WriteLine("Got RST Should shut down!");
                    return;
                }

                // First lets update our acked squence number;
                _sendAckSequenceNumber = header.Header.AcknowledgmentNumber;

                if (_receiveSequenceNumber != header.Header.SequenceNumber)
                {
                    // We are just going to drop this and wait for a resend
                    return;
                }
                unchecked { _receiveSequenceNumber += (uint)data.Length; }
                var output = Input.GetMemory(data.Length);
                data.CopyTo(output.Span);
                Input.Advance(data.Length);
                // need to do something with the task and make sure we don't overlap the writes
                var task = Input.FlushAsync();
                if (!task.IsCompleted)
                {
                    _flushTask = task.AsTask();
                }
                PendingAck          = true;
                _totalBytesWritten += data.Length;
                break;

            case TcpConnectionState.Fin_Wait_1:
            case TcpConnectionState.Fin_Wait_2:
                break;

            default:
                throw new NotImplementedException($"Unknown tcp state?? {_state}");
            }
        }
Example #3
0
 public TcpConnection(Ethernet ethHeader, IPv4 ipHeader, Network.Header.Tcp tcpHeader, TTransmitter packetTransmitter, IConnectionDispatcher connectionDispatcher)
     : this(ethHeader, ipHeader, tcpHeader, packetTransmitter, PipeScheduler.ThreadPool, PipeScheduler.ThreadPool, MemoryPool <byte> .Shared, connectionDispatcher)
 {
 }