⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp_send.c

📁 一款类linux的操作系统源码
💻 C
字号:
/* *  Roadrunner/pk *    Copyright (C) 1989-2002  Cornfed Systems, Inc. * *  The Roadrunner/pk operating system is free software; you can *  redistribute and/or modify it under the terms of the GNU General *  Public License, version 2, as published by the Free Software *  Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public *  License along with this program; if not, write to the Free *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, *  MA 02111-1307 USA * *  More information about the Roadrunner/pk operating system of *  which this file is a part is available on the World-Wide Web *  at: http://www.cornfed.com. * */#include <net/ether.h>#include <net/tcp.h>#if _DEBUG_TCP#include <stdio.h>#endif#include <stdlib.h>#include <sys/intr.h>#include <sys/timer.h>u_short cksum(void *buf, int len);#if _DEBUG_RETRvoid tcp_dump_retr(char *s, buf_t b);#endifstatic voidtcp_send_segment(char *s, tcb_t tcb, buf_t b,		 int iplen, ipaddr src, ipaddr dst){    etherhdr_t eh;    iphdr_t ih;    tcphdr_t th;    tcpiphdr_t ti;    eh = (etherhdr_t) bstart(b);    ih = (iphdr_t) eh->data;    th = (tcphdr_t) (((char *) ih) + sizeof(struct iphdr));    ti = (tcpiphdr_t) (((char *) th) - sizeof(struct ipovly));    /* Convert to network order */    th->sport = HS2NET(th->sport);    th->dport = HS2NET(th->dport);    th->seq = HL2NET(th->seq);    th->ack = HL2NET(th->ack);    th->win = HS2NET(th->win);    th->urp = HS2NET(th->urp);    /* Compute checksum */    ti->iv.src = HL2NET(src);    ti->iv.dst = HL2NET(dst);    ti->iv.zero = 0;    ti->iv.pr = IP_PROTOCOL_TCP;    ti->iv.len = HS2NET(iplen);    th->cksum = cksum(ti, sizeof(struct ipovly) + iplen);    /*     * Insert segment in retransmission queue unless it is an ACK with     * no data.  iplen is the size of the IP packet payload so subtracting     * off the size of the TCP hdr gives the data length.  Create a     * duplicate buffer descriptor that points to the segment and send     * it to the IP layer.     */    {	int datalen = iplen - sizeof(struct tcphdr);	if (datalen > 0 || th->flags & (TF_SYN | TF_FIN)) {	    buf_t h = balloc();	    b->blk->refcnt++;	    h->blk = b->blk;	    bstart(h) = bstart(b);	    blen(h) = blen(b);	    disable;	    benq(h, &(tcb->retr));	    enable;	}    }    /* Send the segment */    ip_send(b, iplen, IP_PROTOCOL_TCP, src, dst);}static voidtcp_retransmit(tcb_t tcb){    /* Resend the first segment in the retransmission queue */    if (tcb->retr.h != NULL) {	buf_t b, h;	etherhdr_t eh;	iphdr_t ih;	tcphdr_t th;	ipaddr dst, src;	int iplen;	b = tcb->retr.h;	eh = (etherhdr_t) bstart(b);	ih = (iphdr_t) eh->data;	th = (tcphdr_t) (((char *) ih) + sizeof(struct iphdr));	iplen = blen(b) - ETHER_HDR_LEN - IP_HLEN(ih);	src = NET2HL(ih->src);	dst = NET2HL(ih->dst);	h = balloc();	b->blk->refcnt++;	h->blk = b->blk;	bstart(h) = bstart(b);	blen(h) = blen(b);#if _DEBUG_RETR	tcp_dump_retr("tcp_retransmit", h);#endif	/* Send the segment */	ip_send(h, iplen, IP_PROTOCOL_TCP, src, dst);    }    /* Restart retransmission timer */    if (tcb->flags & TCPF_RETRANSMIT) {	struct timeval tv;	tv.tv_sec = TCP_RETRANSMIT_SEC;	tv.tv_usec = TCP_RETRANSMIT_USEC;	timer_start("tcp retransmit", &tv,		    (timer_func_t) tcp_retransmit, tcb);    }}voidtcp_send_syn(tcb_t tcb){    socket_t socket = tcb->socket;    buf_t b;    etherhdr_t eh;    iphdr_t ih;    tcphdr_t th;    b = _bget(ETHER_PKT_LEN);    if (b == NULL)	return;    blen(b) = ETHER_HDR_LEN + sizeof(struct iphdr) + sizeof(struct tcphdr);    eh = (etherhdr_t) bstart(b);    ih = (iphdr_t) eh->data;    th = (tcphdr_t) (((char *) ih) + sizeof(struct iphdr));    /* Format and send TCP segment header */    th->sport = socket->sport;    th->dport = socket->dport;    th->seq = tcb->snd_nxt++;    th->ack = tcb->rcv_nxt;    th->off = sizeof(struct tcphdr) << 2;    th->flags = TF_SYN;    if (tcb->state == TCPS_SYN_RECEIVED)	th->flags |= TF_ACK;    th->win = RCV_WND;    th->cksum = 0;    th->urp = th->seq;    tcp_send_segment("tcp_send_syn", tcb, b, sizeof(struct tcphdr),		     socket->src, socket->dst);}voidtcp_send_ack(tcb_t tcb){    socket_t socket = tcb->socket;    buf_t b;    etherhdr_t eh;    iphdr_t ih;    tcphdr_t th;    b = _bget(ETHER_PKT_LEN);    if (b == NULL)	return;    blen(b) = ETHER_HDR_LEN + sizeof(struct iphdr) + sizeof(struct tcphdr);    eh = (etherhdr_t) bstart(b);    ih = (iphdr_t) eh->data;    th = (tcphdr_t) (((char *) ih) + sizeof(struct iphdr));    /* Format TCP segment header */    th->sport = socket->sport;    th->dport = socket->dport;    th->seq = tcb->snd_nxt;    th->ack = tcb->rcv_nxt;    th->off = sizeof(struct tcphdr) << 2;    th->flags = TF_ACK;    th->win = tcb->rcv_wnd;    th->cksum = 0;    th->urp = th->seq;    tcp_send_segment("tcp_send_ack", tcb, b, sizeof(struct tcphdr),		     socket->src, socket->dst);}voidtcp_send_fin(tcb_t tcb){    socket_t socket = tcb->socket;    buf_t b;    etherhdr_t eh;    iphdr_t ih;    tcphdr_t th;    b = _bget(ETHER_PKT_LEN);    if (b == NULL)	return;    blen(b) = ETHER_HDR_LEN + sizeof(struct iphdr) + sizeof(struct tcphdr);    eh = (etherhdr_t) bstart(b);    ih = (iphdr_t) eh->data;    th = (tcphdr_t) (((char *) ih) + sizeof(struct iphdr));    /* Format TCP segment header */    th->sport = socket->sport;    th->dport = socket->dport;    th->seq = tcb->snd_nxt++;    th->ack = tcb->rcv_nxt;    th->off = sizeof(struct tcphdr) << 2;    th->flags = TF_FIN;    th->win = tcb->rcv_wnd;    th->cksum = 0;    th->urp = th->seq;    tcp_send_segment("tcp_send_fin", tcb, b, sizeof(struct tcphdr),		     socket->src, socket->dst);}voidtcp_send(tcb_t tcb){    socket_t socket = tcb->socket;    buf_t b;    etherhdr_t eh;    iphdr_t ih;    tcphdr_t th;    int bytecnt = 0, hdrlen, len;    hdrlen = ETHER_HDR_LEN + sizeof(struct iphdr) + sizeof(struct tcphdr);    for (;;) {	disable;	b = bdeq(&(tcb->socket->sndq));	enable;	if (b == NULL)	    break;	tcb->socket->snd_cc -= blen(b) - hdrlen;	eh = (etherhdr_t) bstart(b);	ih = (iphdr_t) eh->data;	th = (tcphdr_t) (((char *) ih) + sizeof(struct iphdr));	/* Format TCP segment header */	th->sport = socket->sport;	th->dport = socket->dport;	th->seq = tcb->snd_nxt;	tcb->snd_nxt += blen(b) - hdrlen;	th->ack = tcb->rcv_nxt;	th->off = sizeof(struct tcphdr) << 2;	th->flags = TF_ACK;	th->win = tcb->rcv_wnd;	th->cksum = 0;	th->urp = th->seq;	len = blen(b) - ETHER_HDR_LEN - sizeof(struct iphdr);	tcp_send_segment("tcp_send", tcb, b, len, socket->src, socket->dst);	bytecnt += len;    }    /* Set retransmission timer */    if (!(tcb->flags & TCPF_RETRANSMIT) && bytecnt > 0) {	struct timeval tv;	tv.tv_sec = TCP_RETRANSMIT_SEC;	tv.tv_usec = TCP_RETRANSMIT_USEC;	timer_start("tcp retransmit", &tv,		    (timer_func_t) tcp_retransmit, tcb);	tcb->flags |= TCPF_RETRANSMIT;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -