-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handling close in a websocket proxy #316
Comments
Describe the problem you are trying to solve in more detail. |
Honestly, this is pretty self-explanatory if you know what |
I am asking you to describe the problem you are trying to solve in your application, not a description of the context package and how the package is used elsewhere. |
For example, when I am dialing, instead of |
Why does the timeout not work for your application? Describe the problem. I am not going to sprinkle magic context dust over the package with the hope that it will solve actual problems. |
As I said, context is created and suggested for problems like this. Let me give you a more detailed and realistic situation. There's a MITM websocket service running, two goroutines respectively handle connections from (client to self) and (self to the real server). Say that I am reading data from (self to the real server) connection and to send it to the client side, but since the real server is not sending anything, the procedure is blocked. Now, the client closed the (client to self) connection, so I am supposed to be closing (self to the real server) connection as well. However, since the (self to the real server) goroutine is still blocked on reading, I can do nothing about it. Now I know that I can set a ReadTimeout on (self to the real server) side, and detect if the other (client to self) connection is still alive after every timeout, but a cancellable context would be a perfect and quick solution for this: simply calls |
Context cancelation is not the right solution for handling close in a websocket proxy. Let me know if this is an actual problem you are encountering. If it is, then I'lll take the time to describe how to handle close in a proxy. I know what the context package is and the problems the package is intended to solve. I am willing to add context related features based on actual application requirements. I don't want to spend time reviewing or implementing features that nobody needs. |
Yes, please go ahead. My current solution is inserting detection anywhere in the code, which is really messy. |
The RFC describes how to cleanly close a websocket connection. I assume that you have two connections, Create two channels for communicating that the connections are closed:
Run goroutines to copy the connections:
where copyConn is:
The goal of the code above is to show how to coordinate the closing handshake across two goroutines. A robust proxy application will use PING/PONG and deadlines to detect dead connections and peers. The most complicated part of the code is related to closing handshake. If the handshake is dropped, the code reduces to
Coordinating the closing handshake between two connections is an application problem. The above code can be rewritten to use contexts instead of plain channels and timers, but that's overkill. In any case, it's a layer above the websocket package.
A connection is not usable after a timeout error. This does not work.
Close the connection to cause a read to return with an error. |
That'll do, thanks. |
Apologies for commenting on an old closed issue, but I'm still learning Go, and the code above, while functional, seems less idiomatic than using context.Context, at least that's the impression I've gotten from the reading I've done (and implementing exactly what the OP was trying to do). As I understand it, context.Context is created to solve exactly this kind of problem without having to create a bunch of signal channels to keep track of everything, and through the Context.Done() channel, you can control the running of all your own internal goroutines while keeping them synchronized with external resources that support context.Context. It's the same reason that CancellationTokens are used in .NET, for example. They're a really useful pattern for keeping disparate asynchronous systems in lock-step when everything needs to be closed down (due to error, disconnect, etc.) I see that Context support has been merged in as of a few days ago, so maybe it's beyond moot at this point, but mainly I'm trying to be a better Go programmer and trying to understand the language features (goroutine, context.Context, channels, etc.) a bit better. Also, context.Context support will result in much cleaner code in my own implementation as I can clean up a lot of signal channels and just rely on <-context.Context.Done(), as well as the other features of context.Context like Deadlines. (As an aside, grpc recommends using Deadlines for all grpc connections as a best practice.) Again, apologies for beating a bit of a dead horse, here. |
The OP's actual issue is implementing close in a websocket proxy. I updated the title of the issue to reflect this. Coordinating the application's goroutines, sending close messages and and receiving close messages is the responsibility of the application in this scenario. This package provides all of the functionality required to implement this scenario idiomatically. Context support is not needed for the scenario. Open a new issue if you require some functionality not present in this package. |
I guess what I'm really asking is for clarification about this statement:
In my reading that sounds like exactly what context cancellation was written to handle. I don't understand why one wouldn't want to use context cancellation (assuming context support were available throughout your service stack). Again, I'm just trying to understand the core concepts and why context is not considered idiomatic in this case. |
My statement refers to functionality implemented by this package. The functionality needed from this package for proxy shutdown is: write a message to a connection, read a message from a connection and close a connection. These features are exposed as methods on the connection object. Exposing these features through context cancelation is not needed, nor does it make sense. This is not an appropriate forum for learning about the context package. |
Support wanted for better coroutine manipulation.
The text was updated successfully, but these errors were encountered: