[libmill] Re: Full duplex tcp proxy

  • From: Martin Sustrik <sustrik@xxxxxxxxxx>
  • To: Marek Majkowski <majek04@xxxxxxxxx>
  • Date: Mon, 29 Feb 2016 07:27:24 +0100

Ah, yes, I know that Golang uses socket close as a sychronisation mechanism among goroutines.

Anyway, the network classes in libmill are just simple socket wrappers to help people get started with the library. No point in making them more complex. Just copy the code to your project and make any modifications you need there.

Martin

On 2016-02-29 06:06, Marek Majkowski wrote:

Actually, it's surprisingly hard to come up with a test case. I think
the problem is that tcpclose(x) doesn't cause blocking tcprecv(x) in
another coroutine to fail. You may argue that tcpclose() is invalid in
this context since the socket is shared between more than one
coroutine therefore causing read-after-free. The workaround I found is
to separate the lifetime of the socket (tcp layer) from lifetime of
the socket on the libmill layer. Namely - to call shutdown(2) on the
underlying file descriptor. This unblocks the blocked read(), and all
goes well.

The updated code of a dumb TCP proxy:
https://gist.github.com/majek/0f9b4f578c9da7ff09e5

Far more complex than it should be. Missing features:
 - There is no way to extract tcpsock file descriptor (to be further
given to shutdown()). So either please implement tcpsockfd() or
tcpshutdown().
 - There is no way to receive and send a "packet" worth of data.
tcprecv(,x) waits for exactly X bytes to arrive. For the proxy use
case I don't want any internal buffering.

Cheers,
    Marek



On Sat, Feb 27, 2016 at 11:54 PM, Martin Sustrik <sustrik@xxxxxxxxxx> wrote:
Can you please provide a standalone tests case? I.e. one that you run and it
fails.

Thanks!
Martin


On 2016-02-27 16:22, Marek Majkowski wrote:

Hi!

I'm trying to write a full duplex tcp proxy. Sounds easy, right.
Here's the code:
https://gist.github.com/majek/c2889943d6cbcc6d6972

Since one coroutine can block only on one operation (read or write) I
need to use two coroutines. One reading from one local socket, another
reading from the remote.

But here is the thing - if there is an error on one socket, I tear
down and close both sockets. Sadly, this doesn't seem to wake up the
other coroutine.

I'm pretty sure equivalent code works in golang.

What am I doing wrong?

Cheers,
  Marek




Other related posts: