Skip to content

Instantly share code, notes, and snippets.

@gabonator
Last active May 5, 2024 20:36
Show Gist options
  • Save gabonator/d7b813dd33e5413c29661f42e7472437 to your computer and use it in GitHub Desktop.
Save gabonator/d7b813dd33e5413c29661f42e7472437 to your computer and use it in GitHub Desktop.
raw socket websocket client
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);
});
});
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);
});
});
#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