AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   Solved Communicating with socket.io using sourcemod and socket (https://forums.alliedmods.net/showthread.php?t=298782)

Blowst 06-22-2017 13:40

Communicating with socket.io using sourcemod and socket
 
Hello, I'm trying to connect to my socket.io server with a plugin using socket(3.0.1)

It works nice when I connected to it with web browser(socket.io client)

But it just close the connection throwing close code 1002 when I connected with my plugin.

Have you guys any idea or solution?

here's my node.js server DEBUG LOG
Code:

Thu, 22 Jun 2017 17:20:03 GMT socket.io:socket joined room H6lgVyeHYXKaNQ7cAAAF
Thu, 22 Jun 2017 17:20:03 GMT engine upgrading existing transport
Thu, 22 Jun 2017 17:20:03 GMT engine:socket might upgrade socket transport from "polling" to "websocket"
Thu, 22 Jun 2017 17:20:03 GMT engine:ws received "Hello"
Thu, 22 Jun 2017 17:20:03 GMT engine:ws closing
Thu, 22 Jun 2017 17:20:13 GMT engine:polling closing
Thu, 22 Jun 2017 17:20:13 GMT engine:polling transport not writable - buffering orderly close
Thu, 22 Jun 2017 17:20:13 GMT socket.io:client client close with reason ping timeout
Thu, 22 Jun 2017 17:20:13 GMT socket.io:socket closing socket - reason ping timeout

And here's my plugins code

PHP Code:

#include <sourcemod>
#include <socket>

char roomId[21];
char yeast[8];

public 
OnPluginStart() {
    new 
Handle:socket SocketCreate(SOCKET_TCPOnSocketError);
    
SocketConnect(socketOnSocketConnectedOnSocketReceiveOnSocketDisconnected"110.45.113.25"3000);
}

public 
OnSocketConnected(Handle:socketany:arg) {
    
// socket is connected, send the http request
    
PrintToServer("######Socket Connected!######");
    
decl String:requestStr[512];
    
    
PrintToServer("######Let's Try to CONNECT to websocket!######");
    
Format(requestStrsizeof(requestStr), "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n""getstamp""localhost:3000");
    
SocketSend(socketrequestStr);
    
    
PrintToServer("######Let's Try to HANDSHAKE with websocket!######");    
    
Format(requestStrsizeof(requestStr), "GET /%s%s HTTP/1.1\r\nHost: %s\r\n\r\n""socket.io/?clienttype=SRCDS&EIO=3&transport=polling&t="yeast"localhost:3000");
    
SocketSend(socketrequestStr);
}

public 
OnSocketReceive(Handle:socketString:receiveData[], const dataSizeany:hFile)
{
    
PrintToServer(receiveData);
    if(
StrContains(receiveData"Yeast:"false) != -1)
    {
        
Format(yeast8"%s"receiveData[StrContains(receiveData"Yeast:"true) + 6]);
    }
    else if(
StrContains(receiveData"HTTP/1.1 200 OK"true) != -1)
    {
        
/*
        HTTP/1.1 200 OK
        Content-Type: application/octet-stream
        Content-Length: 101
        Access-Control-Allow-Origin: *
        Set-Cookie: io=iCx7MnGxL1aqNU1gAAAJ; Path=/; HttpOnly
        Date: Mon, 24 Apr 2017 08:03:02 GMT
        Connection: keep-alive
        */
        
decl String:requestStr[512];        
        
PrintToServer("READY TO GO!");
        
        
Format(roomId21"%s"receiveData[StrContains(receiveData"Set-Cookie: io="true) + 15]);
        
// request handshake
        
Format(requestStrsizeof(requestStr), "GET /%s%s HTTP/1.1\r\nHost: %s\r\nConnection: Upgrade\r\nUpgrade: WebSocket\r\nOrigin: http://127.0.0.1:3000/\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: %s\r\n\r\n""socket.io/?clienttype=SRCDS&EIO=3&transport=websocket&sid="roomId"localhost:3000""YW4gc3JjZHMgd3MgdGVzdA==");
        
SocketSend(socketrequestStr);
    }
    else if(
StrContains(receiveData"HTTP/1.1 101 Switching Protocols"true) == 0)
    {
        
/*
        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: MWRJjQKH/LfNpV4m0z+2rF8En+k=
        Sec-WebSocket-Protocol: chat
        */
        
        
char acceptKey[29];
        
Format(acceptKey29"%s"receiveData[StrContains(receiveData"Sec-WebSocket-Accept: "true) + 22]);
        
PrintToServer("ACCEPT-KEY: %s"acceptKey);

        
char sTemp[11]; // Text, Masked Hello
            
sTemp[0] = 0x81;
            
sTemp[1] = 0x85;
            
sTemp[2] = 0x37;
            
sTemp[3] = 0xfa;
            
sTemp[4] = 0x21;
            
sTemp[5] = 0x3d;
            
sTemp[6] = 0x7f;
            
sTemp[7] = 0x9f;
            
sTemp[8] = 0x4d;
            
sTemp[9] = 0x51;
            
sTemp[10] = 0x58;
        
SocketSend(socketsTemp);                  
    }
    else
    {
        
PrintToServer("You received a data:");
        
PrintToServer(receiveData);
    }


When I send Ping packet to socket.io server, it prints these.

Code:

Thu, 22 Jun 2017 17:22:35 GMT socket.io:socket joined room 2yNY-DX-uNWmtmftAAAG
Thu, 22 Jun 2017 17:22:35 GMT engine upgrading existing transport
Thu, 22 Jun 2017 17:22:35 GMT engine:socket might upgrade socket transport from "polling" to "websocket"
Thu, 22 Jun 2017 17:22:45 GMT engine:socket client did not complete upgrade - closing transport
Thu, 22 Jun 2017 17:22:45 GMT engine:ws closing
Thu, 22 Jun 2017 17:24:00 GMT engine:polling closing
Thu, 22 Jun 2017 17:24:00 GMT engine:polling transport not writable - buffering orderly close
Thu, 22 Jun 2017 17:24:00 GMT socket.io:client client close with reason ping timeout
Thu, 22 Jun 2017 17:24:00 GMT socket.io:socket closing socket - reason ping timeout


Fyren 06-22-2017 20:22

Re: Communicating with socket.io using sourcemod and socket
 
WebSockets are not just raw sockets. It's a communications protocol.

Kinsi 06-23-2017 13:02

Re: Communicating with socket.io using sourcemod and socket
 
Luckily, somebody already did the hard work of implementing the websocket protocol:

https://forums.alliedmods.net/showthread.php?t=182615

Blowst 06-24-2017 01:47

Re: Communicating with socket.io using sourcemod and socket
 
Quote:

Originally Posted by Kinsi (Post 2531066)
Luckily, somebody already did the hard work of implementing the websocket protocol:

https://forums.alliedmods.net/showthread.php?t=182615

Yes, I actually checked it out many times. and tried to understand the protocol.

but it implementing only server-side websockets.

It looks more complicated communicating with socket.io server via TCP socket client.

perhaps I'm missing something that need to be at very last step of handshake...
(ping-pong or something?)

thanks for reply

ElectricStalin 06-24-2017 06:33

Re: Communicating with socket.io using sourcemod and socket
 
Maybe you'd better suited HTTP requests? I make plugin with it, that send data to server, and then recieve response.

Fyren 06-24-2017 06:38

Re: Communicating with socket.io using sourcemod and socket
 
Sorry, my reply earlier was way too hasty.

Can you post the handshake headers for the request and response using both your browser and your plugin? I see you have some in your comments, but I'm not sure if that's what you hope to get or what you're actually getting.

Blowst 06-24-2017 15:25

Re: Communicating with socket.io using sourcemod and socket
 
Quote:

Originally Posted by Fyren (Post 2531294)
Sorry, my reply earlier was way too hasty.

Can you post the handshake headers for the request and response using both your browser and your plugin? I see you have some in your comments, but I'm not sure if that's what you hope to get or what you're actually getting.

Now, Server closes the connection after sending any data even after the handshake.
I just want to keep these connected.

OK, first(after socket connection) I send a request for getting session id:
Code:

GET /socket.io/?clienttype=SRCDS&EIO=3&transport=polling&t=LpRVJRD HTTP/1.1
Host: localhost:3000

Then, server response:
Code:

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 101
Access-Control-Allow-Origin: *
Set-Cookie: io=q6GVx_8byvJDsuGUAAAA; Path=/; HttpOnly
Date: Sat, 24 Jun 2017 19:03:55 GMT
Connection: keep-alive

I got the session id 'q6GVx_8byvJDsuGUAAAA' now request handshaking:
Code:

GET /socket.io/?clienttype=SRCDS&EIO=3&transport=websocket&sid=q6GVx_8byvJDsuGUAAAA HTTP/1.1
Host: localhost:3000
Connection: Upgrade
Upgrade: WebSocket
Origin: http://127.0.0.1:3000/
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: YW4gc3JjZHMgd3MgdGVzdA==

Then, server switch polling to websocket

Code:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: g0G7yI0fUu+ZAN+kTvfCOjCqOJg=


Fyren 06-24-2017 21:09

Re: Communicating with socket.io using sourcemod and socket
 
I tested your code using "wscat --listen" for the server and it does seem to work right. Maybe your websocket server is expecting different data to be sent first?

I did make a few small changes, but I don't think anything changed that matters:

PHP Code:

#include <socket>

Handle socket;
public 
OnPluginStart() {
        
socket SocketCreate(SOCKET_TCPOnSocketError);
        
SocketConnect(socketOnSocketConnectedOnSocketReceiveOnSocketDisconnected"127.0.0.1"8000);
        
RegServerCmd("sendhello"sendHello);
}

public 
OnSocketConnected(Handle:sany:arg) {
        
PrintToServer("Socket connected!");
        
sendHandshake();
}

void sendHandshake() {
        
char str[2048];
        
Format(strsizeof(str), "GET / HTTP/1.1\r\nHost: %s\r\nConnection: Upgrade\r\nUpgrade: WebSocket\r\nOrigin: http://127.0.0.1:8000/\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: %s\r\n\r\n""127.0.0.1:8000""YW4gc3JjZHMgd3MgdGVzdA==");
        
PrintToServer("Sending to socket:\n%s"str);
        
SocketSend(socketstr);
}

public 
OnSocketError(Handle sint errorTypeint errorNumany arg) {
        
PrintToServer("Socket error: %d %d"errorTypeerrorNum);
}

public 
OnSocketDisconnected(Handle sany data) {
        
PrintToServer("Socket disconnected.");
}

public 
OnSocketReceive(Handle schar[] receiveDataint szany hFile)
{
        
PrintToServer("Received from socket:\n%s"receiveData);
        if (
StrContains(receiveData"HTTP/1.1 101 Switching Protocols"true) == 0)
        {
                
char acceptKey[29];
                
Format(acceptKey29"%s"receiveData[StrContains(receiveData"Sec-WebSocket-Accept: "true) + 22]);
                
PrintToServer("ACCEPT-KEY: %s"acceptKey);
        }
}

public 
Action sendHello(int args) {
        
PrintToServer("Sending websocket frame");
        
char sTemp[11]; // Text, Masked Hello
        
sTemp[0] = 0x81;
        
sTemp[1] = 0x85;
        
sTemp[2] = 0x37;
        
sTemp[3] = 0xfa;
        
sTemp[4] = 0x21;
        
sTemp[5] = 0x3d;
        
sTemp[6] = 0x7f;
        
sTemp[7] = 0x9f;
        
sTemp[8] = 0x4d;
        
sTemp[9] = 0x51;
        
sTemp[10] = 0x58;
        
SocketSend(socketsTemp);


srcds console:
Code:

Socket connected!
Sending to socket:
GET / HTTP/1.1
Host: 127.0.0.1:8000
Connection: Upgrade
Upgrade: WebSocket
Origin: http://127.0.0.1:8000/
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: YW4gc3JjZHMgd3MgdGVzdA==


Received from socket:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: g0G7yI0fUu+ZAN+kTvfCOjCqOJg=


ACCEPT-KEY: g0G7yI0fUu+ZAN+kTvfCOjCqOJg=
sendhello
Sending websocket frame
Received from socket:
response

wscat:
Code:

$ wscat --listen 8000
listening on port 8000 (press CTRL+C to quit)
client connected
< Hello
> response
>


Blowst 06-25-2017 02:13

Re: Communicating with socket.io using sourcemod and socket
 
1 Attachment(s)
Quote:

Originally Posted by Fyren (Post 2531512)
I tested your code using "wscat --listen" for the server and it does seem to work right. Maybe your websocket server is expecting different data to be sent first?

I did make a few small changes, but I don't think anything changed that matters:

I got this. setting sid parameter in handshake request was the problem


Code:

GET /socket.io/?EIO=3&transport=websocket&sid=q6GVx_8byvJDsuGUAAAA HTTP/1.1
Host: 127.0.0.1:8000
Connection: Upgrade
Upgrade: WebSocket
Origin: http://127.0.0.1:8000/
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: YW4gc3JjZHMgd3MgdGVzdA==

working request:
Code:

GET /socket.io/?EIO=3&transport=websocket HTTP/1.1
Host: 127.0.0.1:8000
Connection: Upgrade
Upgrade: WebSocket
Origin: http://127.0.0.1:8000/
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: YW4gc3JjZHMgd3MgdGVzdA==


server console outputs:
Code:

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 101
Access-Control-Allow-Origin: *
Set-Cookie: io=koZVmcSaYqjz_Yn5AAAF; Path=/; HttpOnly
Date: Sun, 25 Jun 2017 06:04:51 GMT
Connection: keep-alive


Room(Session) ID: koZVmcSaYqjz_Yn5AAAF
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: g0G7yI0fUu+ZAN+kTvfCOjCqOJg=


ACCEPT-KEY: g0G7yI0fUu+ZAN+kTvfCOjCqOJg=
갫0{"sid":"2_Q9DdgHvOzEwalvAAAG","upgrades":[],"pingInterval":25000,"pingTimeout":60000}
?40

sendhello
Sending websocket frame
42["sendchat", "Hello, Socket.io!"]

You received a data:
?42["updatechat",null,"Hello, Socket.io!"]

web outputs:
https://forums.alliedmods.net/attach...1&d=1498371165


Thank you guys for helping to solve the problem

Kinsi 06-25-2017 15:43

Re: Communicating with socket.io using sourcemod and socket
 
Do you necessarily need socket.io? Possibly try using raw websockets? Implementing stuff like socket.io's rooms etc would be way too complicated anyways. Possibly give raw websockets a try, or if you want some kind of abstraction which is closer to native primus.io: https://github.com/primus/primus


All times are GMT -4. The time now is 07:45.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.