📄 tcp.c
字号:
ipaddr_t remaddr;{ tcp_conn_t *tcp_conn; int i, state;#if DEBUG & 256 { where(); printf("find_conn_entry(locport= %u, locaddr= ", ntohs(locport)); writeIpAddr(locaddr); printf("\nremport= %u, remaddr= ", ntohs(remport)); writeIpAddr(remaddr); printf(")\n"); }#endifassert(remport);assert(remaddr); for (i=TCP_PORT_NR, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR; i++, tcp_conn++) /* the first TCP_PORT_NR connection are reserved for RSTs */ { if (tcp_conn->tc_flags == TCF_EMPTY) continue; if (tcp_conn->tc_locport != locport || tcp_conn->tc_locaddr != locaddr || tcp_conn->tc_remport != remport || tcp_conn->tc_remaddr != remaddr) continue; if (tcp_conn->tc_mainuser) return tcp_conn; state= tcp_conn->tc_state; if (state != TCS_CLOSED) { tcp_close_connection(tcp_conn, ENOCONN); } return tcp_conn; } return NULL;}PRIVATE void read_ip_packets(tcp_port)tcp_port_t *tcp_port;{ int result; do { tcp_port->tp_flags |= TPF_READ_IP;#if DEBUG & 256 { where(); printf("doing ip_read\n"); }#endif result= ip_read(tcp_port->tp_ipfd, TCP_MAX_DATAGRAM); if (result == NW_SUSPEND) { tcp_port->tp_flags |= TPF_READ_SP; return; }assert(result == NW_OK); tcp_port->tp_flags &= ~TPF_READ_IP; } while(!(tcp_port->tp_flags & TPF_READ_IP));}/*process_inc_fragm*/PRIVATE void process_inc_fragm(tcp_port, data)tcp_port_t *tcp_port;acc_t *data;{ acc_t *ip_pack, *tcp_pack; ip_hdr_t *ip_hdr; tcp_hdr_t *tcp_hdr; tcp_conn_t *tcp_conn; int pack_len, ip_hdr_len; pack_len= bf_bufsize(data); if ((u16_t)~tcp_pack_oneCsum(data, pack_len)) { data= bf_packIffLess(data, IP_MIN_HDR_SIZE); ip_hdr= (ip_hdr_t *)ptr2acc_data(data);#if DEBUG { where(); printf("checksum error in tcp_pack\n"); printf("tcp_pack_oneCsum(...)= 0x%x (%d) length= %d\n", (u16_t)~tcp_pack_oneCsum(data, pack_len), (u16_t)~tcp_pack_oneCsum(data, pack_len), pack_len); printf("src ip_addr= "); writeIpAddr(ip_hdr->ih_src); printf("\n"); }#endif bf_afree(data); return; } data= bf_packIffLess(data, IP_MIN_HDR_SIZE); ip_hdr= (ip_hdr_t *)ptr2acc_data(data); ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2; ip_pack= bf_cut(data, 0, ip_hdr_len); pack_len -= ip_hdr_len; tcp_pack= bf_cut(data, ip_hdr_len, pack_len); bf_afree(data); tcp_pack= bf_packIffLess(tcp_pack, TCP_MIN_HDR_SIZE); tcp_hdr= (tcp_hdr_t *)ptr2acc_data(tcp_pack); tcp_conn= find_best_conn(ip_hdr, tcp_hdr);assert(tcp_conn);#if DEBUG & 256 { where(); tcp_print_pack(ip_hdr, tcp_hdr); printf("\n"); tcp_print_conn(tcp_conn); printf("\n"); }#endif tcp_hdr->th_chksum= pack_len; /* tcp_pack size in chksum field */#if DEBUG & 256 { where(); printf("calling tcp_frag2conn(...)\n"); }#endif tcp_frag2conn(tcp_conn, ip_pack, tcp_pack);}/*find_best_conn*/PRIVATE tcp_conn_t *find_best_conn(ip_hdr, tcp_hdr)ip_hdr_t *ip_hdr;tcp_hdr_t *tcp_hdr;{ int best_level, new_level; tcp_conn_t *best_conn, *listen_conn, *tcp_conn; tcp_fd_t *tcp_fd; int i; ipaddr_t locaddr; ipaddr_t remaddr; tcpport_t locport; tcpport_t remport; locaddr= ip_hdr->ih_dst; remaddr= ip_hdr->ih_src; locport= tcp_hdr->th_dstport; remport= tcp_hdr->th_srcport; if (!remport) /* This can interfere with a listen, so we reject it * by clearing the requested port */ locport= 0; #if DEBUG & 256 { where(); printf("find_best_conn(locport= %u, locaddr= ", ntohs(locport)); writeIpAddr(locaddr); printf("\nremport= %u, remaddr= ", ntohs(remport)); writeIpAddr(remaddr); printf(")\n"); }#endif best_level= 0; best_conn= NULL; listen_conn= NULL; for (i= TCP_PORT_NR, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR; i++, tcp_conn++) /* the first TCP_PORT_NR connection are reserved for RSTs */ { if (!(tcp_conn->tc_flags & TCF_INUSE)) continue; /* First fast check for open connections. */ if (tcp_conn->tc_locaddr == locaddr && tcp_conn->tc_locport == locport && tcp_conn->tc_remport == remport && tcp_conn->tc_remaddr == remaddr && tcp_conn->tc_mainuser) return tcp_conn; /* Now check for listens and abandoned connections. */ if (tcp_conn->tc_locaddr != locaddr) {#if DEBUG { where(); printf("conn %d: wrong locaddr\n",i); }#endif continue; } new_level= 0; if (tcp_conn->tc_locport) { if (locport != tcp_conn->tc_locport) {#if DEBUG & 256 { where(); printf("conn %d: wrong locport(%u)\n",i, ntohs(tcp_conn->tc_locport)); }#endif continue; } new_level += 4; } if (tcp_conn->tc_remport) { if (remport != tcp_conn->tc_remport) {#if DEBUG & 256 { where(); printf("conn %d: wrong remport\n",i); }#endif continue; } new_level += 1; } if (tcp_conn->tc_remaddr) { if (remaddr != tcp_conn->tc_remaddr) {#if DEBUG & 256 { where(); printf("conn %d: wrong remaddr\n",i); }#endif continue; } new_level += 2; } if (new_level<best_level) continue; if (new_level != 7 && tcp_conn->tc_state != TCS_LISTEN) continue; if (new_level == 7 && !tcp_conn->tc_mainuser) /* We found an abandoned connection */ {assert (!best_conn); best_conn= tcp_conn; continue; } if (!(tcp_hdr->th_flags & THF_SYN)) continue; best_level= new_level; listen_conn= tcp_conn; } if (!best_conn && !listen_conn) {#if DEBUG & 256 { where(); printf("refusing connection for locport= %u, locaddr= ", ntohs(locport)); writeIpAddr(locaddr); printf("\nremport= %u, remaddr= ", ntohs(remport)); writeIpAddr(remaddr); printf("\n"); }#endif for (i=0, tcp_conn= tcp_conn_table; i<TCP_PORT_NR; i++, tcp_conn++) /* find valid port to send RST */ if ((tcp_conn->tc_flags & TCF_INUSE) && tcp_conn->tc_locaddr==locaddr) { break; }assert (tcp_conn);assert (tcp_conn->tc_state == TCS_CLOSED); tcp_conn->tc_locport= locport; tcp_conn->tc_locaddr= locaddr; tcp_conn->tc_remport= remport; tcp_conn->tc_remaddr= remaddr;assert (!tcp_conn->tc_mainuser);assert (!tcp_conn->tc_readuser);assert (!tcp_conn->tc_writeuser); return tcp_conn; } if (best_conn) {assert(!best_conn->tc_mainuser); if (!listen_conn) return best_conn; tcp_fd= listen_conn->tc_mainuser;assert(tcp_fd && tcp_fd == listen_conn->tc_connuser && tcp_fd->tf_conn == listen_conn); if (best_conn->tc_state != TCS_CLOSED) tcp_close_connection(best_conn, ENOCONN); best_conn->tc_state= TCS_LISTEN;#if DEBUG { where(); tcp_write_state(best_conn); }#endif best_conn->tc_mainuser= best_conn->tc_connuser= tcp_fd; best_conn->tc_flags= listen_conn->tc_flags; tcp_fd->tf_conn= best_conn; listen_conn->tc_flags= TCF_EMPTY;#if DEBUG & 16 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", listen_conn-tcp_conn_table, listen_conn->tc_flags); }#endif return best_conn; }assert (listen_conn); return listen_conn;}PUBLIC void tcp_reply_ioctl(tcp_fd, reply)tcp_fd_t *tcp_fd;int reply;{#if DEBUG & 256 { where(); printf("tcp_reply_ioctl called\n"); }#endif#if DEBUG if (!(tcp_fd->tf_flags & TFF_IOCTL_IP)) { where(); printf("not TFF_IOCTL_IP\n"); }#endifassert (tcp_fd->tf_flags & TFF_IOCTL_IP);#if DEBUGif (tcp_fd->tf_ioreq != NWIOTCPSHUTDOWN && tcp_fd->tf_ioreq != NWIOTCPLISTEN && tcp_fd->tf_ioreq != NWIOTCPCONN) { where(); printf("wrong value in ioreq (0x%lx)\n", tcp_fd->tf_ioreq); }#endifassert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN || tcp_fd->tf_ioreq == NWIOTCPLISTEN || tcp_fd->tf_ioreq == NWIOTCPCONN); tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, reply, TRUE);}PUBLIC void tcp_reply_write(tcp_fd, reply)tcp_fd_t *tcp_fd;size_t reply;{ assert (tcp_fd->tf_flags & TFF_WRITE_IP); tcp_fd->tf_flags &= ~TFF_WRITE_IP; reply_thr_get (tcp_fd, reply, FALSE);}PUBLIC void tcp_reply_read(tcp_fd, reply)tcp_fd_t *tcp_fd;size_t reply;{ assert (tcp_fd->tf_flags & TFF_READ_IP);#if DEBUG & 256 { where(); printf("tcp_reply_read(.., %d)\n", reply); }#endif tcp_fd->tf_flags &= ~TFF_READ_IP; reply_thr_put (tcp_fd, reply, FALSE);}PUBLIC int tcp_write(fd, count)int fd;size_t count;{ tcp_fd_t *tcp_fd; tcp_conn_t *tcp_conn; tcp_fd= &tcp_fd_table[fd]; assert (tcp_fd->tf_flags & TFF_INUSE); if (!(tcp_fd->tf_flags & TFF_CONNECTED)) { reply_thr_get (tcp_fd, ENOTCONN, FALSE); return NW_OK; } tcp_conn= tcp_fd->tf_conn; if (tcp_conn->tc_flags & TCF_FIN_SENT) {#if DEBUG & 16 { where(); printf("replying ESHUTDOWN for connection %d and fd %d\n", tcp_conn-tcp_conn_table, tcp_fd-tcp_fd_table); }#endif reply_thr_get (tcp_fd, ESHUTDOWN, FALSE); return NW_OK; } tcp_fd->tf_flags |= TFF_WRITE_IP; tcp_fd->tf_write_offset= 0; tcp_fd->tf_write_count= count; if (tcp_conn->tc_writeuser) return NW_SUSPEND; tcp_conn->tc_writeuser= tcp_fd; tcp_restart_fd_write (tcp_conn); if (!(tcp_fd->tf_flags & TFF_WRITE_IP)) return NW_OK; else return NW_SUSPEND;}PUBLIC int tcp_read(fd, count)int fd;size_t count;{ tcp_fd_t *tcp_fd; tcp_conn_t *tcp_conn;#if DEBUG & 256 { where(); printf("tcp_read(%d, %u)\n", fd, count); }#endif tcp_fd= &tcp_fd_table[fd]; assert (tcp_fd->tf_flags & TFF_INUSE); if (!(tcp_fd->tf_flags & TFF_CONNECTED)) { reply_thr_put (tcp_fd, ENOTCONN, FALSE); return NW_OK; } tcp_conn= tcp_fd->tf_conn; tcp_fd->tf_flags |= TFF_READ_IP; tcp_fd->tf_read_offset= 0; tcp_fd->tf_read_count= count; if (tcp_conn->tc_readuser) return NW_SUSPEND; tcp_conn->tc_readuser= tcp_fd; tcp_restart_fd_read (tcp_conn); if (!(tcp_fd->tf_flags & TFF_READ_IP)) return NW_OK; else return NW_SUSPEND;}/*tcp_restart_connectreply the success or failure of a connect to the user.*/PUBLIC void tcp_restart_connect(tcp_fd)tcp_fd_t *tcp_fd;{ tcp_conn_t *tcp_conn; int reply;#if DEBUG & 256 { where(); printf("tcp_restart_connect called\n"); }#endifassert (tcp_fd->tf_flags & TFF_IOCTL_IP);assert (tcp_fd->tf_ioreq == NWIOTCPLISTEN || tcp_fd->tf_ioreq == NWIOTCPCONN); tcp_conn= tcp_fd->tf_conn;assert (tcp_conn->tc_connuser == tcp_fd); if (tcp_conn->tc_state == TCS_CLOSED) reply= tcp_conn->tc_error; else { tcp_fd->tf_flags |= TFF_CONNECTED; reply= NW_OK; } tcp_conn->tc_connuser= 0;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_connuser= 0x%x\n", tcp_conn- tcp_conn_table, tcp_conn->tc_connuser); }#endif tcp_reply_ioctl (tcp_fd, reply);}PUBLIC void tcp_close(fd)int fd;{ tcp_fd_t *tcp_fd; tcp_conn_t *tcp_conn; tcp_fd= &tcp_fd_table[fd];#if DEBUG { if (!(tcp_fd->tf_flags & TFF_INUSE)) { where(); printf("not inuse\n"); } if (tcp_fd->tf_flags & TFF_IOCTL_IP) { where(); printf("ioctl ip\n"); } if (tcp_fd->tf_flags & TFF_READ_IP) { where(); printf("read ip\n"); } if (tcp_fd->tf_flags & TFF_WRITE_IP) { where(); printf("write ip\n"); } }#endifassert (tcp_fd->tf_flags & TFF_INUSE);assert (!(tcp_fd->tf_flags & (TFF_IOCTL_IP|TFF_READ_IP|TFF_WRITE_IP))); tcp_fd->tf_flags &= ~TFF_INUSE; if (!tcp_fd->tf_conn) return; tcp_conn= tcp_fd->tf_conn; close_mainuser(tcp_conn, tcp_fd); tcp_shutdown (tcp_conn);}PUBLIC int tcp_cancel(fd, which_operation)int fd;int which_operation;{ tcp_fd_t *tcp_fd; tcp_conn_t *tcp_conn; int i; int type;#if DEBUG & 256 { where(); printf("tcp_cancel(%d, %d)\n", fd, which_operation); }#endif tcp_fd= &tcp_fd_table[fd]; assert (tcp_fd->tf_flags & TFF_INUSE); tcp_conn= tcp_fd->tf_conn; switch (which_operation) { case SR_CANCEL_WRITE:assert (tcp_fd->tf_flags & TFF_WRITE_IP); tcp_fd->tf_flags &= ~TFF_WRITE_IP; if (tcp_conn->tc_writeuser == tcp_fd) { tcp_conn->tc_writeuser= 0; tcp_restart_fd_write (tcp_conn); } if (tcp_fd->tf_write_count) reply_thr_get (tcp_fd, tcp_fd->tf_write_count, FALSE); else reply_thr_get (tcp_fd, EINTR, FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -