internal virtual void Post(TcpFlags flags, uint ackno, uint seqno, uint length = 0, int retransmission = 0, bool timeout = false) { SegmentsContext segments = null; lock (this) { lock (this.SegmentsContexts) { segments = new SegmentsContext() { AcknowledgeNo = ackno, SequenceNo = seqno, Flags = flags, Length = length, Stopwatch = new Stopwatch(), Retransmission = retransmission, Pcb = this, Timeout = timeout, }; if (retransmission > 0) { long nackNo = segments.SequenceNo + segments.Length; if (this.SegmentsContexts.TryAdd(nackNo, segments)) { segments.Stopwatch.Start(); } } } } TcpFrame frame = segments.CreateFrame(this); this.Locator.Tcp.Output(frame); }
public TcpPcb(TcpFrame frame, ILayerLocator locator) { if (frame == null) { throw new ArgumentNullException(nameof(frame)); } this.Locator = locator ?? throw new ArgumentNullException(nameof(locator)); this.AcknowledgeNo = frame.AcknowledgeNo; this.SequenceNo = frame.SequenceNo; this.AddressFamily = frame.AddressFamily; this.Destination = frame.Destination; this.Source = frame.Source; this.Ttl = frame.Ttl; this.Aborted = false; this.Estableshed = false; this.SendBufferSize = frame.WindowSize; this.ReceiveBufferSize = frame.WindowSize; this.InputStream = new TcpInputStream(this); this.InputStream.Receive += (sender, e) => { uint ackNo = Convert.ToUInt32(e.SequenceNo + e.Payload.Length); uint seqNo = e.AcknowledgeNo; this.SequenceNo = ackNo; { this.Post(TcpFlags.TCP_ACK, ackNo, seqNo, 0); } this.OnMessage(e.Payload); }; }
public virtual void Output(TcpFrame frame) { IPFrame ip = ToIPFrame(frame); if (ip != null) { Locator.IPv4.Output(ip); } }
private void RST(TcpPcb pcb, TcpFrame frame) { uint seqno = frame.AcknowledgeNo; uint ackno = frame.SequenceNo + 1; pcb.State = TcpState.LAST_ACK; pcb.Post(TcpFlags.TCP_RST, ackno, seqno); ClosePCB(pcb, TcpState.CLOSED); }
public override bool Send(BufferSegment payload) { if (payload == null || payload.Length <= 0) { return(false); } bool sendto(BufferSegment buffer) { if (buffer == null || buffer.Length <= 0) { return(false); } SegmentsContext segments = null; lock (this) { lock (this.SegmentsContexts) { segments = new SegmentsContext() { AcknowledgeNo = this.SequenceNo, SequenceNo = this.AcknowledgeNo, Flags = TcpFlags.TCP_PSH | TcpFlags.TCP_ACK, Length = (uint)buffer.Length, Stopwatch = new Stopwatch(), Pcb = this, Retransmission = 5, Payload = payload, }; var ackNo = segments.SequenceNo + segments.Length; if (this.SegmentsContexts.TryAdd(ackNo, segments)) { segments.Stopwatch.Start(); this.AcknowledgeNo += segments.Length; } } } TcpFrame frame = segments.CreateFrame(this); this.Locator.Tcp.Output(frame); return(true); } foreach (BufferSegment buffer in Slices(payload)) { if (!sendto(buffer)) { return(false); } } return(true); }
public virtual void Input(TcpFrame frame) { if (frame == null || frame.Payload == null) { return; } if (frame.Payload.Length <= 0) { return; } lock (this.Frames) { if (frame.SequenceNo == this.Pcb.SequenceNo) { this.Pcb.SequenceNo = frame.SequenceNo + (uint)frame.Payload.Length; OnReceive(frame); var node = this.Frames.First; while (node != null) { TcpFrame f = node.Value; var current = node; node = current.Next; if (f.SequenceNo == this.Pcb.SequenceNo) { this.Frames.Remove(current); this.Pcb.SequenceNo = f.SequenceNo + (uint)f.Payload.Length; OnReceive(f); } } } else if (this.Frames.Count <= 0) { this.Frames.AddLast(frame); } else { var node = this.Frames.Last; if (frame.SequenceNo == node.Value.SequenceNo) { return; } else if (frame.SequenceNo > node.Value.SequenceNo) { this.Frames.AddLast(frame); } else { node = this.Frames.Last; while (node != null) { TcpFrame f = node.Value; if (f.SequenceNo == frame.SequenceNo) { return; } if (f.SequenceNo < frame.SequenceNo) { this.Frames.AddAfter(node, frame); break; } node = node.Previous; } if (node == null) { this.Frames.AddFirst(frame); } } } } }
protected virtual void OnReceive(TcpFrame frame) { this.Receive?.Invoke(this, frame); }
public static TcpFrame ParseFrame(IPFrame ip, bool checksum = true) { if (ip == null) { return(null); } TcpFrame frame = null; BufferSegment packet = ip.Payload; packet.UnsafeAddrOfPinnedArrayElement((p) => { tcp_hdr *tcphdr = (tcp_hdr *)p; if (tcphdr == null) { return; } int hdrlen_bytes = TCPH_HDRLEN_BYTES(tcphdr); if (hdrlen_bytes < TCP_HLEN || hdrlen_bytes > packet.Length) // 错误的数据报 { return; } int len = packet.Length - hdrlen_bytes; if (len < 0) { return; } TcpFlags flags = (TcpFlags)TCPH_FLAGS(tcphdr); if (checksum && tcphdr->chksum != 0) { uint pseudo_checksum = CheckSum.inet_chksum_pseudo((byte *)p.ToPointer(), (uint)ProtocolType.Tcp, (uint)packet.Length, ip.SourceAddressV4, ip.DestinationAddressV4); if (pseudo_checksum != 0) { return; } } long payload_offset = 0; fixed(byte *stream = packet.Buffer) { payload_offset = ((byte *)p + hdrlen_bytes) - stream; } BufferSegment message_data = new BufferSegment(packet.Buffer, unchecked ((int)payload_offset), len); BufferSegment options_data = null; int options_size = hdrlen_bytes - sizeof(tcp_hdr); if (options_size <= 0) { options_data = new BufferSegment(BufferSegment.Empty); } else { options_data = new BufferSegment(packet.Buffer, packet.Offset + sizeof(tcp_hdr), options_size); } frame = new TcpFrame(new IPEndPoint(ip.Source, CheckSum.ntohs(tcphdr->src)), new IPEndPoint(ip.Destination, CheckSum.ntohs(tcphdr->dest)), message_data) { Ttl = ip.Ttl, AcknowledgeNo = CheckSum.ntohl(tcphdr->ackno), SequenceNo = CheckSum.ntohl(tcphdr->seqno), WindowSize = CheckSum.ntohs(tcphdr->wnd), Flags = flags, SourceMacAddress = ip.SourceMacAddress, DestinationMacAddress = ip.DestinationMacAddress, Options = options_data, UrgentPointer = CheckSum.ntohs(tcphdr->urgp) }; }); return(frame); }
public static IPFrame ToIPFrame(TcpFrame frame) { if (frame == null) { throw new ArgumentNullException(nameof(frame)); } if (frame.AddressFamily != AddressFamily.InterNetwork) { throw new ArgumentNullException("TCP frames of this address family type are not supported."); } BufferSegment options_data = frame.Options; int options_size = options_data?.Length ?? 0; int payload_offset = sizeof(tcp_hdr) + options_size; int payload_size = frame.Payload?.Length ?? 0; byte[] message = new byte[payload_offset + payload_size]; fixed(byte *pinned = message) { tcp_hdr *tcphdr = (tcp_hdr *)pinned; tcphdr->dest = CheckSum.htons((ushort)frame.Destination.Port); tcphdr->src = CheckSum.htons((ushort)frame.Source.Port); tcphdr->seqno = CheckSum.htonl(frame.SequenceNo); tcphdr->ackno = CheckSum.htonl(frame.AcknowledgeNo); tcphdr->urgp = CheckSum.htons(frame.UrgentPointer); tcphdr->wnd = CheckSum.htons(frame.WindowSize); TCPH_HDRLEN_SET(tcphdr, payload_offset >> 2); TCPH_FLAGS_SET(tcphdr, (int)frame.Flags); if (options_size > 0) { IntPtr destination_options = (IntPtr)(pinned + sizeof(tcp_hdr)); Marshal.Copy(options_data.Buffer, options_data.Offset, destination_options, options_size); } if (payload_size > 0) { using (MemoryStream ms = new MemoryStream(message, payload_offset, payload_size)) { ms.Write(frame.Payload.Buffer, frame.Payload.Offset, payload_size); } } ushort pseudo_checksum = CheckSum.inet_chksum_pseudo(pinned, (uint)ProtocolType.Tcp, (uint)message.Length, IPFrame.GetAddressV4(frame.Source.Address), IPFrame.GetAddressV4(frame.Destination.Address)); if (pseudo_checksum == 0) { pseudo_checksum = 0xffff; } tcphdr->chksum = pseudo_checksum; } return(new IPFrame(ProtocolType.Tcp, frame.Source.Address, frame.Destination.Address, new BufferSegment(message)) { Ttl = frame.Ttl, SourceMacAddress = frame.SourceMacAddress, DestinationMacAddress = frame.DestinationMacAddress, }); }
public virtual void Input(TcpFrame frame) { string pcbKey = GetPcbKey(frame.Source, frame.Destination); TcpPcb pcb = null; lock (_pcbTable) { _pcbTable.TryGetValue(pcbKey, out pcb); if (pcb == null) { pcb = new TcpPcb(frame, this.Locator) { State = TcpState.SYN_RCVD }; if (0 == (frame.Flags & TcpFlags.TCP_SYN) || // 不接受此套接字则积极拒绝 !this.Locator.Sockets.BeginAccept(pcb)) { RST(pcb, frame); return; } _pcbTable.TryAdd(pcbKey, pcb); pcb.Open += (sender, e) => { if (!pcb.Estableshed) { pcb.Estableshed = true; var socket = this.Locator.Sockets.EndAccept(pcb); if (socket == null) { pcb.Close(); } else { pcb.OnOpen(e); } } }; pcb.Abort += (sender, e) => ClosePCB(sender as TcpPcb, TcpState.CLOSED); } } lock (pcb) { if (0 != (frame.Flags & TcpFlags.TCP_SYN)) { uint seqno = pcb.AcknowledgeNo++; uint ackno = ++pcb.SequenceNo; pcb.Post(TcpFlags.TCP_SYN | TcpFlags.TCP_ACK, ackno, seqno, 1, 3); } else if (0 != (frame.Flags & TcpFlags.TCP_RST) || 0 != (frame.Flags & (TcpFlags.TCP_CWR | TcpFlags.TCP_ECE | TcpFlags.TCP_UGR))) { RST(pcb, frame); } else { pcb.SendBufferSize = frame.WindowSize; if (0 != (frame.Flags & TcpFlags.TCP_ACK)) { pcb.Ack(frame.AcknowledgeNo); } if (0 != (frame.Flags & TcpFlags.TCP_PSH)) { uint pylen = (uint)frame.Payload.Length; uint seqno = frame.AcknowledgeNo; uint ackno = frame.SequenceNo + pylen; if (ackno >= pcb.SequenceNo) { pcb.InputStream.Input(frame); } else { pcb.Post(TcpFlags.TCP_ACK, ackno, seqno, 0); } } else if (0 != (frame.Flags & TcpFlags.TCP_FIN)) { uint seqno = frame.AcknowledgeNo; uint ackno = frame.SequenceNo + 1; pcb.Post(TcpFlags.TCP_ACK, ackno, seqno, 0); ClosePCB(pcb, TcpState.CLOSED); } } } }