1 /* tcp_usrreq.c 1.3 81/10/18 */ 2 #include "../h/param.h" 3 #include "../bbnnet/net.h" 4 #include "../bbnnet/tcp.h" 5 #include "../bbnnet/ip.h" 6 #include "../bbnnet/imp.h" 7 #include "../bbnnet/ucb.h" 8 #include "../bbnnet/fsm.h" 9 #include "../bbnnet/tcp_pred.h" 10 11 lis_cls(wp) /* passive open (1) */ 12 struct work *wp; 13 { 14 15 COUNT(LIS_CLS); 16 t_open(wp->w_tcb, PASSIVE); 17 18 return(LISTEN); 19 } 20 21 sys_cls(wp) /* active open (6) */ 22 register struct work *wp; 23 { 24 25 COUNT(SYS_CLS); 26 t_open(wp->w_tcb, ACTIVE); 27 send_ctl(wp->w_tcb); /* send SYN */ 28 29 return(SYN_SENT); 30 } 31 32 cls_opn(wp) /* close request before receiving foreign SYN (10) */ 33 struct work *wp; 34 { 35 36 COUNT(CLS_OPN); 37 t_close(wp->w_tcb, UCLOSED); 38 39 return(CLOSED); 40 } 41 42 cl2_clw(wp) /* close request after receiving foreign FIN (13) */ 43 struct work *wp; 44 { 45 register struct tcb *tp; 46 47 COUNT(CL2_CLW); 48 tp = wp->w_tcb; 49 50 tp->snd_fin = TRUE; /* send our own FIN */ 51 send_ctl(tp); 52 tp->usr_closed = TRUE; 53 54 return(CLOSING2); 55 } 56 57 cls_rwt(wp) /* rcv request after foreign close (20) */ 58 struct work *wp; 59 { 60 register struct tcb *tp; 61 62 COUNT(CLS_RWT); 63 tp = wp->w_tcb; 64 65 present_data(tp); /* present any remaining data */ 66 67 if (rcv_empty(tp)) { 68 t_close(tp, UCLOSED); 69 return(CLOSED); 70 } else 71 return(RCV_WAIT); 72 73 } 74 75 fw1_syr(wp) /* close request on synced connection (24,25) */ 76 struct work *wp; 77 { 78 register struct tcb *tp; 79 80 COUNT(FW1_SYR); 81 tp = wp->w_tcb; 82 83 tp->snd_fin = TRUE; /* send FIN */ 84 send_ctl(tp); 85 tp->usr_closed = TRUE; 86 87 return(FIN_W1); 88 } 89 90 sss_snd(wp) /* send request on open connection (40,41) */ 91 struct work *wp; 92 { 93 register struct tcb *tp; 94 register struct mbuf *m, *n; 95 register struct ucb *up; 96 register off; 97 sequence last; 98 99 COUNT(SSS_SND); 100 tp = wp->w_tcb; 101 up = tp->t_ucb; 102 103 last = tp->snd_off; 104 105 /* count number of mbufs in send data */ 106 107 for (m = n = (struct mbuf *)wp->w_dat; m != NULL; m = m->m_next) { 108 up->uc_ssize++; 109 last += m->m_len; 110 } 111 112 /* find end of send buffer and append data */ 113 114 if ((m = up->uc_sbuf) != NULL) { /* something in send buffer */ 115 while (m->m_next != NULL) { /* find the end */ 116 m = m->m_next; 117 last += m->m_len; 118 } 119 last += m->m_len; 120 121 /* if there's room in old buffer for new data, consolidate */ 122 123 off = m->m_off + m->m_len; 124 while (n != NULL && (MSIZE - off) >= n->m_len) { 125 bcopy((caddr_t)((int)n + n->m_off), 126 (caddr_t)((int)m + off), n->m_len); 127 m->m_len += n->m_len; 128 off += n->m_len; 129 up->uc_ssize--; 130 n = m_free(n); 131 } 132 m->m_next = n; 133 134 } else /* nothing in send buffer */ 135 up->uc_sbuf = n; 136 137 if (up->uc_flags & UEOL) { /* set EOL */ 138 tp->snd_end = last; 139 } 140 141 if (up->uc_flags & UURG) { /* urgent data */ 142 tp->snd_urp = last+1; 143 tp->snd_urg = TRUE; 144 } 145 146 send(tp); 147 148 return(SAME); 149 } 150 151 sss_rcv(wp) /* rcv request on open connection (42) */ 152 struct work *wp; 153 { 154 register struct tcb *tp; 155 156 COUNT(SSS_RCV); 157 tp = wp->w_tcb; 158 159 send_ctl(tp); /* send new window */ 160 present_data(tp); 161 162 return(SAME); 163 } 164 165 cls_nsy(wp) /* abort request on unsynced connection (44) */ 166 struct work *wp; 167 { 168 169 COUNT(CLS_NSY); 170 t_close(wp->w_tcb, UABORT); 171 172 return(CLOSED); 173 } 174 175 cls_syn(wp) /* abort request on synced connection (45) */ 176 struct work *wp; 177 { 178 register struct tcb *tp; 179 180 COUNT(CLS_SYN); 181 tp = wp->w_tcb; 182 183 tp->snd_rst = TRUE; /* send reset */ 184 send_null(tp); 185 t_close(tp, UABORT); 186 187 return(CLOSED); 188 } 189 190 cls_act(wp) /* net closing open connection (47) */ 191 struct work *wp; 192 { 193 194 COUNT(CLS_ACT); 195 t_close(wp->w_tcb, UNETDWN); 196 197 return(CLOSED); 198 } 199 200 cls_err(wp) /* invalid user request in closing states */ 201 struct work *wp; 202 { 203 COUNT(CLS_ERR); 204 to_user(wp->w_tcb->t_ucb, UCLSERR); 205 206 return(SAME); 207 } 208 209 timers(wp) /* timer processor (14,17,34,35,36,37,38) */ 210 struct work *wp; 211 { 212 register struct tcb *tp; 213 register type; 214 215 COUNT(TIMERS); 216 tp = wp->w_tcb; 217 type = wp->w_stype; 218 219 switch (type) { 220 221 case TINIT: /* initialization timer */ 222 223 if (!tp->syn_acked) { /* haven't got ACK of our SYN (35) */ 224 225 t_close(tp, UINTIMO); 226 return(CLOSED); 227 } 228 break; 229 230 case TFINACK: /* fin-ack timer */ 231 232 if (tp->t_state == TIME_WAIT) { 233 234 /* can be sure our ACK of for FIN was rcvd, 235 can close if no data left for user */ 236 237 if (rcv_empty(tp)) { /* 14 */ 238 t_close(tp, UCLOSED); 239 return(CLOSED); 240 } else /* 17 */ 241 return(RCV_WAIT); 242 243 } else if (tp->t_state == CLOSING1) /* 37 */ 244 245 /* safe to close */ 246 247 tp->waited_2_ml = TRUE; 248 249 break; 250 251 case TREXMT: /* retransmission timer */ 252 253 /* set up for a retransmission, increase rexmt time 254 in case of multiple retransmissions. */ 255 256 if (tp->t_rexmt_val > tp->snd_una) { /* 34 */ 257 tp->snd_nxt = tp->snd_una; 258 tp->rexmt = TRUE; 259 tp->t_xmtime = tp->t_xmtime << 1; 260 if (tp->t_xmtime > T_REMAX) 261 tp->t_xmtime = T_REMAX; 262 send(tp); 263 } 264 break; 265 266 case TREXMTTL: /* retransmit too long */ 267 268 /* tell user */ 269 270 if (tp->t_rtl_val > tp->snd_una) /* 36 */ 271 to_user(tp->t_ucb, URXTIMO); 272 273 /* if user has already closed, abort the connection */ 274 275 if (tp->usr_closed) { 276 t_close(tp, URXTIMO); 277 return(CLOSED); 278 } 279 break; 280 281 case TPERSIST: /* persist timer */ 282 283 /* force a byte send through closed window */ 284 285 tp->force_one = TRUE; /* 38 */ 286 send(tp); 287 break; 288 } 289 290 return(SAME); 291 } 292