commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hurd] 22/37: Backport Linux changes for proper TCP EOF handling


From: Samuel Thibault
Subject: [hurd] 22/37: Backport Linux changes for proper TCP EOF handling
Date: Mon, 09 Feb 2015 09:59:10 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to annotated tag upstream/hurd/0.5.git20150208
in repository hurd.

commit 87fad50310f2bd0dcc990e80e23b09768918cf5b
Author: Samuel Thibault <address@hidden>
Date:   Sat Jan 3 17:44:01 2015 +0100

    Backport Linux changes for proper TCP EOF handling
    
    Notably when remote eagerly sends a RST: we want to return EOF to the
    application, not EPIPE.
    
    * pfinet/linux-src/net/ipv4/tcp_output.c (tcp_connect): Set sk->done to 0.
    * pfinet/linux-src/net/ipv4/tcp_input.c (tcp_fin): Set RCV_SHUTDOWN, and
    sk->done to 1.
    * pfinet/linux-src/net/ipv4/tcp.c (tcp_recv_urg): Only return ENOTCONN when
    we never actually connect.  Always return 0 when reception is closed.
    (tcp_recvmsg): When any data is available, ignore errors and EOF.  When no
    data is available, first check for reception being closed, then for errors.
---
 pfinet/linux-src/net/ipv4/tcp.c        | 59 ++++++++++++++++------------------
 pfinet/linux-src/net/ipv4/tcp_input.c  |  3 ++
 pfinet/linux-src/net/ipv4/tcp_output.c |  1 +
 3 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/pfinet/linux-src/net/ipv4/tcp.c b/pfinet/linux-src/net/ipv4/tcp.c
index 8cde385..1a05743 100644
--- a/pfinet/linux-src/net/ipv4/tcp.c
+++ b/pfinet/linux-src/net/ipv4/tcp.c
@@ -1059,13 +1059,11 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
        if (sk->err)
                return sock_error(sk);
 
-       if (sk->done)
+       if (sk->state == TCP_CLOSE && !sk->done)
                return -ENOTCONN;
 
-       if (sk->state == TCP_CLOSE || (sk->shutdown & RCV_SHUTDOWN)) {
-               sk->done = 1;
+       if (sk->state == TCP_CLOSE || (sk->shutdown & RCV_SHUTDOWN))
                return 0;
-       }
 
        lock_sock(sk);
        if (tp->urg_data & URG_VALID) {
@@ -1177,9 +1175,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
        int err = 0;
        int target = 1;         /* Read at least this many bytes */
 
-       if (sk->err)
-               return sock_error(sk);
-
        if (sk->state == TCP_LISTEN)
                return -ENOTCONN;
 
@@ -1261,36 +1256,36 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                if (copied >= target)
                        break;
 
-               /*
-                  These three lines and clause if (sk->state == TCP_CLOSE)
-                  are unlikely to be correct, if target > 1.
-                  I DO NOT FIX IT, because I have no idea, what
-                  POSIX prescribes to make here. Probably, it really
-                  wants to lose data 8), if not all target is received.
-                                                                --ANK
-                */
-               if (sk->err && !(flags&MSG_PEEK)) {
-                       copied = sock_error(sk);
-                       break;
-               }
+               if (copied) {
+                       if (sk->err ||
+                           sk->state == TCP_CLOSE ||
+                           (sk->shutdown & RCV_SHUTDOWN) ||
+                           nonblock)
+                               break;
+               } else {
+                       if (sk->done)
+                               break;
 
-               if (sk->shutdown & RCV_SHUTDOWN) {
-                       sk->done = 1;
-                       break;
-               }
+                       if (sk->err) {
+                               copied = sock_error(sk);
+                               break;
+                       }
+
+                       if (sk->shutdown & RCV_SHUTDOWN)
+                               break;
 
-               if (sk->state == TCP_CLOSE) {
-                       if (!sk->done) {
-                               sk->done = 1;
+                       if (sk->state == TCP_CLOSE) {
+                               if (!sk->done) {
+                                       copied = -ENOTCONN;
+                                       break;
+                               }
                                break;
                        }
-                       copied = -ENOTCONN;
-                       break;
-               }
 
-               if (nonblock) {
-                       copied = -EAGAIN;
-                       break;
+                       if (nonblock) {
+                               copied = -EAGAIN;
+                               break;
+                       }
                }
 
                cleanup_rbuf(sk, copied);
diff --git a/pfinet/linux-src/net/ipv4/tcp_input.c 
b/pfinet/linux-src/net/ipv4/tcp_input.c
index e84eaf4..e2dfc15 100644
--- a/pfinet/linux-src/net/ipv4/tcp_input.c
+++ b/pfinet/linux-src/net/ipv4/tcp_input.c
@@ -1129,6 +1129,9 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, 
struct tcphdr *th)
 
        tcp_send_ack(sk);
 
+       sk->shutdown |= RCV_SHUTDOWN;
+       sk->done = 1;
+
        if (!sk->dead) {
                sk->state_change(sk);
                sock_wake_async(sk->socket, 1);
diff --git a/pfinet/linux-src/net/ipv4/tcp_output.c 
b/pfinet/linux-src/net/ipv4/tcp_output.c
index 9ea4b7a..a15b7b3 100644
--- a/pfinet/linux-src/net/ipv4/tcp_output.c
+++ b/pfinet/linux-src/net/ipv4/tcp_output.c
@@ -922,6 +922,7 @@ void tcp_connect(struct sock *sk, struct sk_buff *buff, int 
mtu)
        tp->rcv_nxt = 0;
 
        sk->err = 0;
+       sk->done = 0;
        
        /* We'll fix this up when we get a response from the other end.
         * See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]