-
-t_open(tp, mode) /* set up a tcb for a connection */
- register struct tcb *tp;
- int mode;
-{
- register struct ucb *up;
-COUNT(T_OPEN);
-
- /* enqueue the tcb */
-
- if (netcb.n_tcb_head == NULL) {
- netcb.n_tcb_head = tp;
- netcb.n_tcb_tail = tp;
- } else {
- tp->t_tcb_next = netcb.n_tcb_head;
- netcb.n_tcb_head->t_tcb_prev = tp;
- netcb.n_tcb_head = tp;
- }
-
- /* initialize non-zero tcb fields */
-
- tp->t_rcv_next = (struct th *)tp;
- tp->t_rcv_prev = (struct th *)tp;
- tp->t_xmtime = T_REXMT;
- tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi =
- tp->snd_una = tp->iss = netcb.n_iss;
- tp->snd_off = tp->iss + 1;
- netcb.n_iss += (ISSINCR >> 1) + 1;
-
- /* set timeout for open */
-
- up = tp->t_ucb;
- tp->t_init = (up->uc_timeo != 0 ? up->uc_timeo :
- (mode == ACTIVE ? T_INIT : 0));
- up->uc_timeo = 0; /* overlays uc_ssize */
-}
-
-t_close(tp, state)
- register struct tcb *tp;
- short state;
-{
- register struct ucb *up;
- register struct th *t;
- register struct mbuf *m;
-COUNT(T_CLOSE);
-
- up = tp->t_ucb;
-
- tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist =
- tp->t_finack = 0;
-
- /* delete tcb */
-
- if (tp->t_tcb_prev == NULL)
- netcb.n_tcb_head = tp->t_tcb_next;
- else
- tp->t_tcb_prev->t_tcb_next = tp->t_tcb_next;
- if (tp->t_tcb_next == NULL)
- netcb.n_tcb_tail = tp->t_tcb_prev;
- else
- tp->t_tcb_next->t_tcb_prev = tp->t_tcb_prev;
-
- /* free all data on receive and send buffers */
-
- for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next)
- m_freem(dtom(t));
-
- if (up->uc_rbuf != NULL) {
- m_freem(up->uc_rbuf);
- up->uc_rbuf = NULL;
- }
- if (up->uc_sbuf != NULL) {
- m_freem(up->uc_sbuf);
- up->uc_sbuf = NULL;
- }
- for (m = tp->t_rcv_unack; m != NULL; m = m->m_act) {
- m_freem(m);
- tp->t_rcv_unack = NULL;
- }
- m_free(dtom(tp));
- up->uc_tcb = NULL;
-
- /* lower buffer allocation and decrement host entry */
-
- netcb.n_lowat -= up->uc_snd + up->uc_rcv + 2;
- netcb.n_hiwat = 2 * netcb.n_lowat;
- if (up->uc_host != NULL) {
- h_free(up->uc_host);
- up->uc_host = NULL;
- }
-
- /* if user has initiated close (via close call), delete ucb
- entry, otherwise just wakeup so user can issue close call */
-
- if (tp->tc_flags&TC_USR_ABORT)
- up->uc_proc = NULL;
- else
- to_user(up, state);
-}
-
-sss_snd(tp, m0)
- register struct tcb *tp;
- struct mbuf *m0;
-{
- register struct mbuf *m, *n;
- register struct ucb *up = tp->t_ucb;
- register off;
- seq_t last;
-
- last = tp->snd_off;
-
- /* count number of mbufs in send data */
-
- for (m = n = m0; m != NULL; m = m->m_next) {
- up->uc_ssize++;
- last += m->m_len;
- }
-
- /* find end of send buffer and append data */
-
- if ((m = up->uc_sbuf) != NULL) { /* something in send buffer */
- while (m->m_next != NULL) { /* find the end */
- m = m->m_next;
- last += m->m_len;
- }
- last += m->m_len;
-
- /* if there's room in old buffer for new data, consolidate */
-
- off = m->m_off + m->m_len;
- while (n != NULL && (MSIZE - off) >= n->m_len) {
- bcopy((caddr_t)((int)n + n->m_off),
- (caddr_t)((int)m + off), n->m_len);
- m->m_len += n->m_len;
- off += n->m_len;
- up->uc_ssize--;
- n = m_free(n);
- }
- m->m_next = n;
-
- } else /* nothing in send buffer */
- up->uc_sbuf = n;
-
- if (up->uc_flags & UEOL) { /* set EOL */
- tp->snd_end = last;
- }
-
- if (up->uc_flags & UURG) { /* urgent data */
- tp->snd_urp = last+1;
- tp->tc_flags |= TC_SND_URG;
- }
-
- send(tp);
-
- return (SAME);
-}
-
-tcp_timers(tp, timertype)
- register struct tcb *tp;
- int timertype;
-{
-
-COUNT(TCP_TIMERS);
- switch (timertype) {
-
- case TINIT: /* initialization timer */
- if ((tp->tc_flags&TC_SYN_ACKED) == 0) { /* 35 */
- t_close(tp, UINTIMO);
- return (CLOSED);
- }
- return (SAME);
-
- case TFINACK: /* fin-ack timer */
- switch (tp->t_state) {
-
- case TIME_WAIT:
- /*
- * We can be sure our ACK of foreign FIN was rcvd,
- * and can close if no data left for user.
- */
- if (rcv_empty(tp)) {
- t_close(tp, UCLOSED); /* 14 */
- return (CLOSED);
- }
- return (RCV_WAIT); /* 17 */
-
- case CLOSING1:
- tp->tc_flags |= TC_WAITED_2_ML;
- return (SAME);
-
- default:
- return (SAME);
- }
-
- case TREXMT: /* retransmission timer */
- if (tp->t_rexmt_val > tp->snd_una) { /* 34 */
- /*
- * Set up for a retransmission, increase rexmt time
- * in case of multiple retransmissions.
- */
- tp->snd_nxt = tp->snd_una;
- tp->tc_flags |= TC_REXMT;
- tp->t_xmtime = tp->t_xmtime << 1;
- if (tp->t_xmtime > T_REMAX)
- tp->t_xmtime = T_REMAX;
- send(tp);
- }
- return (SAME);
-
- case TREXMTTL: /* retransmit too long */
- if (tp->t_rtl_val > tp->snd_una) /* 36 */
- to_user(tp->t_ucb, URXTIMO);
- /*
- * If user has already closed, abort the connection.
- */
- if (tp->tc_flags & TC_USR_CLOSED) {
- t_close(tp, URXTIMO);
- return (CLOSED);
- }
- return (SAME);
-
- case TPERSIST: /* persist timer */
- /*
- * Force a byte send through closed window.
- */
- tp->tc_flags |= TC_FORCE_ONE;
- send(tp);
- return (SAME);
- }
- panic("tcp_timers");
-}
-
-/* THIS ROUTINE IS A CROCK */
-to_user(up, state)
- register struct ucb *up;
- register short state;
-{
-COUNT(TO_USER);
-
- up->uc_state |= state;
- netwakeup(up);
- if (state == UURGENT)
- psignal(up->uc_proc, SIGURG);
-}
-
-#ifdef TCPDEBUG
-tcp_prt(tdp)
- register struct tcp_debug *tdp;
-{
-COUNT(TCP_PRT);
-
- printf("TCP(%X) %s X %s",
- tdp->td_tcb, tcpstates[tdp->td_old], tcpinputs[tdp->td_inp]);
- if (tdp->td_inp == ISTIMER)
- printf("(%s)", tcptimers[tdp->td_tim]);
- printf(" --> %s",
- tcpstates[(tdp->td_new > 0) ? tdp->td_new : tdp->td_old]);
- /* GROSS... DEPENDS ON SIGN EXTENSION OF CHARACTERS */
- if (tdp->td_new < 0)
- printf(" (FAILED)");
- printf("\n");
-}
-#endif