📄 tcp.c
字号:
ip_header_t *ip = pkt->ip_hdr; tcp_socket_t *prev,*s; dword ack; int queued = 0; /* set length for pseudo sum calculation */ ip->length = htons(pkt->pkt_bytes); if (__sum((word *)tcp, pkt->pkt_bytes, __pseudo_sum(ip)) == 0) { for (prev = NULL, s = tcp_list; s; prev = s, s = s->next) { if (s->our_port == ntohs(tcp->dest_port)) { if (s->his_port == 0) break; if (s->his_port == ntohs(tcp->src_port) && !memcmp(r->ip_addr, s->his_addr.ip_addr, sizeof(ip_addr_t))) break; } } if (s) { /* found the socket this packet belongs to */ /* refresh his ethernet address */ memcpy(s->his_addr.enet_addr, r->enet_addr, sizeof(enet_addr_t)); if (s->state != _SYN_RCVD && tcp->flags & TCP_FLAG_RST) { BSPLOG(bsp_log("TCP_FLAG_RST rcvd\n")); do_reset(s); __pktbuf_free(pkt); return; } switch (s->state) { case _SYN_SENT: /* active open not supported */ break; case _LISTEN: if (tcp->flags & TCP_FLAG_SYN) { s->state = _SYN_RCVD; s->ack = ntohl(tcp->seqnum) + 1; s->his_port = ntohs(tcp->src_port); memcpy(s->his_addr.ip_addr, r->ip_addr, sizeof(ip_addr_t)); s->data_bytes = 0; s->ack_pending = 0; BSPLOG(bsp_log("SYN from %d.%d.%d.%d:%d (seq %x)\n", s->his_addr.ip_addr[0],s->his_addr.ip_addr[1], s->his_addr.ip_addr[2],s->his_addr.ip_addr[3], s->his_port, ntohl(tcp->seqnum))); tcp_send(s, TCP_FLAG_SYN | TCP_FLAG_ACK, 0); } else send_reset(pkt, r); break; case _SYN_RCVD: BSPLOG(bsp_log("_SYN_RCVD timer cancel.\n")); __timer_cancel(&s->timer); /* go back to _LISTEN state if reset */ if (tcp->flags & TCP_FLAG_RST) { s->state = _LISTEN; BSPLOG(bsp_log("_SYN_RCVD --> _LISTEN\n")); } else if (tcp->flags & TCP_FLAG_SYN) { /* apparently our SYN/ACK was lost? */ tcp_send(s, 0, 1); BSPLOG(bsp_log("retransmitting SYN/ACK\n")); } else if ((tcp->flags & TCP_FLAG_ACK) && ntohl(tcp->acknum) == (s->seq + 1)) { /* we've established the connection */ s->state = _ESTABLISHED; s->seq++; BSPLOG(bsp_log("ACK received - connection established\n")); } break; case _ESTABLISHED: case _CLOSE_WAIT: ack = s->ack; /* save original ack */ if (tcp->flags & TCP_FLAG_ACK) handle_ack(s, pkt); queued = handle_data(s, pkt); if ((tcp->flags & TCP_FLAG_FIN) && ntohl(tcp->seqnum) == s->ack) { BSPLOG(bsp_log("FIN received - going to _CLOSE_WAIT\n")); s->ack++; s->state = _CLOSE_WAIT; } /* * Send an ack if neccessary. */ if (s->ack != ack || s->ack_pending) { /* * we can't send an ack if our write packet is holding outgoing * data pending an incoming ack. */ if (s->data_bytes == 0) { BSPLOG(bsp_log("Sending ack: new[%x] old[%x]\n", s->ack, ack)); __timer_cancel(&s->timer); tcp_send(s, TCP_FLAG_ACK, 0); s->ack_pending = 0; } else s->ack_pending = 1; } break; case _LAST_ACK: if (tcp->flags & TCP_FLAG_ACK) { handle_ack(s, pkt); if (ntohl(tcp->acknum) == (s->seq + 1)) { BSPLOG(bsp_log("_LAST_ACK --> _CLOSED\n")); s->state = _CLOSED; unlink_socket(s); } } break; case _FIN_WAIT_1: if (tcp->flags & TCP_FLAG_ACK) { handle_ack(s, pkt); if (ntohl(tcp->acknum) == (s->seq + 1)) { /* got ACK for FIN packet */ if (tcp->flags & TCP_FLAG_FIN) { BSPLOG(bsp_log("_FIN_WAIT_1 --> _TIME_WAIT\n")); s->ack++; s->state = _TIME_WAIT; tcp_send(s, TCP_FLAG_ACK, 0); } else { s->state = _FIN_WAIT_2; BSPLOG(bsp_log("_FIN_WAIT_1 --> _FIN_WAIT_2\n")); } } } if (tcp->flags & TCP_FLAG_FIN) { BSPLOG(bsp_log("_FIN_WAIT_1 --> _CLOSING\n")); __timer_cancel(&s->timer); s->ack++; s->state = _CLOSING; tcp_send(s, TCP_FLAG_FIN | TCP_FLAG_ACK, 0); } break; case _FIN_WAIT_2: queued = handle_data(s, pkt); if (tcp->flags & TCP_FLAG_FIN) { BSPLOG(bsp_log("_FIN_WAIT_2 --> _TIME_WAIT\n")); s->ack++; s->state = _TIME_WAIT; tcp_send(s, TCP_FLAG_ACK, 0); } break; case _CLOSING: if (tcp->flags & TCP_FLAG_ACK) { handle_ack(s, pkt); if (ntohl(tcp->acknum) == (s->seq + 1)) { /* got ACK for FIN packet */ BSPLOG(bsp_log("_CLOSING --> _TIME_WAIT\n")); __timer_cancel(&s->timer); s->state = _TIME_WAIT; } } break; case _TIME_WAIT: BSPLOG(bsp_log("_TIME_WAIT resend.\n")); tcp_send(s, 0, 1); /* just resend ack */ break; } } else { BSPLOG(bsp_log("Unexpected segment from: %d.%d.%d.%d:%d\n", r->ip_addr[0], r->ip_addr[1], r->ip_addr[3], r->ip_addr[4], ntohs(tcp->src_port))); send_reset(pkt, r); } } if (!queued) __pktbuf_free(pkt);}void__tcp_poll(void){ __enet_poll(); __timer_poll();}int__tcp_listen(tcp_socket_t *s, word port){ BSPLOG(bsp_log("tcp_listen: s[%p] port[%x]\n", s, port)); memset(s, 0, sizeof(tcp_socket_t)); s->state = _LISTEN; s->our_port = port; s->pkt.buf = (word *)s->pktbuf; s->pkt.bufsize = ETH_MAX_PKTLEN;#if 0 s->pkt.eth_hdr = (eth_header_t *)s->pkt.buf; s->pkt.ip_hdr = (ip_header_t *)(s->pkt.eth_hdr + 1);#else s->pkt.ip_hdr = (ip_header_t *)s->pkt.buf;#endif s->pkt.tcp_hdr = (tcp_header_t *)(s->pkt.ip_hdr + 1); s->next = tcp_list;#if 1 /* limit to one open socket at a time */ if (s->next) { BSPLOG(bsp_log("tcp_listen: recursion error\n")); BSPLOG(while(1)); }#endif tcp_list = s; return 0;}/* * Block while waiting for all data to be transmitted. */void__tcp_drain(tcp_socket_t *s){ BSPLOG(bsp_log("__tcp_drain.\n")); while (s->state != _CLOSED && s->data_bytes) __tcp_poll(); BSPLOG(bsp_log("__tcp_drain done.\n"));}/* * Close the tcp connection. */void__tcp_close(tcp_socket_t *s){ __tcp_drain(s); if (s->state == _ESTABLISHED || s->state == _SYN_RCVD) { BSPLOG(bsp_log("__tcp_close: going to _FIN_WAIT_1\n")); s->state = _FIN_WAIT_1; tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0); } else if (s->state == _CLOSE_WAIT) { BSPLOG(bsp_log("__tcp_close: going to _LAST_ACK\n")); s->state = _LAST_ACK; tcp_send(s, TCP_FLAG_ACK | TCP_FLAG_FIN, 0); } free_rxlist(s);}/* * Wait for connection to be fully closed. */void__tcp_close_wait(tcp_socket_t *s){ BSPLOG(bsp_log("__tcp_close_wait.\n")); while (s->state != _CLOSED) __tcp_poll(); BSPLOG(bsp_log("__tcp_close_wait done.\n"));}/* * Read up to 'len' bytes without blocking. */int__tcp_read(tcp_socket_t *s, char *buf, int len){ int nread; pktbuf_t *pkt; tcp_header_t *tcp; if (len <= 0 || s->rxcnt == 0) return 0; if (s->state != _ESTABLISHED && s->rxcnt == 0) return -1; nread = 0; while (len) { if (len < s->rxcnt) { memcpy(buf, s->rxptr, len); BSPLOG(bsp_log("tcp_read: read %d bytes.\n", len)); s->rxptr += len; s->rxcnt -= len; nread += len; BSPLOG(bsp_log("tcp_read: %d bytes left in rxlist head.\n", s->rxcnt)); break; } else { memcpy(buf, s->rxptr, s->rxcnt); BSPLOG(bsp_log("tcp_read: read %d bytes. pkt[%x] freed.\n", s->rxcnt, s->rxlist)); nread += s->rxcnt; buf += s->rxcnt; len -= s->rxcnt; /* setup for next packet in list */ pkt = s->rxlist; s->rxlist = pkt->next; __pktbuf_free(pkt); if ((pkt = s->rxlist) != NULL) { tcp = pkt->tcp_hdr; s->rxcnt = pkt->pkt_bytes - (tcp->hdr_len << 2); s->rxptr = ((char *)tcp) + (tcp->hdr_len << 2); BSPLOG(bsp_log("tcp_read: next pkt[%x] has %d bytes.\n", s->rxlist, s->rxcnt)); } else { BSPLOG(bsp_log("tcp_read: no more data.\n")); s->rxcnt = 0; break; } } } return nread;}int__tcp_write(tcp_socket_t *s, char *buf, int len){ tcp_header_t *tcp = s->pkt.tcp_hdr; if (len <= 0) return 0; if (s->state != _ESTABLISHED && s->state != _CLOSE_WAIT) return -1; if (s->data_bytes) return 0; if (len > MAX_TCP_DATA) len = MAX_TCP_DATA; memcpy(tcp + 1, buf, len); s->data_bytes = len; tcp_send(s, TCP_FLAG_ACK, 0); return len;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -