Dispatch websocket connections based on subprotocol - websocket

is it technically possible to run multiple websocket servers that listen on the same port and dispatch using the subprotocol name ? E.g. a process that would handle "protocol1" and another that would handle "protocol2". My guess is that it is not, since TCP cannot conditionally accept a connection, so the only way would be some kind of socket ownership transfer.

Actually, it would be possible to achieve by using a Proxy as a load balancer, which isn't something I tried managing before... So I can't post a demo configuration file.
I know Apache will allow you to decide on a proxy path according to the request headers - this means you can check the sub protocol before forwarding the data... But this is mostly a conceptual solution I never tested.

This question is tagged WebSocket++, so I will answer from the context of that library.
Maybe, depending on exactly what you mean. WebSocket++ will let you build one program that can internally handle multiple subprotocols. WebSocket++ has a pre-acceptance hook called the validate handler. In the validate handler you are presented with a list of subprotocols the client has requested and may choose which one you want to accept (or none if your server doesn't support any).
This isn't the same as conditionally accepting the TCP connection itself, but does let you conditionally accept the WebSocket connection. Once accepted your app can inspect the selected subprotocol in the open handler and choose which logic to use to process the connection.
A WebSocket++ based program can juggle multiple connections on multiple subprotocols simultaneously. If you truly want multiple independent processes handling each then the best WebSocket++ will be able to do is act as a proxy for those connections.

Related

wanted - golang wrapper around Dial/Listen to handle tcp server/client communication

In golang, when you make a client/server combination with Listen/Accept on the server and Dial on the client, as far as I can tell writing to the client doesn't actually guarantee the full transmission chain. IE when you say:
_len, _err := conn.Write([]byte("sent"))
it is possible that the text you send may reach the buffer of the client machine but not the client itself. In other words, if the client becomes unavailable, _err may still be unset and _len may still show the correct length of bytes being sent. I noticed this by killing the connection between my server and client and monitoring the return status of conn.Write() manually and seeing that it didn't show an error.
In other words, just using these tools out of the box won't guarantee delivery, and I was hoping that there was a go library that implemented a client acknowledgement to insure this further guarantee. I'd like to say something like:
_len, _err := _write(conn, "sent\n")
and have guarantees that if the client goes away that _err will be set accordingly - assuming a specific timeout between the send and an acknowledgement from the client.
Is there a standard library like this? I could write my own wrapper to do this, but I have a feeling the logic to do this correctly would be somewhat intricate.
thanks much again for any info,
Ed
Is there a standard library like this?
There is no standard library for this. How application level acknowledgements are done is specified in the specific application protocol, i.e. a protocol like HTTP (web), SMTP (mail delivery), SIP (VoIP) etc. And this protocol must be spoken in both client and server. There is no way for a client to enforce some application level acknowledgement if it is not part of the protocol specification and the server will not explicitly send it.
Therefore you either need to pick an application protocol which supports the semantics you need and use it on both client and server. Or you need to define your own application protocol which supports the exact semantics you need and implement it yourself on both sides.

How do I respond to multiple gRPC clients?

I am building an application which can have multiple gRPC servers and definitely will have multiple gRPC clients, I wanted to know, how to identify on server side that this is the client I am talking to and only send data to that client. I am using bidirectional streaming RPC and right now the data gets broadcasted to every client and I don't want that. What functions in go gRPC make it possible or how can I implement it?
There are two ways to read this question. One way is to read it as the auth problem as answered before. The second way is how I read it, as a connection/session problem.
When the client connects, the grpc server will invoke a function to implement the call in its own goroutine, and that function will be only talking to the client that initiated that call. So, the struct you registered as your grpc server will be shared among many connections, but each connection will run in its own goroutine, and will only talk to the client that initiated it. That also means you have to make sure the grpc server implementation is thread-safe.
You mentioned data is being broadcasted to every client? There is no broadcast in grpc, are you sure that's what's happening?
This sounds like a common authentication/authorization problem that ultimately won't have much to do with gRPC or Go.
You need a way for a client to indicate who they are. Personally I'm a fan of JWTs. In a standard HTTP request, there are authorization headers that can indicate who is making the request. Similarly, gRPC supports meta data attached to each remote call. In my current work project, every call must have a JWT in the meta data or else I don't process the request. Every call except the login endpoint that is.
I haven't looked into how to get details like a gRPC client's IP address or other information about a client's connection but chances are that anything provided by gRPC's generated code is something potentially faked by the client. When architected correctly, JWTs can offer cryptographic confidence that the client is who they claim to be.

Which is better: multiple web socket endpoints or single web socket endpoint in Java EE7

Java EE 7 allows you to create new endpoints very easily through annotations. However, I was wondering is having multiple endpoints one to handle each message type a good idea or should I have just one endpoint facade for everything?
I am leaning towards having one single end-point facade based on the theory that each endpoint creates a new socket connection to the client. However, that theory could be incorrect and Web Socket may be implemented so that it will use just one TCP/IP socket connection regardless of how many web socket end points are connected so long as they connect to the same host:port.
I am asking specifically for Java EE 7, as there may be other web socket server implementations that may do things differently.
Just noticed an ambiguity on my question re: message types. When I say message types I meant different kinds of application messages not native message types such as "binary" or "text". As such I marked #PavelBucek answer as the accepted one.
However, I did try an experiment with Glassfish and having two end points. My suspicions were correct and that there is a TCP connection established per connected endpoint. This would cause more load on the server side if there is more than one websocket endpoint being used on a single page.
As such I concluded that there should be only one endpoint to handle the application messages provided that everything is a single native type.
This would mean that the application needs to do the dispatching rather than relying on some higher level API to do it for us.
The only valid answer here is the latter option - having multiple endpoints.
See WebSocket spec chaper 2.1.3:
The API limits the registration of MessageHandlers per Session to be one MessageHandler per native websocket message type. [WSC 2.1.3-1] In other words, the developer can only register at most one Mes- sageHandler for incoming text messages, one MessageHandler for incoming binary messages, and one MessageHandler for incoming pong messages. The websocket implementation must generate an error if this restriction is violated [WSC 2.1.3-2].
As for using or not using multiple TCP connections - AFAIK currently there will be new connection for every client and there is no easy way how you can force anything else. WebSocket multiplexing should solve it, but I don't think any WebSocket API implementation support it (I might be wrong..)

How to handle different (url) websocket connections in netty

Websocket example in netty (examples) has a http request handler which:
performs hand shaking (at first)
(then) handles different types of WebSocket frames, eventually "TextWebSocketFrame"s.
There is only one url for websocket connections in this example.
The problem is, when TextWebSocketFrame based actual websocket communication starts, there is no direct way to determine websocket url from TextWebSocketFrames themselves (correct me if I am wrong).
So, how to handle different (url) websocket connections in netty?
One solution can be registering channels and their "websocket connection urls" during handshaking process.
The other is having only one websocket connection url and resolving different contexts by adding extra information to websocket messages (TextWebSocketFrames).
I don't find these solutions elegant, so any ideas?
It is my understanding that when you perform a web socket handshake, it is to a specific URL. That is specified in the web socket standard. See RFC 6455. Hence, there is no URL information in the TextWebSocketFrame because the assumption is that the frame will be sent to the URL to which the socket is bound.
To handle different URLs, you will have to either:
Setup a different pipeline and bind to a different IP and/or port for each URL, or
Like you stated, customise the hand shake and store the URL with the channel.
Personally, I've just used JSON in a TextWebSocketFrame. In my JSON, I have a field that states the intended action. This field is used for routing to the appropriate message handler.
I think it comes down to a design decision. WebSockets are intended for long lived connections where a request message can have 0, 1 or > 1 responses. This contrasts the REST style 1 request and 1 responses model.
Hope this helps.
The question "how to handle different (url) websocket connections in netty" does not make sense, I presume that the author meant to ask "how to serve multiple different websocket paths on a single port:host".
The question is valid because the HTTP protocol, (at least version 1.1,) WebSockets, and web browsers all support this scenario:
Client connects to server and the two start exchanging HTTP request/response pairs.
Client sends the HTTP request to upgrade to WebSocket, server honors it, and now a WebSocket is established between client and server.
The original HTTP connection remains open, so client and server can continue exchanging HTTP request/response pairs in parallel to the WebSocket. (In light of this, the term "upgrade" is a misnomer, because the connection is not upgraded at all; instead, a new connection is established for the WebSocket.)
Since the HTTP connection is still available, the client can send another HTTP upgrade request, thus creating another WebSocket. On the client side, it would look like this:
socket1 = new WebSocket( "https://acme.com:8443/alpha" );
socket2 = new WebSocket( "https://acme.com:8443/bravo" );
However, you can't have that, because Netty in all its magnificent glory and terrifying complexity does not exactly support that, and this is true even now, 10 years after the question was asked.
That's because:
Only one ServerBootstrap can bind to a given port on a given host.
(That's how the socket layer works.)
A ServerBootstrap can only have one "Child Handler".
(ServerBootstrap.childHandler() silently fails to report an error if you invoke it twice, but only the last invocation takes effect.)
A ChannelPipeline can only have one WebSocketServerProtocolHandler.
(Only the first WebSocketServerProtocolHandler that you add works, and Netty silently fails to issue an error if you add more.)
A WebSocketServerProtocolHandler accepts one and only one webSocketPath.
So, there you have it, a port:host can only have one webSocketPath, and that's a Netty limitation.
It might be possible to overcome this limitation by rewriting WebSocketServerProtocolHandler, but #aintNoBodyGotNoTimeFoDat.
Luckily, Netty does support another feature which makes it possible to achieve a similar thing. The constructor of WebSocketServerProtocolHandler supports a poorly documented and poorly named checkStartsWith parameter which, if set to true, will cause the handler to honor websocket negotiation requests not only on the given webSocketPath but also for any webSocket path that starts with the given webSocketpath and continues with a '?' or a '/' followed by other stuff. So, the code on the client would then look like this:
socket1 = new WebSocket( "https://acme.com:8443/allWebSocketsHere/alpha" );
socket2 = new WebSocket( "https://acme.com:8443/allWebSocketsHere/bravo" );
If you decide to build your netty server to handle this, the next problem you will face is how to obtain the "/allWebSocketsHere/alpha" and "allWebSocketsHere/bravo" parts. Luckily, someone else has already figured that out, see "Netty: How to use query string with websocket?" https://stackoverflow.com/a/47897963/773113

In Windows, how do I find out which process is on the other end of a local network socket?

That is to say, if I have a server listening on 127.0.0.1, and a TCP connection comes in, how can I determine the process id of the client?
Also if there isn't an API for this, where would I be able to extract the information from in a more hackish manner?
(The purpose of this is to modify a local HTTP proxy server to accept or deny requests based on the requesting process.)
Edit: palacsint's answer below led me to find this answer to a similar question which is just what's needed
netstat -a -o
prints it. I suppose they are on the same machine becase you are listening on 127.0.0.1.
The only way to do this is if the connecting process sends some sort of custom headers which contains identifier. This is due to the fact that the networking layer is completely separated from the application layer (hint: OSI MODEL. This way it is possible to write lower layers software without caring what happens above as long as the messages exchanged (read: networking packets) follow a pre-determined format (read: use the same protocol).

Resources