📄 tcp.c
字号:
/*tcp.c*/#include "inet.h"#include "buf.h"#include "clock.h"#include "type.h"#include "io.h"#include "ip.h"#include "sr.h"#include "assert.h"#include "tcp.h"#include "tcp_int.h"INIT_PANIC();PUBLIC tcp_port_t tcp_port_table[TCP_PORT_NR];PUBLIC tcp_fd_t tcp_fd_table[TCP_FD_NR];PUBLIC tcp_conn_t tcp_conn_table[TCP_CONN_NR];FORWARD void tcp_main ARGS(( tcp_port_t *port ));FORWARD acc_t *tcp_get_data ARGS(( int fd, size_t offset, size_t count, int for_ioctl ));FORWARD int tcp_put_data ARGS(( int fd, size_t offset, acc_t *data, int for_ioctl ));FORWARD void read_ip_packets ARGS(( tcp_port_t *port ));FORWARD int tcp_setconf ARGS(( tcp_fd_t *tcp_fd ));FORWARD int tcp_connect ARGS(( tcp_fd_t *tcp_fd ));FORWARD int tcp_listen ARGS(( tcp_fd_t *tcp_fd ));FORWARD int tcp_attache ARGS(( tcp_fd_t *tcp_fd ));FORWARD tcpport_t find_unused_port ARGS(( int fd ));FORWARD int is_unused_port ARGS(( Tcpport_t port ));FORWARD int reply_thr_put ARGS(( tcp_fd_t *tcp_fd, int reply, int for_ioctl ));FORWARD void reply_thr_get ARGS(( tcp_fd_t *tcp_fd, int reply, int for_ioctl ));FORWARD tcp_conn_t *find_conn_entry ARGS(( Tcpport_t locport, ipaddr_t locaddr, Tcpport_t remport, ipaddr_t readaddr ));FORWARD tcp_conn_t *find_empty_conn ARGS(( void ));FORWARD void process_inc_fragm ARGS(( tcp_port_t *tcp_port, acc_t *data ));FORWARD tcp_conn_t *find_best_conn ARGS(( ip_hdr_t *ip_hdr, tcp_hdr_t *tcp_hdr ));FORWARD void close_mainuser ARGS(( tcp_conn_t *tcp_conn, tcp_fd_t *tcp_fd ));FORWARD int conn_right4fd ARGS(( tcp_conn_t *tcp_conn, tcp_fd_t *tcp_fd ));FORWARD int tcp_su4connect ARGS(( tcp_fd_t *tcp_fd ));FORWARD void tcp_buffree ARGS(( int priority, size_t reqsize ));FORWARD void tcp_notreach ARGS(( acc_t *pack ));FORWARD void tcp_setup_conn ARGS(( tcp_conn_t *tcp_conn ));PUBLIC void tcp_init(){ int i, result; tcp_fd_t *tcp_fd; tcp_port_t *tcp_port; tcp_conn_t *tcp_conn; assert (BUF_S >= sizeof(struct nwio_ipopt)); assert (BUF_S >= sizeof(struct nwio_ipconf)); assert (BUF_S >= sizeof(struct nwio_tcpconf)); assert (BUF_S >= IP_MAX_HDR_SIZE); assert (BUF_S >= TCP_MAX_HDR_SIZE); tcp_port_table[0].tp_minor= TCP_DEV0; tcp_port_table[0].tp_ipdev= IP0; for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++) { tcp_fd->tf_flags= TFF_EMPTY; } for (i=0, tcp_conn= tcp_conn_table; i<TCP_CONN_NR; i++, tcp_fd++) { tcp_conn->tc_flags= TCF_EMPTY;#if DEBUG & 256 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif } bf_logon(tcp_buffree); for (i=0, tcp_port= tcp_port_table; i<TCP_PORT_NR; i++, tcp_port++) { tcp_port->tp_flags= TPF_EMPTY; tcp_port->tp_state= TPS_EMPTY; result= sr_add_minor (tcp_port->tp_minor, tcp_port-tcp_port_table, tcp_open, tcp_close, tcp_read, tcp_write, tcp_ioctl, tcp_cancel); assert (result>=0); tcp_main(tcp_port); }}PRIVATE void tcp_main(tcp_port)tcp_port_t *tcp_port;{ int result, i; tcp_conn_t *tcp_conn; tcp_fd_t *tcp_fd; switch (tcp_port->tp_state) { case TPS_EMPTY: tcp_port->tp_state= TPS_SETPROTO;#if DEBUG & 256 { where(); printf("doing ip_open\n"); }#endif tcp_port->tp_ipfd= ip_open(tcp_port->tp_ipdev, tcp_port-tcp_port_table, tcp_get_data, tcp_put_data); if (tcp_port->tp_ipfd < 0) { tcp_port->tp_state= TPS_ERROR; printf("%s, %d: unable to open ip port\n", __FILE__, __LINE__); return; }#if DEBUG & 256 { where(); printf("doing ip_ioctl(.., NWIOSIPOPT)\n"); }#endif result= ip_ioctl(tcp_port->tp_ipfd, NWIOSIPOPT); if (result == NW_SUSPEND) tcp_port->tp_flags |= TPF_SUSPEND; if (result < 0) {#if DEBUG { where(); printf("ip_ioctl(..,%lx)=%d\n", NWIOSIPOPT, result); }#endif return; } if (tcp_port->tp_state != TPS_GETCONF) return; /* drops through */ case TPS_GETCONF: tcp_port->tp_flags &= ~TPF_SUSPEND;#if DEBUG & 256 { where(); printf("doing ip_ioctl(.., NWIOGIPCONF)\n"); }#endif result= ip_ioctl(tcp_port->tp_ipfd, NWIOGIPCONF); if (result == NW_SUSPEND) tcp_port->tp_flags |= TPF_SUSPEND; if (result < 0) {#if DEBUG & 256 { where(); printf("ip_ioctl(..,%lx)=%d\n", NWIOGIPCONF, result); }#endif return; } if (tcp_port->tp_state != TPS_MAIN) return; /* drops through */ case TPS_MAIN: tcp_port->tp_flags &= ~TPF_SUSPEND; tcp_port->tp_pack= 0; tcp_conn= &tcp_conn_table[tcp_port-tcp_port_table]; tcp_conn->tc_flags= TCF_INUSE;#if DEBUG & 16 { where(); printf("tcp_conn_table[%d].tc_flags= 0x%x\n", tcp_conn-tcp_conn_table, tcp_conn->tc_flags); }#endif tcp_conn->tc_locport= 0; tcp_conn->tc_locaddr= tcp_port->tp_ipaddr; tcp_conn->tc_remport= 0; tcp_conn->tc_remaddr= 0; tcp_conn->tc_state= TCS_CLOSED;#if DEBUG & 2 { where(); tcp_write_state(tcp_conn); }#endif tcp_conn->tc_mainuser= 0; tcp_conn->tc_readuser= 0; tcp_conn->tc_writeuser= 0; 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_conn->tc_orglisten= FALSE; tcp_conn->tc_senddis= 0; tcp_conn->tc_ISS= 0; tcp_conn->tc_SND_UNA= tcp_conn->tc_ISS; tcp_conn->tc_SND_TRM= tcp_conn->tc_ISS; tcp_conn->tc_SND_NXT= tcp_conn->tc_ISS; tcp_conn->tc_SND_UP= tcp_conn->tc_ISS; tcp_conn->tc_SND_WL2= tcp_conn->tc_ISS; tcp_conn->tc_IRS= 0; tcp_conn->tc_SND_WL1= tcp_conn->tc_IRS; tcp_conn->tc_RCV_LO= tcp_conn->tc_IRS; tcp_conn->tc_RCV_NXT= tcp_conn->tc_IRS; tcp_conn->tc_RCV_HI= tcp_conn->tc_IRS; tcp_conn->tc_RCV_UP= tcp_conn->tc_IRS; tcp_conn->tc_port= tcp_port; tcp_conn->tc_rcvd_data= 0; tcp_conn->tc_rcv_queue= 0; tcp_conn->tc_send_data= 0; tcp_conn->tc_remipopt= 0; tcp_conn->tc_remtcpopt= 0; tcp_conn->tc_frag2send= 0; tcp_conn->tc_tos= TCP_DEF_TOS; tcp_conn->tc_ttl= IP_MAX_TTL; tcp_conn->tc_rcv_wnd= TCP_MAX_WND_SIZE; tcp_conn->tc_urg_wnd= TCP_DEF_URG_WND; tcp_conn->tc_max_no_retrans= TCP_DEF_MAX_NO_RETRANS; tcp_conn->tc_0wnd_to= 0; tcp_conn->tc_rtt= TCP_DEF_RTT; tcp_conn->tc_ett= 0; tcp_conn->tc_mss= TCP_DEF_MSS; tcp_conn->tc_error= NW_OK; tcp_conn->tc_snd_wnd= TCP_MAX_WND_SIZE; for (i=0, tcp_fd= tcp_fd_table; i<TCP_FD_NR; i++, tcp_fd++) { if (!(tcp_fd->tf_flags & TFF_INUSE)) continue; if (tcp_fd->tf_port != tcp_port) continue; if (tcp_fd->tf_flags & TFF_IOC_INIT_SP) { tcp_fd->tf_flags &= ~TFF_IOC_INIT_SP;#if DEBUG & 256 { where(); printf("restarting tcp_ioctl\n"); }#endif tcp_ioctl(i, tcp_fd->tf_ioreq); } } read_ip_packets(tcp_port); return; default: ip_panic(( "unknown state" )); break; }}PRIVATE acc_t *tcp_get_data (port, offset, count, for_ioctl)int port;size_t offset;size_t count;int for_ioctl;{ tcp_port_t *tcp_port; int result; tcp_port= &tcp_port_table[port]; switch (tcp_port->tp_state) { case TPS_SETPROTO: if (!count) { result= (int)offset; if (result<0) { tcp_port->tp_state= TPS_ERROR; break; } tcp_port->tp_state= TPS_GETCONF; if (tcp_port->tp_flags & TPF_SUSPEND) tcp_main(tcp_port); return NW_OK; }assert (!offset);assert (count == sizeof(struct nwio_ipopt)); { struct nwio_ipopt *ipopt; acc_t *acc; acc= bf_memreq(sizeof(*ipopt)); ipopt= (struct nwio_ipopt *)ptr2acc_data(acc); ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC | NWIO_DI_BROAD | NWIO_REMANY | NWIO_PROTOSPEC | NWIO_HDR_O_ANY | NWIO_RWDATALL; ipopt->nwio_proto= IPPROTO_TCP; return acc; } case TPS_MAIN: assert(tcp_port->tp_flags & TPF_WRITE_IP); if (!count) { result= (int)offset;#if DEBUG & 256 { where(); printf("tcp_get_data: got reply: %d\n", result); }#endif if (result<0) { if (result == EDSTNOTRCH) { tcp_notreach(tcp_port->tp_pack); } else { ip_warning(( "ip_write failed with error: %d\n", result )); } } assert (tcp_port->tp_pack); bf_afree (tcp_port->tp_pack); tcp_port->tp_pack= 0; if (tcp_port->tp_flags & TPF_WRITE_SP) { tcp_port->tp_flags &= ~(TPF_WRITE_SP| TPF_WRITE_IP); if (tcp_port->tp_flags & TPF_MORE2WRITE) {#if DEBUG & 256 { where(); printf("calling tcp_restart_write_port(&tcp_port_table[%d])\n", tcp_port - tcp_port_table); }#endif tcp_restart_write_port( tcp_port); } } else tcp_port->tp_flags &= ~TPF_WRITE_IP; } else {#if DEBUG & 256 { where(); printf("suplying data, count= %d, offset= %d, bufsize= %d\n", count, offset, bf_bufsize(tcp_port->tp_pack)); }#endif return bf_cut (tcp_port->tp_pack, offset, count); } break; default: printf("tcp_get_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n", port, offset, count, tcp_port->tp_state); break; } return NW_OK;}PRIVATE int tcp_put_data (fd, offset, data, for_ioctl)int fd;size_t offset;acc_t *data;int for_ioctl;{ tcp_port_t *tcp_port; int result; tcp_port= &tcp_port_table[fd]; switch (tcp_port->tp_state) { case TPS_GETCONF: if (!data) { result= (int)offset; if (result<0) { tcp_port->tp_state= TPS_ERROR; return NW_OK; } tcp_port->tp_state= TPS_MAIN;#if DEBUG & 256 { where(); printf("get GETCONF reply\n"); }#endif if (tcp_port->tp_flags & TPF_SUSPEND) tcp_main(tcp_port); } else { struct nwio_ipconf *ipconf; data= bf_packIffLess(data, sizeof(*ipconf)); ipconf= (struct nwio_ipconf *)ptr2acc_data(data);assert (ipconf->nwic_flags & NWIC_IPADDR_SET); tcp_port->tp_ipaddr= ipconf->nwic_ipaddr; bf_afree(data); } break; case TPS_MAIN: assert(tcp_port->tp_flags & TPF_READ_IP); if (!data) { result= (int)offset; if (result<0)#if DEBUG { where(); printf("tcp_put_data got error %d (ignored)\n", result); }#elseip_panic(( "ip_read() failed" ));#endif if (tcp_port->tp_flags & TPF_READ_SP) { tcp_port->tp_flags &= ~(TPF_READ_SP| TPF_READ_IP); read_ip_packets(tcp_port); } else tcp_port->tp_flags &= ~TPF_READ_IP; } else {assert(!offset); /* this isn't a valid assertion but ip sends * only whole datagrams up */#if DEBUG & 256 { where(); printf("got data from ip\n"); }#endif process_inc_fragm(tcp_port, data); } break; default: printf("tcp_put_data(%d, 0x%x, 0x%x) called but tp_state= 0x%x\n", fd, offset, data, tcp_port->tp_state); break; } return NW_OK;}PUBLIC int tcp_open (port, srfd, get_userdata, put_userdata)int port;int srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;{ int i; tcp_fd_t *tcp_fd; for (i=0; i<TCP_FD_NR && (tcp_fd_table[i].tf_flags & TFF_INUSE); i++); if (i>=TCP_FD_NR) {#if DEBUG { where(); printf("out of fds\n"); }#endif return EOUTOFBUFS; } tcp_fd= &tcp_fd_table[i]; tcp_fd->tf_flags= TFF_INUSE; tcp_fd->tf_flags |= TFF_PUSH_DATA; /* XXX */ tcp_fd->tf_port= &tcp_port_table[port]; tcp_fd->tf_srfd= srfd; tcp_fd->tf_tcpconf.nwtc_flags= TCP_DEF_OPT; tcp_fd->tf_tcpconf.nwtc_remaddr= 0; tcp_fd->tf_tcpconf.nwtc_remport= 0; tcp_fd->tf_get_userdata= get_userdata; tcp_fd->tf_put_userdata= put_userdata; tcp_fd->tf_conn= 0; return i;}PUBLIC int tcp_ioctl (fd, req)int fd;int req;{ tcp_fd_t *tcp_fd; tcp_port_t *tcp_port; tcp_conn_t *tcp_conn; nwio_tcpconf_t *tcp_conf; acc_t *conf_acc; int type; int result;#if DEBUG & 256 { where(); printf("tcp_ioctl called\n"); }#endif tcp_fd= &tcp_fd_table[fd]; type= req & IOCTYPE_MASK;assert (tcp_fd->tf_flags & TFF_INUSE); tcp_port= tcp_fd->tf_port; tcp_fd->tf_flags |= TFF_IOCTL_IP; tcp_fd->tf_ioreq= req; if (tcp_port->tp_state != TPS_MAIN) { tcp_fd->tf_flags |= TFF_IOC_INIT_SP; return NW_SUSPEND; } switch (type) { case NWIOSTCPCONF & IOCTYPE_MASK: if (req != NWIOSTCPCONF) {#if DEBUG { where(); printf("0x%x: bad ioctl\n", req); }#endif tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EBADIOCTL, TRUE); result= NW_OK; break; } if (tcp_fd->tf_flags & TFF_CONNECTED) { tcp_fd->tf_flags &= ~TFF_IOCTL_IP; reply_thr_get (tcp_fd, EISCONN, TRUE); result= NW_OK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -