From mboxrd@z Thu Jan 1 00:00:00 1970 MIME-Version: 1.0 References: In-Reply-To: From: Skip Tavakkolian Date: Sun, 5 Feb 2017 04:24:08 +0000 Message-ID: To: Fans of the OS Plan 9 from Bell Labs <9fans@9fans.net> Content-Type: multipart/alternative; boundary=94eb2c09ab4a7487a90547c0e358 Subject: Re: [9fans] adding TCP half-duplex close Topicbox-Message-UUID: b3684e68-ead9-11e9-9d60-3106f5b1d025 --94eb2c09ab4a7487a90547c0e358 Content-Type: text/plain; charset=UTF-8 cool. On Fri, Feb 3, 2017 at 10:35 PM Bakul Shah wrote: > For the shut_rd case, I think a cleaner impl is to send RST *only* if > there is pending data (received but not read by the user) or new data is > received after the read end is closed. At the moment I don't recall what > BSD does but you don't have to allow draining once the read end is closed. > Just drain and RST! Any user reads should fail. > > I recall having to deal with this in the past while working on a packet > level network proxy. No access to that code now so the above is from > memory. > > > > Sent from my iPad > On Feb 3, 2017, at 5:56 PM, Skip Tavakkolian > wrote: > > Has anyone looked into implementing this? Can anyone comment on the > details? > > For the curious, this is described here: > https://tools.ietf.org/html/rfc1122#page-87 > Go net package (https://github.com/golang/go/issues/17906). > > As I understand it, one would only worry about 'shutdown' if the > connection is in 'Established' state. It is not clear to me what the state > should transition to when the read-end is closed (i.e. shut_rd). Also, > there doesn't not seem to be consistency between different implementations > (Windows,Linux, *BSD) on what should happen to what's already in the read > queue; should it be allowed to drain to the reader or discarded immediately? > > Shutting down the write-end (i.e. 'shut_wr'), should send FIN, and > transition to Finwait1. > > I think the correct mechanics to handle this would be to add two new > messages in tcpctl (/sys/src/9/ip/tcp.c). Then, roughly something like this: > > case 'shut_rd' : > if (Etablished) { > qhangup(rq); > send(RST); // Windows does this and RFC1122 seems to recommend it. > Linux does not. > tcb->rcv.blocked = 1; // all that's needed? > tcb->rcv.wnd = 0; > tcpsetstate(????) // not sure what it should be or should stay > Established? > } > > case 'shut_wr': > if (Established) { > qhangup(wq); > send(FIN) > tcpsetstate(Finwait_1) > } > > > --94eb2c09ab4a7487a90547c0e358 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
cool.

On Fri, Feb 3, 2017 at 10:35 PM Bakul Shah <bakul@bitblocks.com> wrote:
For the shut_rd case, I think a cleaner impl is to send RST *only= * if there is pending data (received but not read by the user) or new data = is received after the read end is closed. At the moment I don't recall = what BSD does but you don't have to allow draining once the read end is= closed. Just drain and RST! Any user reads should fail.

I recall= having to deal with this in the past while working on a packet level network= =C2=A0proxy. No access to that code now so the above is from memory.=



Sent from my iPad
On Feb 3, 2017, at 5:56 PM, Skip Tavakkolian <skip.tavakkolian= @gmail.com> wrote:

Has any= one looked into implementing this?=C2=A0 Can anyone comment on the details?=

For the curious, this is described here: http= s://tools.ietf.org/html/rfc1122#page-87
Go net package (https://github.com/= golang/go/issues/17906).

As I underst= and it, one would only worry about 'shutdown' if the connection is = in 'Established' state. It is not clear to me what the state should= transition to when the read-end is closed (i.e. shut_rd).=C2=A0 Also, ther= e doesn't not seem to be consistency between different implementations = (Windows,Linux, *BSD) on what should happen to what's already in the re= ad queue; should it be allowed to drain to the reader or discarded immediat= ely?

Shutting down the write-end (i.e. 'shut_wr'), should= send FIN, and transition to Finwait1.

I= think the correct mechanics to handle this would be to add two new message= s in tcpctl (/sys/src/9/ip/tcp.c). Then, roughly something like this:
=

case 'shut_rd' :=C2=A0
=C2=A0if = (Etablished) {
=C2=A0 qhangup(rq);
=C2=A0 send(RST); =C2=A0// Windows does this and RFC112= 2 seems to recommend it. Linux does not.
=C2= =A0 tcb->rcv.blocked =3D 1; =C2=A0// all that's needed?
=C2=A0 tcb->rcv.wnd =3D 0;
=C2=A0 tcpsetstate(????) =C2=A0// not sure what it should be or should s= tay Established?
}

case 'shut_w= r':
=C2=A0 if (Established) {
=C2=A0 =C2=A0 qhangup(wq);
=C2=A0 =C2=A0 send(FIN)
=C2=A0 =C2=A0 tcpset= state(Finwait_1)
=C2=A0 }

--94eb2c09ab4a7487a90547c0e358--