Last active
May 5, 2024 20:36
-
-
Save gabonator/d7b813dd33e5413c29661f42e7472437 to your computer and use it in GitHub Desktop.
raw socket websocket client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var net = require('net'); | |
var socket = net.connect(8080, "localhost", () => { | |
var request = "GET / HTTP/1.1\r\nHost: " + "localhost" + "\r\n\r\n"; | |
var rawResponse = ""; | |
socket.write(` | |
GET / HTTP/1.1 | |
Host: localhost | |
Connection: Upgrade | |
Upgrade: websocket | |
Sec-WebSocket-Version: 13 | |
Sec-WebSocket-Key: IS0tZXhhbXBsZS5haS0tIQ== | |
Origin: localhost | |
`.split("\n").map(x=>x.trim()).splice(1).join("\r\n")); | |
setInterval(()=>{ | |
var message = "Ahoj toto je sprava! " + new Date(); | |
var buf = new Buffer(message.length + 8); | |
buf[0] = 0x81; | |
buf[1] = 126 | 0x80; | |
buf[2] = message.length >> 8; // TODO: this breaks rfc6455 Payload length rules, but works | |
buf[3] = message.length & 255; | |
buf[4] = buf[5] = buf[6] = buf[7] = 0; | |
for (var i=0; i<message.length; i++) | |
buf[i+8] = message.charCodeAt(i); | |
socket.write(buf); | |
}, 1000) | |
socket.on('data', function(chunk) { | |
if (chunk[0] == 0x81 || chunk[0] == 0x82) // text frame, binary frame | |
{ | |
var msg = ""; | |
var ofs = 2; | |
var len = chunk[1]; | |
if (len == 126) | |
{ | |
ofs = 4; | |
len = (chunk[2]<<8) | chunk[3]; | |
} | |
for (var i=0; i<len; i++) | |
msg += String.fromCharCode(chunk[i+ofs]); | |
console.log("WS:" + msg); | |
} else | |
console.log("RAW:" + chunk.toString()); | |
}); | |
socket.on('end', function(){ | |
console.log(rawResponse); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const WebSocket = require('ws'); | |
const server = new WebSocket.Server({port: 8080}); | |
let sockets = []; | |
server.on('connection', function(socket) { | |
sockets.push(socket); | |
socket.on('message', function(msg) { | |
console.log(msg.toString()); | |
sockets.forEach(s => s.send(msg)); | |
}); | |
socket.on('close', function() { | |
sockets = sockets.filter(s => s !== socket); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define SerialDebug Serial | |
#define DEBUG_ETHERNET_GENERIC_PORT SerialDebug | |
#define _ETG_LOGLEVEL_ 0 | |
#define USE_THIS_SS_PIN 10 | |
#define SENDCONTENT_P_BUFFER_SZ 512 | |
#include <SPI.h> | |
#define ETHERNET_LARGE_BUFFERS | |
#include "Ethernet_Generic.h" | |
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x01 }; | |
IPAddress ip(192, 168, 2, 222); | |
EthernetClient client; | |
void WsReceive() | |
{ | |
char buffer[64]; | |
int bufferi = 0; | |
while (client.available()) | |
buffer[bufferi++] = client.read(); | |
if (bufferi) | |
{ | |
Serial.print("Received "); | |
Serial.print((int)bufferi); | |
Serial.print(" bytes: "); | |
buffer[bufferi] = 0; | |
if ((uint8_t)buffer[0] == 0x81 || (uint8_t)buffer[0] == 0x82) | |
{ | |
if (buffer[1] < sizeof(buffer)) | |
buffer[buffer[1]+2] = 0; | |
Serial.print(buffer+2); | |
Serial.print("\n"); | |
} else { | |
Serial.print("<Wrong websocket frame>"); | |
Serial.print(buffer[0], HEX); | |
Serial.print(">\n"); | |
} | |
} | |
} | |
void setup() | |
{ | |
SerialDebug.begin(115200); | |
SerialDebug.print("\nStarting WebClient\n"); | |
Ethernet.init (USE_THIS_SS_PIN); | |
Ethernet.begin(mac, ip); | |
//Ethernet.begin(mac); | |
SerialDebug.print(F("Connected! IP address: ")); | |
SerialDebug.println(Ethernet.localIP()); | |
if ( (Ethernet.getChip() == w5500) || (Ethernet.getChip() == w6100) || (Ethernet.getAltChip() == w5100s) ) | |
{ | |
SerialDebug.print(F("Speed: ")); | |
SerialDebug.print(Ethernet.speedReport()); | |
SerialDebug.print(F(", Duplex: ")); | |
SerialDebug.print(Ethernet.duplexReport()); | |
SerialDebug.print(F(", Link status: ")); | |
SerialDebug.println(Ethernet.linkReport()); | |
} | |
delay(100); | |
} | |
void WsSend(const char* message) | |
{ | |
int len = strlen(message); | |
char buffer[64] = {0}; | |
buffer[0] = 0x81; | |
buffer[1] = 0xfe; | |
buffer[2] = len >> 8; | |
buffer[3] = len & 255; | |
for (int i=0; message[i]; i++) | |
buffer[i+8] = message[i]; | |
client.write(buffer, len+8); | |
} | |
bool processHeader(void (*handler)(const char*, const char*)) //(std::function<void(const char*, const char*)> handler) | |
{ | |
const int timeout = 300; | |
long t0 = millis(); | |
char line[128]; | |
int linei = 0; | |
char buf[5] = {0}; | |
while (millis() - t0 < timeout && client.connected()) | |
{ | |
if (!client.available()) | |
continue; | |
t0 = millis(); | |
while (client.available()) | |
{ | |
char c = client.read(); | |
buf[0] = buf[1]; | |
buf[1] = buf[2]; | |
buf[2] = buf[3]; | |
buf[3] = c; | |
if (strcmp(buf, "\r\n\r\n") == 0) | |
return true; | |
if (c == 0x0d || c == 0x0a) | |
{ | |
line[linei] = 0; | |
if (linei) | |
{ | |
char *delim = strstr(line, ": "); | |
if (delim) | |
{ | |
*delim = 0; | |
for (int i=0; line[i]; i++) | |
if (line[i] >= 'A' && line[i] <= 'Z') | |
line[i] -= 'A' - 'a'; | |
handler(line, delim+2); | |
} | |
} | |
linei = 0; | |
} else { | |
if (linei < sizeof(line)-1) | |
line[linei++] = c; | |
} | |
} | |
} | |
return false; | |
} | |
void loop() | |
{ | |
static int failedTries = 0; | |
static long lastTimestamp = 0; | |
if (client.available()) | |
WsReceive(); | |
long now = millis(); | |
if (now - lastTimestamp < 300) | |
return; | |
lastTimestamp = now; | |
if (!Ethernet.link()) | |
{ | |
Serial.print("No link\n"); | |
return; | |
} | |
if (client.connected()) | |
{ | |
char message[64]; | |
sprintf(message, "Toto je sprava %ld!", millis()); | |
WsSend(message); | |
Serial.print("."); | |
return; | |
} | |
Serial.print("Connecting...\n"); | |
if (client.connect(IPAddress(192, 168, 2, 1), 8080)) | |
{ | |
client.print("GET / HTTP/1.1\r\n" | |
"Host: 192.168.2.1\r\n" | |
"Connection: Upgrade\r\n" | |
"Upgrade: websocket\r\n" | |
"Sec-WebSocket-Version: 13\r\n" | |
"Sec-WebSocket-Key: IS0tZXhhbXBsZS5haS0tIQ==\r\n" | |
"Origin: localhost\r\n" | |
"\r\n"); | |
processHeader([](const char* head, const char* value){ | |
// upgrade=websocket | |
// connection=Upgrade | |
// sec-websocket-accept=... | |
Serial.print("header: "); | |
Serial.print(head); | |
Serial.print("="); | |
Serial.print(value); | |
Serial.print("\n"); | |
}); | |
failedTries = 0; | |
} else | |
{ | |
SerialDebug.println(F("Server not available")); | |
if (failedTries++ >= 5) | |
{ | |
failedTries = 0; | |
SerialDebug.println(F("Ethernet reset")); | |
Ethernet.init (USE_THIS_SS_PIN); | |
Ethernet.begin(mac, ip); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment