Olivier Baudron <[EMAIL PROTECTED]> writes:

> A connects to B and forwards a local port (say 8080) to a http port of an
> internet server (say www.google.com):
> A:~$ lsh -L 8080:www.google.com:80 B
> 
> Next A download a web page through the tunnel:
> In an other xterm:
> A:~$ lynx localhost:8080/
> 
> From this point lynx receives the datas and freezes, because it does not
> receive any tcp Fin flag from port 8080, whereas www.google.com delivered
> the page. So the situation is that the connection between B and google is
> half-closed (B sent a Fin packet) and the connection between lynx and A:8080
> is opened. And it stands like this indefinitly.

I dont' quite understand the situation, but I don't really know the
TCP handshake details. What do you mean with a "half-closed"
connection? Is it some internal tcp state, or a connection on which
one end have called shutdown to close one direction?

As far as I know, no web servers or clients use shutdown() to close
only one direction of a tcp connection. There are two cases, and they
ought to work like this:

1. Traditional http:

  www.google.com sends out the file, and it's forwarded via opensshd
  and lsh to lynx.
  
  www.google.com closes the connection

  openssh notices its connection was closed, and sends some
  combination of CHANNEL_EOF and CHANNEL_CLOSE.

  lsh receives the CHANNEL_CLOSE and closes the corresponding socket.

2. keep-alive http

  www.google.com sends out the file,, and it's forwarded via opensshd
  and lsh to lynx.

  lynx uses the Content-Length header to figure out when it has
  received the entire file, so it doesn't have to wait for any
  connection to be closed.

  www.google.com may or may not close the connection (and if it does,
  the close event is forwarded to lynx, just as in case 2.

  or lynx closes the connection, in which case a close event is
  forwarded the other way.

The tcp-level handshakes between lynx and lsh and between opensshd and
google are quite independent. And looking at the code, it seems lsh
doesn't handle the case of partially shutdown() connections right.

To figure out what's happening, please run lsh with -v or --debug, and
pay attention to the eof and close messages that are sent and
received. Also try to find out whether or not the HTTP keep-alive
feature is used.

You may also want to try the (untested) patch below, which should make
lsh call shutdown() on the local socket when it receives an
CHANNEL_EOF message on a forwarded channel.

Regards,
/Niels

--- tcpforward.c        2000/11/26 23:26:03     1.56
+++ tcpforward.c        2001/01/23 18:20:36
@@ -142,11 +142,18 @@
 }

 static void
-do_tcpip_eof(struct ssh_channel *c)
+do_tcpip_eof(struct ssh_channel *s)
 {
-  if ( (c->flags & CHANNEL_SENT_EOF)
-       && (c->flags & CHANNEL_CLOSE_AT_EOF))
-    channel_close(c);
+  CAST(tcpip_channel, self, s);
+
+  /* 1 is SHUT_WR, disallow further writes */
+  if (shutdown (self->socket->fd, 1) < 0)
+    werror("do_tcpip_eof, shutdown() failed, (errno = %i): %z\n",
+          errno, STRERROR(errno));
+
+  if ( (s->flags & CHANNEL_SENT_EOF)
+       && (s->flags & CHANNEL_CLOSE_AT_EOF))
+    channel_close(s);
 }

 /* NOTE: Adds the socket to the channel's resource list */

Reply via email to