patch-2.1.127 linux/net/ipv4/tcp.c
Next file: linux/net/ipv4/tcp_input.c
Previous file: linux/net/ipv4/sysctl_net_ipv4.c
Back to the patch index
Back to the overall index
- Lines: 193
- Date:
Sat Nov 7 11:00:32 1998
- Orig file:
v2.1.126/linux/net/ipv4/tcp.c
- Orig date:
Mon Oct 5 13:13:48 1998
diff -u --recursive --new-file v2.1.126/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.127 1998/10/04 07:04:32 davem Exp $
+ * Version: $Id: tcp.c,v 1.130 1998/11/07 14:36:10 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -860,8 +860,8 @@
if(copy > seglen)
copy = seglen;
+ /* Determine how large of a buffer to allocate. */
tmp = MAX_HEADER + sk->prot->max_header;
- queue_it = 0;
if (copy < min(mss_now, tp->max_window >> 1) &&
!(flags & MSG_OOB)) {
tmp += min(mss_now, tp->max_window);
@@ -876,6 +876,7 @@
queue_it = 1;
} else {
tmp += copy;
+ queue_it = 0;
}
skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
@@ -1452,7 +1453,7 @@
tcp_synq_init(tp);
}
-void tcp_close(struct sock *sk, unsigned long timeout)
+void tcp_close(struct sock *sk, long timeout)
{
struct sk_buff *skb;
int data_was_unread = 0;
@@ -1522,7 +1523,6 @@
struct task_struct *tsk = current;
struct wait_queue wait = { tsk, NULL };
- tsk->timeout = timeout;
add_wait_queue(sk->sleep, &wait);
release_sock(sk);
@@ -1530,12 +1530,11 @@
tsk->state = TASK_INTERRUPTIBLE;
if (!closing(sk))
break;
- schedule();
- if (signal_pending(tsk) || !tsk->timeout)
+ timeout = schedule_timeout(timeout);
+ if (signal_pending(tsk) || !timeout)
break;
}
- tsk->timeout=0;
tsk->state = TASK_RUNNING;
remove_wait_queue(sk->sleep, &wait);
@@ -1547,8 +1546,8 @@
*/
tcp_check_fin_timer(sk);
- sk->dead = 1;
release_sock(sk);
+ sk->dead = 1;
}
/*
@@ -1619,6 +1618,8 @@
req->class->destructor(req);
tcp_openreq_free(req);
sk->ack_backlog--;
+ if(sk->keepopen)
+ tcp_inc_slow_timer(TCP_SLT_KEEPALIVE);
/*
* This does not pass any already set errors on the new socket
@@ -1657,48 +1658,86 @@
return -EFAULT;
switch(optname) {
- case TCP_MAXSEG:
-/* values greater than interface MTU won't take effect. however at
- * the point when this call is done we typically don't yet know
- * which interface is going to be used
- */
- if(val<1||val>MAX_WINDOW)
- return -EINVAL;
- tp->user_mss=val;
- return 0;
- case TCP_NODELAY:
- sk->nonagle=(val==0)?0:1;
- return 0;
- default:
- return(-ENOPROTOOPT);
+ case TCP_MAXSEG:
+ /* values greater than interface MTU won't take effect. however at
+ * the point when this call is done we typically don't yet know
+ * which interface is going to be used
+ */
+ if(val < 1 || val > MAX_WINDOW)
+ return -EINVAL;
+ tp->user_mss = val;
+ return 0;
+
+ case TCP_NODELAY:
+ /* You cannot try to use this and TCP_CORK in
+ * tandem, so let the user know.
+ */
+ if (sk->nonagle == 2)
+ return -EINVAL;
+ sk->nonagle = (val == 0) ? 0 : 1;
+ return 0;
+
+ case TCP_CORK:
+ /* When set indicates to always queue non-full frames.
+ * Later the user clears this option and we transmit
+ * any pending partial frames in the queue. This is
+ * meant to be used alongside sendfile() to get properly
+ * filled frames when the user (for example) must write
+ * out headers with a write() call first and then use
+ * sendfile to send out the data parts.
+ *
+ * You cannot try to use TCP_NODELAY and this mechanism
+ * at the same time, so let the user know.
+ */
+ if (sk->nonagle == 1)
+ return -EINVAL;
+ if (val != 0) {
+ sk->nonagle = 2;
+ } else {
+ sk->nonagle = 0;
+
+ if (tp->send_head) {
+ lock_sock(sk);
+ if (tp->send_head &&
+ tcp_snd_test (sk, tp->send_head))
+ tcp_write_xmit(sk);
+ release_sock(sk);
+ }
+ }
+ return 0;
+
+ default:
+ return -ENOPROTOOPT;
};
}
-int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
+int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval,
int *optlen)
{
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
- int val;
- int len;
+ int val, len;
if(level != SOL_TCP)
return tp->af_specific->getsockopt(sk, level, optname,
optval, optlen);
-
+
if(get_user(len,optlen))
return -EFAULT;
-
- len = min(len,sizeof(int));
+
+ len = min(len, sizeof(int));
switch(optname) {
- case TCP_MAXSEG:
- val=tp->user_mss;
- break;
- case TCP_NODELAY:
- val=sk->nonagle;
- break;
- default:
- return(-ENOPROTOOPT);
+ case TCP_MAXSEG:
+ val = tp->user_mss;
+ break;
+ case TCP_NODELAY:
+ val = (sk->nonagle == 1);
+ break;
+ case TCP_CORK:
+ val = (sk->nonagle == 2);
+ break;
+ default:
+ return -ENOPROTOOPT;
};
if(put_user(len, optlen))
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov