- if (send(tp))
- return (1);
- tcp_sndnull(tp);
- return (0);
-}
-tcp_sndnull(tp) /* send only control information */
- register struct tcb *tp;
-{
-COUNT(SEND_NULL);
-
- tcp_output(tp, 0, 0, (struct mbuf *)0);
- tp->tc_flags &= ~TC_ACK_DUE;
-}
-
-tcp_sndrst(tp, n) /* send a reset */
- register struct tcb *tp;
- register struct th *n;
-{
-COUNT(SEND_RST);
- /* don't send a reset in response to a reset */
-
- if (n->th_flags&TH_RST)
- return;
-
- tp->tc_flags |= TC_SND_RST;
-
- if (n->th_flags&TH_ACK)
- tp->snd_nxt = n->t_ackno;
-
- tp->tc_flags &= ~TC_SYN_RCVD;
- tcp_sndnull(tp);
- tp->tc_flags &= ~TC_SND_RST;
-}
-
-/*
- * Create template to be used to send tcp packets on a connection.
- * Call after host entry created, allocates an mbuf and fills
- * in a skeletal tcp/ip header, minimizing the amount of work
- * necessary when the connection is used.
- */
-struct th *
-tcp_template(tp)
- struct tcb *tp;
-{
- register struct host *h = tp->t_ucb->uc_host;
- register struct mbuf *m;
- register struct th *n;
- register struct ip *ip;
-
- if (h == 0)
- return (0);
- m = m_get(1);
- if (m == 0)
- return (0);
- m->m_off = MMAXOFF - sizeof (struct th);
- m->m_len = sizeof (struct th);
- n = mtod(m, struct th *);
- n->t_next = n->t_prev = 0;
- n->t_x1 = 0;
- n->t_pr = TCPROTO;
- n->t_len = htons(sizeof (struct th) - sizeof (struct ip));
- n->t_s.s_addr = n_lhost.s_addr;
- n->t_d.s_addr = h->h_addr.s_addr;
- n->t_src = htons(tp->t_lport);
- n->t_dst = htons(tp->t_fport);
- n->t_seq = 0;
- n->t_ackno = 0;
- n->t_x2 = 0;
- n->t_off = 5;
- n->th_flags = 0;
- n->t_win = 0;
- n->t_sum = 0;
- n->t_urp = 0;
- return (n);
-}
-
-tcp_output(tp, flags, len, dat)
- register struct tcb *tp;
- register int flags;
- int len;
- struct mbuf *dat;
-{
- register struct mbuf *m;
- register struct th *t;
- register struct ip *ip;
- int i;
-#ifdef TCPDEBUG
- struct tcp_debug tdb;
-#endif
-COUNT(SEND_TCP);
+ ti->ti_flags = flags;
+ /*
+ * Calculate receive window. Don't shrink window,
+ * but avoid silly window syndrome.
+ */
+ if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg)
+ win = 0;
+ if (win > IP_MAXPACKET)
+ win = IP_MAXPACKET;
+ if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
+ win = (long)(tp->rcv_adv - tp->rcv_nxt);
+ if (win > IP_MAXPACKET)
+ win = IP_MAXPACKET;
+ ti->ti_win = htons((u_short)win);
+ if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
+ ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
+ ti->ti_flags |= TH_URG;
+ } else
+ /*
+ * If no urgent pointer to send, then we pull
+ * the urgent pointer to the left edge of the send window
+ * so that it doesn't drift into the send window on sequence
+ * number wraparound.
+ */
+ tp->snd_up = tp->snd_una; /* drag it along */
+ /*
+ * If anything to send and we can send it all, set PUSH.
+ * (This will keep happy those implementations which only
+ * give data to the user when a buffer fills or a PUSH comes in.)
+ */
+ if (len && off+len == so->so_snd.sb_cc)
+ ti->ti_flags |= TH_PUSH;
+
+ /*
+ * Put TCP length in extended header, and then
+ * checksum extended header and data.
+ */
+ if (len + optlen)
+ ti->ti_len = htons((u_short)(sizeof(struct tcphdr) +
+ optlen + len));
+ ti->ti_sum = in_cksum(m,
+ (int)(sizeof (struct tcpiphdr) + (int)optlen + len));
+
+ /*
+ * In transmit state, time the transmission and arrange for
+ * the retransmit. In persist state, just set snd_max.
+ */
+ if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
+ tcp_seq startseq = tp->snd_nxt;
+
+ /*
+ * Advance snd_nxt over sequence space of this segment.
+ */
+ if (flags & TH_SYN)
+ tp->snd_nxt++;
+ if (flags & TH_FIN) {
+ tp->snd_nxt++;
+ tp->t_flags |= TF_SENTFIN;
+ }
+ tp->snd_nxt += len;
+ if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
+ tp->snd_max = tp->snd_nxt;
+ /*
+ * Time this transmission if not a retransmission and
+ * not currently timing anything.
+ */
+ if (tp->t_rtt == 0) {
+ tp->t_rtt = 1;
+ tp->t_rtseq = startseq;
+ tcpstat.tcps_segstimed++;
+ }
+ }