StreamLabs socket API using Java - java

I am trying to connect to streamLabs socket API using Java. The API url is
https://sockets.streamlabs.com?token=<socketToken>
This doesnt work because Java expects the socket to be ws://.... When I change it to "ws" format it gives a connection timeout.
Am I missing something? Is this not actually a websocket, if not how would it work?
Here is a link to their documentation: https://streamlabs.readme.io/docs/socket-api
More info: I have tried with both org.asynchttpclient.ws.WebSocket and javax.websocket neither are working

Solved using SocketIo
<dependency>
<groupId>io.socket</groupId>
<artifactId>socket.io-client</artifactId>
<version>1.0.0</version>
</dependency>

Their socket documentation is definitely lacking, their actual websocket url you will be connecting to is
wss://sockets.streamlabs.com/socket.io/?token=<your_socket_api_token>&transport=websocket
Additionally, since it's not really mentioned anywhere, they use an integer, prepended to their messages, as a message type indicator.
0 is the init message type, containing heartbeat interval and timeout
40 is the ping message you will be sending and receiving
41 is invalid token message you will get after connecting with an invalid token
42 will be the actual streamlabs event messages you will be getting
At least that's what I've gathered so far from poking around a bit.

Related

How to fix tinyRadius bad packet: Invalid identifier exception?

I'm using TinyRadius library and a FreeRadius server for authentication in a Spring boot app. Authentication works fine for about 4 requests, then I start getting "Error occurred while authenticating user. Message: bad packet: invalid packet identifier (request: 5, response: 4") The request number matches the one I see in the FreeRadius server by the way.
I had the same problem and I had deployed some workaround. This kind of problem in my situation was very rare. In case of RadiusException I use close() method to close socket and I am creating new object of RadiusClient class, which has the same hostname and secret as old RadiusClient object. In other way I recreate Radius socket. Maybe it's not the best solution, but I didn't want to modify code of TinyRadius library.

how to respond from plain tcp client to MessagingTemplate's sendAndReceive

I'm using channel-adapters (not gateways) to send data with MessagingTemplate's sendAndReceive from spring integration server to a connected nonspring client (or just telnet).
After receiving the data in the client, somewhen I want to reply data to the server and resolve that sendAndReceive-Waiting. I still want to be able to send other data to the server.
How will sendAndReceive detect a response? Right now I can send whatever I want to the server, it will assume it as a new incoming message.
Is there a predefined way, like prefixing a messageid or do I have to implement it manually by interpreting the incoming messages and somehow "resolve" the sendAndReceive-blocker?
MessagingTemplate.sendAndReceive is based on the TemporaryReplyChannel which is placed to the MessageHeaders and afterward some AbstractReplyProducingMessageHandler just uses that header to send reply back.
Yes, the sending Thread is blocked to wait for the reply throughout that TemporaryReplyChannel.
Hope that can help you a bit.
All other your comment regarding TCP/IP isn't clear for me yet...

Heart-beating in STOMP client

The design of my current stomp client process is as follows:
Open stomp connection (sending CONNECT frame)
Subscribe to a feed (send a SUBSCRIBE frame)
Do a loop to continually receive feed:
while (true) {
connection.begin("txt1");
StompFrame message = connection.receive();
System.out.println("message get header"+message.toString());
LOG.info(message.getBody());
connection.ack(message, "txt1");
connection.commit("txt1");
}
My problem with this process is that I get
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)...
and I think the cause of this is mostly because the feed I am subscribed to gives information slower on certain times (as I normally get this error when the weekend comes, holidays or evenings).
I have been reading up on this here and I think this would help with my problem. However, I'm not so sure how to incorporate it with the current layout of my stomp client. Would I have to send a CONNECT header within Step 3?
I am currently using activemq to create my stomp client if that helps.
In the stomp spec we have:
Regarding the heart-beats themselves, any new data received over the
network connection is an indication that the remote end is alive. In a
given direction, if heart-beats are expected every milliseconds:
the sender MUST send new data over the network connection at least every milliseconds
if the sender has no real STOMP frame to send, it MUST send a single newline byte (0x0A)
if, inside a time window of at least milliseconds, the receiver did not receive any new data, it CAN consider the
connection as dead
because of timing inaccuracies, the receiver SHOULD be tolerant and take into account an error margin
Would that mean my client would need to send a newline bye every n seconds?
The stomp server you are connected to has timed out your connection due to innactivity.
Providing the server supports Stomp version 1.1 or newer, the easiest solution for your client is to include a heart-beat instruction in the header of your CONNECT, such as "0,10000". This tells the server that you cannot send heart-beats, but you want it to send one every 10 seconds. This way you don't need to implement them, and the server will keep the connection active by sending them to you.
Of course the server will have its own requirements of the client. In your comment it responds to your request with "1000,0". This indicates that it will send a heart-beat every 1000 millisecs, and it expects you to send one every 0 millisecs, 0 indicating none at all. So your job will be minimal.

Wrong destination in STOMP header when talking to hornetq server

I am trying to setup a C client to talk to a hornetq jms server. I am using its STOMP acceptor with libstomp on the C side.
My C client code is just this example from the libstomp page verbatim with the passphrase and destination queue name changed (to a valid queue that can be accessed from a java client).
Here's what I get when I run it:
Connecting......OK
Sending connect message.OK
Reading Response.Response: CONNECTED,
OK
Sending Subscribe.OK
Sending Message.OK
Reading Response.Response: ERROR, org.hornetq.core.protocol.stomp.StompException: Client must set destination or id head
er to a SUBSCRIBE command
at org.hornetq.core.protocol.stomp.StompProtocolManager.onSubscribe(StompProtocolManager.java: 339)
at org.hornetq.core.protocol.stomp.StompProtocolManager.handleBuffer(StompProtocolManager.java:196)
at org.hornetq.core.protocol.stomp.StompConnection.bufferReceived(StompConnection.java:279)
at org.hornetq.core.remoting.server.impl.RemotingServiceImpl$DelegatingBufferHandler.bufferRec eived(RemotingServ
iceImpl.java:512)
at org.hornetq.core.remoting.impl.netty.HornetQChannelHandler.messageReceived(HornetQChannelHa ndler.java:73)
at org.jboss.netty.channel.SimpleChannelHandler.handleUpstream(SimpleChannelHandler.java:100)
at org.jboss.netty.channel.StaticChannelPipeline.sendUpstream(StaticChannelPipeline.java:372)
at org.jboss.netty.channel.StaticChannelPipeline.sendUpstream(StaticChannelPipeline.java:367)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:274)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:261)
at org.jboss.netty.channel.socket.oio.OioWorker.run(OioWorker.java:100)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:44)
at org.jboss.netty.util.VirtualExecutorService$ChildExecutorRunnable.run(VirtualExecutorServic e.java:181)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
OK
Sending Disconnect.OK
Disconnecting...OK
In short - I get this exception from the server:
ERROR, org.hornetq.core.protocol.stomp.StompException: Client must set destination or id header to a SUBSCRIBE command
On line 92 of the example, we set the destination:
apr_hash_set(frame.headers, "destination", APR_HASH_KEY_STRING, "/queue/FOO.BAR");
Despite this, when the message gets to the server and it parses the headers, I get a map ation -> /queue/FOO.BAR, but it's looking for a destination key. I have confirmed that the client is adding the correct map entry to the headers and it is not corrupted all the way through to sending it to the network.
Any pointers as to what might be wrong?
P.S. hornetq is 2.2.9.Final, libstomp is the latest revision from svn (rev 90 - http://svn.codehaus.org/stomp/trunk/c/), and it was compiled with apr 1.4.6; all running on Win-7
2.2.9 is a pretty old HornetQ release. You should retry with 2.2.14, or with the latest 2.3.beta. I just looked at the code in git for HornetQ master, the destination is being handled
See onSubscribe() at https://github.com/hornetq/hornetq/blob/master/hornetq-server/src/main/java/org/hornetq/core/protocol/stomp/VersionedStompFrameHandler.java#L254
FWIW, in HornetQ a dot . is used as divisor for destinations (your code is using a slash /). The STOMP protocol leaves this as an implementation dependent convention.

connect to a lacewing server chat

I'm trying to make a port of a chat program a friend of mine made with lacewing and multimedia fusion 2 for android device.
I've managed to create a socket connecting to the listening socket of the server successfully, but I cannot seem to be able to send data to login and enter the chat. The login for now just requires a name, but even if I send a String of data, the server doesn't seem to reply or accept that data to get me over the channel.
I know I could easily port this with other way like using the NDK of the multimedia fusion 2 exporter, but I just want to figure out how this works
PS: I'm using Java and libgdx for the development
You need to read the liblacewing relay protocol:
https://github.com/udp/lacewing/blob/0.2.x/relay/current_spec.txt
On initial connection, you have to send byte 0 to identify that you are not an HTTP client. After this, you can exchange normal protocol messages.
The first message you need to send is the connection request (which may be denied by the server with a deny message). This would be:
byte 0 (2.1.0 request)
(1.2 size)
byte 0 (2.1.0.0 connection request)
string "revision 3" (2.1.0.0 connection request -> version)
When the server responds with response 0 (2.2.0.0 Connect), you then have to set a name before you may join any channels. This is done with message 2.1.0.1 SetName, which is the same structure as above but instead of 2.1.0.0's byte 0, it is 2.1.0.1's byte 1, followed by the name as a string instead of the protocol version.
The server should then respond with 2.2.0.1 SetName, assuming it accepted your name change request. You should process this message in case the server gave you a different name than you requested. Finally, once you have a name, you can join a channel with 2.1.0.2 JoinChannel. The flags you specify here will be used if the channel doesn't exist yet (e.g. nobody is in the chat yet) - these should match the ones in the MMF2 project file. The name should also match.
After all that, you're still not done! You have to process more messages, etc. it's almost like writing the RelayClient class yourself. It's a tough task, but with the protocol specification in hand you should be able to work it all out.

Categories