📄 tcp_out.c
字号:
seg = pcb->unsent;
/* useg should point to last segment on unacked queue */
useg = pcb->unacked;
if (useg != NULL)
{
for (; useg->next != NULL; useg = useg->next);
}
/* If the TF_ACK_NOW flag is set, we check if there is data that is
to be sent. If data is to be sent out, we'll just piggyback our
acknowledgement with the outgoing segment. If no data will be
sent (either because the ->unsent queue is empty or because the
window doesn't allow it) we'll have to construct an empty ACK
segment and send it. */
if (pcb->flags & TF_ACK_NOW &&(seg == NULL || ntohl(seg->tcphdr->seqno)
- pcb->lastack + seg->len > wnd))
{
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if (p == NULL)
{
return ERR_BUF;
}
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt);
tcphdr->ackno = htonl(pcb->rcv_nxt);
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->dest_ip),
TCP, p->tot_len);
///////////////////////////////////////////////////////////////////
if(alloc_skb(&skb,ETH_FRAME_LEN)==-1)
{
return ERR_BUF;
}
ip_skb_reserve(&skb);
DesData=(Uint8 *)skb_put(&skb,p->len);
memcpy(DesData,p->payload,p->len);
if(ip_send(&skb,ntohl(pcb->dest_ip), TCP)==-1)
{
free_skb(&skb);
}
////////////////////////////////////////////////////////////////
/*需要改
ip_output(p, (struct ip_addr *)&(pcb->local_ip), (struct ip_addr *)&(pcb->dest_ip), pcb->ttl, pcb->tos,
TCP);
*/
pbuf_free(p);
return ERR_OK;
}
while (seg != NULL &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd)
{
pcb->unsent = seg->next;
if (pcb->state != SYN_SENT)
{
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
tcp_output_segment(seg, pcb);
pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt))
{
pcb->snd_max = pcb->snd_nxt;
}
/* put segment on unacknowledged list if length > 0 */
if (TCP_TCPLEN(seg) > 0)
{
seg->next = NULL;
if (pcb->unacked == NULL)
{
pcb->unacked = seg;
useg = seg;
}
else
{
useg->next = seg;
useg = useg->next;
}
}
else
{
tcp_seg_free(seg);
}
seg = pcb->unsent;
}
return ERR_OK;
}
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
{
u16_t len;
struct netif *netif;
struct sk_buff skb;
Uint8 *DesData;
/* The TCP header has already been constructed, but the ackno and
wnd fields remain. */
seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
/* silly window avoidance */
if (pcb->rcv_wnd < pcb->mss)
{
seg->tcphdr->wnd = 0;
}
else
{
/* advertise our receive window size in this TCP segment */
seg->tcphdr->wnd = htons(pcb->rcv_wnd);
}
/* If we don't have a local IP address, we get one by
calling ip_route(). */
if (ip_addr_isany((struct ip_addr *)&(pcb->local_ip)))
{
/* 需要修改
netif = ip_route(&(pcb->dest_ip));
*/
if (netif == NULL)
{
return;
}
ip_addr_set((struct ip_addr *)&(pcb->local_ip), (struct ip_addr *)&(netif->ip_addr));
}
pcb->rtime = 0;
if (pcb->rttest == 0)
{
pcb->rttest = tcp_ticks;
pcb->rtseq = ntohl(seg->tcphdr->seqno);
}
len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
seg->p->len -= len;
seg->p->tot_len -= len;
seg->p->payload = seg->tcphdr;
seg->tcphdr->chksum = 0;
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
&(pcb->local_ip),
&(pcb->dest_ip),
TCP, seg->p->tot_len);
TCP_STATS_INC(tcp.xmit);
///////////////////////////////////////////////////////////////////
if(alloc_skb(&skb,ETH_FRAME_LEN)==-1)
{
return ;
}
ip_skb_reserve(&skb);
DesData=(Uint8 *)skb_put(&skb,seg->p->len);
memcpy(DesData,seg->p->payload,seg->p->len);
if(ip_send(&skb,ntohl(pcb->dest_ip), TCP)==-1)
{
free_skb(&skb);
}
////////////////////////////////////////////////////////////////
/*修要修改
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
*/
}
void tcp_rst(u32_t seqno, u32_t ackno,
u32_t local_ip, u32_t remote_ip,
u16_t local_port, u16_t remote_port)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
struct sk_buff skb;
Uint8 *DesData;
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if (p == NULL)
{
return;
}
tcphdr = p->payload;
tcphdr->src = htons(local_port);
tcphdr->dest = htons(remote_port);
tcphdr->seqno = htonl(seqno);
tcphdr->ackno = htonl(ackno);
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
tcphdr->wnd = htons(TCP_WND);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
// tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
// TCP, p->tot_len);
TCP_STATS_INC(tcp.xmit);
/* Send output with hardcoded TTL since we have no access to the pcb */
///////////////////////////////////////////////////////////////////
if(alloc_skb(&skb,ETH_FRAME_LEN)==-1)
{
return ;
}
ip_skb_reserve(&skb);
DesData=(Uint8 *)skb_put(&skb,p->len);
memcpy(DesData,p->payload,p->len);
if(ip_send(&skb,ntohl(remote_ip), TCP)==-1)
{
free_skb(&skb);
}
////////////////////////////////////////////////////////////////
/*需要修改
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
*/
pbuf_free(p);
}
void tcp_rexmit(struct tcp_pcb *pcb)
{
struct tcp_seg *seg;
if (pcb->unacked == NULL) {
return;
}
/* Move the first unacked segment to the unsent queue */
seg = pcb->unacked->next;
pcb->unacked->next = pcb->unsent;
pcb->unsent = pcb->unacked;
pcb->unacked = seg;
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
++pcb->nrtx;
/* Don't take any rtt measurements after retransmitting. */
pcb->rttest = 0;
/* Do the actual retransmission. */
tcp_output(pcb);
}
void tcp_keepalive(struct tcp_pcb *pcb)
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
struct sk_buff skb;
Uint8 *DesData;
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if(p == NULL)
{
return;
}
tcphdr = p->payload;
tcphdr->src = htons(pcb->local_port);
tcphdr->dest = htons(pcb->remote_port);
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
tcphdr->ackno = htonl(pcb->rcv_nxt);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->dest_ip, TCP, p->tot_len);
TCP_STATS_INC(tcp.xmit);
///////////////////////////////////////////////////////////////////
if(alloc_skb(&skb,ETH_FRAME_LEN)==-1)
{
return ;
}
ip_skb_reserve(&skb);
DesData=(Uint8 *)skb_put(&skb,p->len);
memcpy(DesData,p->payload,p->len);
if(ip_send(&skb,ntohl(pcb->dest_ip), TCP)==-1)
{
free_skb(&skb);
}
////////////////////////////////////////////////////////////////
/* Send output to IP */
/*修要修改
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
*/
pbuf_free(p);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -