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 <skip.tavakkol...@gmail.com> 
> 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)
>   }
> 
> 

Reply via email to