internal void copy_from(tcp_seg seg) { this.next = seg.next; this.p = seg.p; this.len = seg.len; #if TCP_OVERSIZE_DBGCHECK this.oversize_left = seg.oversize_left; #endif // TCP_OVERSIZE_DBGCHECK #if TCP_CHECKSUM_ON_COPY this.chksum = seg.chksum; this.chksum_swapped = seg.chksum_swapped; #endif // TCP_CHECKSUM_ON_COPY this.flags = seg.flags; this.tcphdr = seg.tcphdr; }
/* Define some copy-macros for checksum-on-copy so that the code looks nicer by preventing too many ifdef's. */ public static void TCP_DATA_COPY(pointer dst, pointer src, ushort len, tcp_seg seg) { do { tcp_seg_add_chksum(lwip.LWIP_CHKSUM_COPY(dst, src, len), len, ref seg.chksum, ref seg.chksum_swapped); seg.flags |= tcp_seg.TF_SEG_DATA_CHECKSUMMED; } while (false); }
/** * Called by tcp.tcp_output() to actually send a TCP segment over IP. * * @param seg the tcp_seg to send * @param pcb the tcp_pcb for the TCP connection used to send the segment */ private void tcp_output_segment(tcp_seg seg, tcp_pcb pcb) { ushort len; pointer opts; /** @bug Exclude retransmitted segments from this count. */ //snmp.snmp_inc_tcpoutsegs(); /* The TCP header has already been constructed, but the ackno and wnd fields remain. */ seg.tcphdr.ackno = lwip.lwip_htonl(pcb.rcv_nxt); /* advertise our receive window size in this TCP segment */ seg.tcphdr.wnd = lwip.lwip_htons(pcb.rcv_ann_wnd); pcb.rcv_ann_right_edge = pcb.rcv_nxt + pcb.rcv_ann_wnd; /* Add any requested options. NB MSS option is only set on SYN packets, so ignore it here */ opts = new pointer(seg.tcphdr.data, seg.tcphdr.offset + tcp_hdr.length); if ((seg.flags & tcp_seg.TF_SEG_OPTS_MSS) != 0) { ushort mss; #if TCP_CALCULATE_EFF_SEND_MSS mss = tcp_eff_send_mss(opt.TCP_MSS, pcb.remote_ip); #else // TCP_CALCULATE_EFF_SEND_MSS mss = opt.TCP_MSS; #endif // TCP_CALCULATE_EFF_SEND_MSS opts.SetValue(tcp_seg.TCP_BUILD_MSS_OPTION(mss)); opts += 1; } #if LWIP_TCP_TIMESTAMPS pcb.ts_lastacksent = pcb.rcv_nxt; if ((seg.flags & tcp_seg.TF_SEG_OPTS_TS) != 0) { tcp_build_timestamp_option(pcb, /*opts*/new pointer(seg.tcphdr.data, seg.tcphdr.offset + 1)); opts += 3; } #endif /* Set retransmission timer running if it is not currently enabled This must be set before checking the route. */ if (pcb.rtime == -1) { pcb.rtime = 0; } /* If we don't have a local IP address, we get one by calling ip.ip_route(). */ if (ip_addr.ip_addr_isany(pcb.local_ip)) { ip_addr.ip_addr_copy(pcb.local_ip, lwip.ip_addr); } if (pcb.rttest == 0) { pcb.rttest = tcp_ticks; pcb.rtseq = lwip.lwip_ntohl(seg.tcphdr.seqno); lwip.LWIP_DEBUGF(opt.TCP_RTO_DEBUG, "tcp_output_segment: rtseq {0}\n", pcb.rtseq); } lwip.LWIP_DEBUGF(opt.TCP_OUTPUT_DEBUG, "tcp_output_segment: {0}:{1}\n", lwip.lwip_htonl(seg.tcphdr.seqno), lwip.lwip_htonl(seg.tcphdr.seqno) + seg.len); len = (ushort)(seg.tcphdr - seg.p.payload); seg.p.len -= len; seg.p.tot_len -= len; seg.p.payload = seg.tcphdr; seg.tcphdr.chksum = 0; #if CHECKSUM_GEN_TCP #if TCP_CHECKSUM_ON_COPY { uint acc; #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK ushort chksum_slow = lwip.inet_chksum_pseudo(seg.p, pcb.local_ip, pcb.remote_ip, lwip.IP_PROTO_TCP, seg.p.tot_len); #endif // TCP_CHECKSUM_ON_COPY_SANITY_CHECK if ((seg.flags & tcp_seg.TF_SEG_DATA_CHECKSUMMED) == 0) { lwip.LWIP_ASSERT("data included but not checksummed", seg.p.tot_len == (tcp_hdr.TCPH_HDRLEN(seg.tcphdr) * 4)); } /* rebuild TCP header checksum (TCP header changes for retransmissions!) */ acc = lwip.inet_chksum_pseudo_partial(seg.p, pcb.local_ip, pcb.remote_ip, lwip.IP_PROTO_TCP, seg.p.tot_len, (ushort)(tcp_hdr.TCPH_HDRLEN(seg.tcphdr) * 4)); /* add payload checksum */ if (seg.chksum_swapped) { seg.chksum = lwip.SWAP_BYTES_IN_WORD(seg.chksum); seg.chksum_swapped = false; } acc += (ushort)~(seg.chksum); seg.tcphdr.chksum = (ushort)lwip.FOLD_U32T(acc); #if TCP_CHECKSUM_ON_COPY_SANITY_CHECK if (chksum_slow != seg.tcphdr.chksum) { lwip.LWIP_DEBUGF(opt.TCP_DEBUG | lwip.LWIP_DBG_LEVEL_WARNING, "tcp_output_segment: calculated checksum is {0} instead of {1:X}\n", seg.tcphdr.chksum, chksum_slow); seg.tcphdr.chksum = chksum_slow; } #endif // TCP_CHECKSUM_ON_COPY_SANITY_CHECK } #else // TCP_CHECKSUM_ON_COPY seg.tcphdr.chksum = lwip.inet_chksum_pseudo(seg.p, pcb.local_ip, pcb.remote_ip, lwip.IP_PROTO_TCP, seg.p.tot_len); #endif // TCP_CHECKSUM_ON_COPY #endif // CHECKSUM_GEN_TCP ++lwip.lwip_stats.tcp.xmit; #if LWIP_NETIF_HWADDRHINT lwip.ip_output_hinted(seg.p, pcb.local_ip, pcb.remote_ip, pcb.ttl, pcb.tos, lwip.IP_PROTO_TCP, pcb.addr_hint); #else // LWIP_NETIF_HWADDRHINT lwip.ip_output(seg.p, pcb.local_ip, pcb.remote_ip, pcb.ttl, pcb.tos, lwip.IP_PROTO_TCP); #endif // LWIP_NETIF_HWADDRHINT }
public static void TCP_DATA_COPY(pointer dst, pointer src, int len, tcp_seg seg) { opt.MEMCPY(dst, src, len); }
internal memp memp_malloc(memp_t type) { memp memp; switch (type) { #if LWIP_RAW case memp_t.MEMP_RAW_PCB: memp = new raw_pcb(this); break; #endif #if LWIP_UDP case memp_t.MEMP_UDP_PCB: memp = new udp_pcb(this); break; #endif #if LWIP_TCP case memp_t.MEMP_TCP_PCB: memp = new tcp_pcb(this); break; case memp_t.MEMP_TCP_PCB_LISTEN: memp = new tcp_pcb_listen(this); break; case memp_t.MEMP_TCP_SEG: memp = new tcp_seg(this); break; #endif #if IP_REASSEMBLY case memp_t.MEMP_REASSDATA: memp = new ip_reassdata(this); break; case memp_t.MEMP_FRAG_PBUF: memp = new frag_pbuf(this); break; #endif #if LWIP_NETCONN case memp_t.MEMP_NETBUF: memp = new netbuf(this); break; case memp_t.MEMP_NETCONN: memp = new netconn(this); break; #endif #if false //!NO_SYS case memp_t.MEMP_TCPIP_MSG_API: memp = new tcpip_msg(this); break; case memp_t.MEMP_TCPIP_MSG_INPKT: memp = new tcpip_msg(this); break; #endif #if LWIP_ARP && ARP_QUEUEING case memp_t.MEMP_ARP_QUEUE: memp = new etharp_q_entry(this); break; #endif #if LWIP_IGMP case memp_t.MEMP_IGMP_GROUP: memp = new igmp_group(this); break; #endif #if false //(!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) case memp_t.MEMP_SYS_TIMEOUT: memp = new sys_timeo(this); break; #endif #if LWIP_SNMP case memp_t.MEMP_SNMP_ROOTNODE: memp = new mib_list_rootnode(this); break; case memp_t.MEMP_SNMP_NODE: memp = new mib_list_node(this); break; case memp_t.MEMP_SNMP_VARBIND: memp = new snmp_varbind(this); break; case memp_t.MEMP_SNMP_VALUE: memp = new snmp_value(this); break; #endif #if LWIP_DNS && LWIP_SOCKET case memp_t.MEMP_NETDB: memp = new netdb(this); break; #endif #if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC case memp_t.MEMP_LOCALHOSTLIST: memp = new local_hostlist_entry(this); break; #endif #if PPP_SUPPORT && PPPOE_SUPPORT case memp_t.MEMP_PPPOE_IF: memp = new pppoe_softc(this); break; #endif default: throw new InvalidOperationException(); } memp._type = type; memp_heap.AddLast(memp); return memp; }
public static int TCP_TCPLEN(tcp_seg seg) { return seg.len + (((tcp_hdr.TCPH_FLAGS(seg.tcphdr) & (tcp.TCP_FIN | tcp.TCP_SYN)) != 0) ? 1 : 0); }
/** * Insert segment into the list (segments covered with new one will be deleted) * * Called from tcp_receive() */ private void tcp_oos_insert_segment(tcp_seg cseg, tcp_seg next) { tcp_seg old_seg; if ((tcp_hdr.TCPH_FLAGS(cseg.tcphdr) & tcp.TCP_FIN) != 0) { /* received segment overlaps all following segments */ tcp_segs_free(next); next = null; } else { /* delete some following segments oos queue may have segments with FIN flag */ while ((next != null) && TCP_SEQ_GEQ((seqno + cseg.len), (next.tcphdr.seqno + next.len))) { /* cseg with FIN already processed */ if ((tcp_hdr.TCPH_FLAGS(next.tcphdr) & tcp.TCP_FIN) != 0) { tcp_hdr.TCPH_SET_FLAG(cseg.tcphdr, tcp.TCP_FIN); } old_seg = next; next = next.next; tcp_seg_free(old_seg); } if ((next != null) && TCP_SEQ_GT(seqno + cseg.len, next.tcphdr.seqno)) { /* We need to trim the incoming segment. */ cseg.len = (ushort)(next.tcphdr.seqno - seqno); lwip.pbuf_realloc(cseg.p, cseg.len); } } cseg.next = next; }
public static int TCP_TCPLEN(tcp_seg seg) { return(seg.len + (((tcp_hdr.TCPH_FLAGS(seg.tcphdr) & (tcp.TCP_FIN | tcp.TCP_SYN)) != 0) ? 1 : 0)); }
internal memp memp_malloc(memp_t type) { memp memp; switch (type) { #if LWIP_RAW case memp_t.MEMP_RAW_PCB: memp = new raw_pcb(this); break; #endif #if LWIP_UDP case memp_t.MEMP_UDP_PCB: memp = new udp_pcb(this); break; #endif #if LWIP_TCP case memp_t.MEMP_TCP_PCB: memp = new tcp_pcb(this); break; case memp_t.MEMP_TCP_PCB_LISTEN: memp = new tcp_pcb_listen(this); break; case memp_t.MEMP_TCP_SEG: memp = new tcp_seg(this); break; #endif #if IP_REASSEMBLY case memp_t.MEMP_REASSDATA: memp = new ip_reassdata(this); break; case memp_t.MEMP_FRAG_PBUF: memp = new frag_pbuf(this); break; #endif #if LWIP_NETCONN case memp_t.MEMP_NETBUF: memp = new netbuf(this); break; case memp_t.MEMP_NETCONN: memp = new netconn(this); break; #endif #if false //!NO_SYS case memp_t.MEMP_TCPIP_MSG_API: memp = new tcpip_msg(this); break; case memp_t.MEMP_TCPIP_MSG_INPKT: memp = new tcpip_msg(this); break; #endif #if LWIP_ARP && ARP_QUEUEING case memp_t.MEMP_ARP_QUEUE: memp = new etharp_q_entry(this); break; #endif #if LWIP_IGMP case memp_t.MEMP_IGMP_GROUP: memp = new igmp_group(this); break; #endif #if false //(!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) case memp_t.MEMP_SYS_TIMEOUT: memp = new sys_timeo(this); break; #endif #if LWIP_SNMP case memp_t.MEMP_SNMP_ROOTNODE: memp = new mib_list_rootnode(this); break; case memp_t.MEMP_SNMP_NODE: memp = new mib_list_node(this); break; case memp_t.MEMP_SNMP_VARBIND: memp = new snmp_varbind(this); break; case memp_t.MEMP_SNMP_VALUE: memp = new snmp_value(this); break; #endif #if LWIP_DNS && LWIP_SOCKET case memp_t.MEMP_NETDB: memp = new netdb(this); break; #endif #if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC case memp_t.MEMP_LOCALHOSTLIST: memp = new local_hostlist_entry(this); break; #endif #if PPP_SUPPORT && PPPOE_SUPPORT case memp_t.MEMP_PPPOE_IF: memp = new pppoe_softc(this); break; #endif default: throw new InvalidOperationException(); } memp._type = type; memp_heap.AddLast(memp); return(memp); }
public tcp(lwip lwip) { this.lwip = lwip; inseg = new tcp_seg(lwip); tcp_pcb_lists = new tcp_pcb_common[]{ tcp_listen_pcbs.pcbs, tcp_bound_pcbs, tcp_active_pcbs, tcp_tw_pcbs}; }