📄 tcp.c
字号:
listen_conn->tc_ISS= best_conn->tc_ISS; if (best_conn->tc_senddis > listen_conn->tc_senddis) listen_conn->tc_senddis= best_conn->tc_senddis; return listen_conn; } assert (listen_conn); return listen_conn;}/*new_conn_for_queue*/PRIVATE tcp_conn_t *new_conn_for_queue(tcp_fd)tcp_fd_t *tcp_fd;{ int i; tcp_conn_t *tcp_conn; assert(tcp_fd->tf_flags & TFF_LISTENQ); for (i= 0; i<TFL_LISTEN_MAX; i++) { if (tcp_fd->tf_listenq[i] == NULL) break; } if (i >= TFL_LISTEN_MAX) return NULL; tcp_conn= find_empty_conn(); if (!tcp_conn) return NULL; tcp_fd->tf_listenq[i]= tcp_conn; (void)tcp_su4listen(tcp_fd, tcp_conn, 0 /* !do_listenq */); return tcp_conn;}/*maybe_listen*/PRIVATE int maybe_listen(locaddr, locport, remaddr, remport)ipaddr_t locaddr;tcpport_t locport;ipaddr_t remaddr;tcpport_t remport;{ int i; tcp_conn_t *tcp_conn; tcp_fd_t *fd; for (i= tcp_conf_nr, tcp_conn= tcp_conn_table+i; i<TCP_CONN_NR; i++, tcp_conn++) { if (!(tcp_conn->tc_flags & TCF_INUSE)) continue; if (tcp_conn->tc_locaddr != locaddr) { continue; } if (tcp_conn->tc_locport != locport ) { continue; } if (!tcp_conn->tc_orglisten) continue; fd= tcp_conn->tc_fd; if (!fd) continue; if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RP) && tcp_conn->tc_remport != remport) { continue; } if ((fd->tf_tcpconf.nwtc_flags & NWTC_SET_RA) && tcp_conn->tc_remaddr != remaddr) { continue; } if (!(fd->tf_flags & TFF_DEL_RST)) continue; return 1; } return 0;}PUBLIC void tcp_reply_ioctl(tcp_fd, reply)tcp_fd_t *tcp_fd;int reply;{ assert (tcp_fd->tf_flags & TFF_IOCTL_IP); assert (tcp_fd->tf_ioreq == NWIOTCPSHUTDOWN || tcp_fd->tf_ioreq == NWIOTCPLISTEN || tcp_fd->tf_ioreq == NWIOTCPLISTENQ || tcp_fd->tf_ioreq == NWIOTCPACCEPTTO || 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); 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_CONNECTEDx)) { reply_thr_get (tcp_fd, ENOTCONN, FALSE); return NW_OK; } tcp_conn= tcp_fd->tf_conn; if (tcp_conn->tc_state == TCS_CLOSED) { reply_thr_get(tcp_fd, tcp_conn->tc_error, FALSE); return NW_OK; } if (tcp_conn->tc_flags & TCF_FIN_SENT) { 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; /* New data may cause a segment to be sent. Clear PUSH_NOW * from last NWIOTCPPUSH ioctl. */ tcp_conn->tc_flags &= ~(TCF_NO_PUSH|TCF_PUSH_NOW); /* Start the timer (if necessary) */ if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_UNA) tcp_set_send_timer(tcp_conn); assert(tcp_conn->tc_busy == 0); tcp_conn->tc_busy++; tcp_fd_write(tcp_conn); tcp_conn->tc_busy--; tcp_conn_write(tcp_conn, 0); if (!(tcp_fd->tf_flags & TFF_WRITE_IP)) return NW_OK; else return NW_SUSPEND;}PUBLIC inttcp_read(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_CONNECTEDx)) { 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; assert(tcp_conn->tc_busy == 0); tcp_conn->tc_busy++; tcp_fd_read(tcp_conn, 0); tcp_conn->tc_busy--; 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_conn)tcp_conn_t *tcp_conn;{ tcp_fd_t *tcp_fd; int reply; assert(tcp_conn->tc_connInprogress); tcp_conn->tc_connInprogress= 0; tcp_fd= tcp_conn->tc_fd; assert(tcp_fd); if (tcp_fd->tf_flags & TFF_LISTENQ) { /* Special code for listen queues */ assert(tcp_conn->tc_state != TCS_CLOSED); /* Reply for select */ if ((tcp_fd->tf_flags & TFF_SEL_READ) && tcp_fd->tf_select_res) { tcp_fd->tf_flags &= ~TFF_SEL_READ; tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_READ); } /* Reply for acceptto */ if (tcp_fd->tf_flags & TFF_IOCTL_IP) (void) tcp_acceptto(tcp_fd); return; } if (tcp_conn->tc_state == TCS_CLOSED) { reply= tcp_conn->tc_error; assert(tcp_conn->tc_fd == tcp_fd); tcp_fd->tf_conn= NULL; tcp_conn->tc_fd= NULL; } else { tcp_fd->tf_flags |= TFF_CONNECTEDx; reply= NW_OK; } if (tcp_fd->tf_flags & TFF_CONNECTING) { /* Special code for asynchronous connects */ tcp_fd->tf_flags &= ~TFF_CONNECTING; /* Reply for select */ if ((tcp_fd->tf_flags & TFF_SEL_WRITE) && tcp_fd->tf_select_res) { tcp_fd->tf_flags &= ~TFF_SEL_WRITE; tcp_fd->tf_select_res(tcp_fd->tf_srfd, SR_SELECT_WRITE); } return; } assert(tcp_fd->tf_flags & TFF_IOCTL_IP); assert(tcp_fd->tf_ioreq == NWIOTCPLISTEN || tcp_fd->tf_ioreq == NWIOTCPCONN); tcp_reply_ioctl (tcp_fd, reply);}/*tcp_close*/PUBLIC void tcp_close(fd)int fd;{ int i; tcp_fd_t *tcp_fd; tcp_conn_t *tcp_conn; tcp_fd= &tcp_fd_table[fd]; assert (tcp_fd->tf_flags & TFF_INUSE); assert (!(tcp_fd->tf_flags & (TFF_IOCTL_IP|TFF_READ_IP|TFF_WRITE_IP))); if (tcp_fd->tf_flags & TFF_LISTENQ) { /* Special code for listen queues */ for (i= 0; i<TFL_LISTEN_MAX; i++) { tcp_conn= tcp_fd->tf_listenq[i]; if (!tcp_conn) continue; tcp_fd->tf_listenq[i]= NULL; assert(tcp_conn->tc_fd == tcp_fd); tcp_conn->tc_fd= NULL; if (tcp_conn->tc_connInprogress) { tcp_conn->tc_connInprogress= 0; tcp_close_connection(tcp_conn, ENOCONN); continue; } tcp_shutdown (tcp_conn); if (tcp_conn->tc_state == TCS_ESTABLISHED) tcp_conn->tc_state= TCS_CLOSING; /* Set the retransmission timeout a bit smaller. */ tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING; /* If all data has been acknowledged, close the connection. */ if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT) tcp_close_connection(tcp_conn, ENOTCONN); } tcp_conn= tcp_fd->tf_conn; assert(tcp_conn->tc_fd == tcp_fd); assert (tcp_conn->tc_connInprogress); tcp_conn->tc_connInprogress= 0; tcp_conn->tc_fd= NULL; tcp_fd->tf_conn= NULL; tcp_close_connection(tcp_conn, ENOCONN); } for (i= 0; i<TFL_LISTEN_MAX; i++) { assert(tcp_fd->tf_listenq[i] == NULL); } if (tcp_fd->tf_flags & TFF_CONNECTING) { tcp_conn= tcp_fd->tf_conn; assert(tcp_conn != NULL); assert (tcp_conn->tc_connInprogress); tcp_conn->tc_connInprogress= 0; tcp_conn->tc_fd= NULL; tcp_fd->tf_conn= NULL; tcp_close_connection(tcp_conn, ENOCONN); tcp_fd->tf_flags &= ~TFF_CONNECTING; } tcp_fd->tf_flags &= ~TFF_INUSE; if (!tcp_fd->tf_conn) return; tcp_conn= tcp_fd->tf_conn; assert(tcp_conn->tc_fd == tcp_fd); tcp_conn->tc_fd= NULL; assert (!tcp_conn->tc_connInprogress); tcp_shutdown (tcp_conn); if (tcp_conn->tc_state == TCS_ESTABLISHED) { tcp_conn->tc_state= TCS_CLOSING; } /* Set the retransmission timeout a bit smaller. */ tcp_conn->tc_rt_dead= TCP_DEF_RT_MAX_CLOSING; /* If all data has been acknowledged, close the connection. */ if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT) tcp_close_connection(tcp_conn, ENOTCONN);}PUBLIC int tcp_cancel(fd, which_operation)int fd;int which_operation;{ tcp_fd_t *tcp_fd; tcp_conn_t *tcp_conn; 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_fd->tf_write_offset) reply_thr_get (tcp_fd, tcp_fd->tf_write_offset, FALSE); else reply_thr_get (tcp_fd, EINTR, FALSE); break; case SR_CANCEL_READ: assert (tcp_fd->tf_flags & TFF_READ_IP); tcp_fd->tf_flags &= ~TFF_READ_IP; if (tcp_fd->tf_read_offset) reply_thr_put (tcp_fd, tcp_fd->tf_read_offset, FALSE); else reply_thr_put (tcp_fd, EINTR, FALSE); break; case SR_CANCEL_IOCTL:assert (tcp_fd->tf_flags & TFF_IOCTL_IP); tcp_fd->tf_flags &= ~TFF_IOCTL_IP; switch (tcp_fd->tf_ioreq) { case NWIOGTCPCONF: reply_thr_put (tcp_fd, EINTR, TRUE); break; case NWIOSTCPCONF: case NWIOTCPSHUTDOWN: reply_thr_get (tcp_fd, EINTR, TRUE); break; case NWIOTCPCONN: case NWIOTCPLISTEN: assert (tcp_conn->tc_connInprogress); tcp_conn->tc_connInprogress= 0; tcp_conn->tc_fd= NULL; tcp_fd->tf_conn= NULL; tcp_close_connection(tcp_conn, ENOCONN); reply_thr_get (tcp_fd, EINTR, TRUE); break; default: ip_warning(( "unknown ioctl inprogress: 0x%x", tcp_fd->tf_ioreq )); reply_thr_get (tcp_fd, EINTR, TRUE); break; } break; default: ip_panic(( "unknown cancel request" )); break; } return NW_OK;}/*tcp_connect*/PRIVATE int tcp_connect(tcp_fd)tcp_fd_t *tcp_fd;{ tcp_conn_t *tcp_conn; nwio_tcpcl_t *tcpcl; long nwtcl_flags; int r, do_asynch; acc_t *data; if (!(tcp_fd->tf_flags & TFF_CONF_SET)) { tcp_reply_ioctl(tcp_fd, EBADMODE); return NW_OK; } assert (!(tcp_fd->tf_flags & TFF_CONNECTEDx) && !(tcp_fd->tf_flags & TFF_CONNECTING) && !(tcp_fd->tf_flags & TFF_LISTENQ)); if ((tcp_fd->tf_tcpconf.nwtc_flags & (NWTC_SET_RA|NWTC_SET_RP)) != (NWTC_SET_RA|NWTC_SET_RP)) { tcp_reply_ioctl(tcp_fd, EBADMODE); return NW_OK; } data= (*tcp_fd->tf_get_userdata) (tcp_fd->tf_srfd, 0, sizeof(*tcpcl), TRUE); if (!data) return EFAULT; data= bf_packIffLess(data, sizeof(*tcpcl)); assert (data->acc_length == sizeof(*tcpcl)); tcpcl= (nwio_tcpcl_t *)ptr2acc_data(data); nwtcl_flags= tcpcl->nwtcl_flags; bf_afree(data); data= NULL; tcpcl= NULL; if (nwtcl_flags == TCF_ASYNCH) do_asynch= 1; else if (nwtcl_flags == TCF_DEFAULT) do_asynch= 0; else { tcp_reply_ioctl(tcp_fd, EINVAL); return NW_OK; } assert(!tcp_fd->tf_conn); tcp_conn= find_conn_entry(tcp_fd->tf_tcpconf.nwtc_locport, tcp_fd->tf_port->tp_ipaddr, tcp_fd->tf_tcpconf.nwtc_remport, tcp_fd->tf_tcpconf.nwtc_remaddr); if (tcp_conn) { if (tcp_conn->tc_fd) { tcp_reply_ioctl(tcp_fd, EADDRINUSE); return NW_OK; } } else { tcp_conn= find_empty_conn(); if (!tcp_conn) { tcp_reply_ioctl(tcp_fd, EAGAIN); return NW_OK; } } tcp_fd->tf_conn= tcp_conn; r= tcp_su4connect(tcp_fd); if (r == NW_SUSPEND && do_asynch) { tcp_fd->tf_flags |= TFF_CONNECTING; tcp_reply_ioctl(tcp_fd, EINPROGRESS); r= NW_OK; } return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -