mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-01-30 22:23:07 +01:00
Fix websocket binary mask issue
Includes <D WEBSOCKET ON>
This commit is contained in:
parent
5600382ae4
commit
04b8e20773
@ -58,14 +58,22 @@ template<typename... Targs> void CommandDistributor::broadcastReply(clientType t
|
|||||||
#ifdef CD_HANDLE_RING
|
#ifdef CD_HANDLE_RING
|
||||||
// wifi or ethernet ring streams with multiple client types
|
// wifi or ethernet ring streams with multiple client types
|
||||||
RingStream * CommandDistributor::ring=0;
|
RingStream * CommandDistributor::ring=0;
|
||||||
CommandDistributor::clientType CommandDistributor::clients[8]={
|
CommandDistributor::clientType CommandDistributor::clients[20]={
|
||||||
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE};
|
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,
|
||||||
|
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,
|
||||||
|
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,
|
||||||
|
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,
|
||||||
|
NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE};
|
||||||
|
|
||||||
// Parse is called by Withrottle or Ethernet interface to determine which
|
// Parse is called by Wifi or Ethernet interface to determine which
|
||||||
// protocol the client is using and call the appropriate part of dcc++Ex
|
// protocol the client is using and call the appropriate part of dcc++Ex
|
||||||
void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream) {
|
void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream) {
|
||||||
if (Diag::WIFI && Diag::CMD)
|
if (clientId>=sizeof (clients)) {
|
||||||
DIAG(F("Parse C=%d T=%d B=%s"),clientId, clients[clientId], buffer);
|
// Caution, diag dump of buffer could corrupt ringstream
|
||||||
|
// if headed by websocket bytes.
|
||||||
|
DIAG(F("::parse invalid client=%d"),clientId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
ring=stream;
|
ring=stream;
|
||||||
|
|
||||||
// First check if the client is not known
|
// First check if the client is not known
|
||||||
|
@ -43,7 +43,7 @@ private:
|
|||||||
static StringBuffer * broadcastBufferWriter;
|
static StringBuffer * broadcastBufferWriter;
|
||||||
#ifdef CD_HANDLE_RING
|
#ifdef CD_HANDLE_RING
|
||||||
static RingStream * ring;
|
static RingStream * ring;
|
||||||
static clientType clients[8];
|
static clientType clients[20];
|
||||||
#endif
|
#endif
|
||||||
public :
|
public :
|
||||||
static void parse(byte clientId,byte* buffer, RingStream * ring);
|
static void parse(byte clientId,byte* buffer, RingStream * ring);
|
||||||
|
@ -1252,6 +1252,10 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[])
|
|||||||
case "LCN"_hk: // <D LCN ON/OFF>
|
case "LCN"_hk: // <D LCN ON/OFF>
|
||||||
Diag::LCN = onOff;
|
Diag::LCN = onOff;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case "WEBSOCKET"_hk: // <D WEBSOCKET ON/OFF>
|
||||||
|
Diag::WEBSOCKET = onOff;
|
||||||
|
return true;
|
||||||
#endif
|
#endif
|
||||||
#ifndef DISABLE_EEPROM
|
#ifndef DISABLE_EEPROM
|
||||||
case "EEPROM"_hk: // <D EEPROM NumEntries>
|
case "EEPROM"_hk: // <D EEPROM NumEntries>
|
||||||
|
@ -28,6 +28,7 @@ bool Diag::WITHROTTLE=false;
|
|||||||
bool Diag::ETHERNET=false;
|
bool Diag::ETHERNET=false;
|
||||||
bool Diag::LCN=false;
|
bool Diag::LCN=false;
|
||||||
bool Diag::RAILCOM=false;
|
bool Diag::RAILCOM=false;
|
||||||
|
bool Diag::WEBSOCKET=false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ class Diag {
|
|||||||
static bool ETHERNET;
|
static bool ETHERNET;
|
||||||
static bool LCN;
|
static bool LCN;
|
||||||
static bool RAILCOM;
|
static bool RAILCOM;
|
||||||
|
static bool WEBSOCKET;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ static const char b64_table[] = {
|
|||||||
|
|
||||||
bool Websockets::checkConnectionString(byte clientId,byte * cmd, RingStream * outbound ) {
|
bool Websockets::checkConnectionString(byte clientId,byte * cmd, RingStream * outbound ) {
|
||||||
// returns true if this input is a websocket connect
|
// returns true if this input is a websocket connect
|
||||||
DIAG(F("In websock check"));
|
if (Diag::WEBSOCKET) DIAG(F("Websock check connection"));
|
||||||
/* Heuristic suppose this is a websocket GET
|
/* Heuristic suppose this is a websocket GET
|
||||||
typically looking like this:
|
typically looking like this:
|
||||||
|
|
||||||
@ -98,14 +98,14 @@ bool Websockets::checkConnectionString(byte clientId,byte * cmd, RingStream * ou
|
|||||||
if (!endkeypos) return false;
|
if (!endkeypos) return false;
|
||||||
*endkeypos=0;
|
*endkeypos=0;
|
||||||
|
|
||||||
DIAG(F("websock key=\"%s\""),keyPos);
|
if (Diag::WEBSOCKET) DIAG(F("Websock key=\"%s\""),keyPos);
|
||||||
// generate the reply key
|
// generate the reply key
|
||||||
uint8_t sha1HashBin[21] = { 0 }; // 21 to make it base64 div 3
|
uint8_t sha1HashBin[21] = { 0 }; // 21 to make it base64 div 3
|
||||||
char replyKey[100];
|
char replyKey[100];
|
||||||
strlcpy(replyKey,keyPos, sizeof(replyKey));
|
strlcpy(replyKey,keyPos, sizeof(replyKey));
|
||||||
strlcat_P(replyKey,(char*)F("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"), sizeof(replyKey));
|
strlcat_P(replyKey,(char*)F("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"), sizeof(replyKey));
|
||||||
|
|
||||||
DIAG(F("websock replykey=%s"),replyKey);
|
if (Diag::WEBSOCKET) DIAG(F("Websock replykey=%s"),replyKey);
|
||||||
|
|
||||||
SHA1_CTX ctx;
|
SHA1_CTX ctx;
|
||||||
SHA1Init(&ctx);
|
SHA1Init(&ctx);
|
||||||
@ -140,7 +140,7 @@ bool Websockets::checkConnectionString(byte clientId,byte * cmd, RingStream * ou
|
|||||||
byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) {
|
byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) {
|
||||||
// buffer should have a websocket header
|
// buffer should have a websocket header
|
||||||
//byte opcode=buffer[0] & 0x0f;
|
//byte opcode=buffer[0] & 0x0f;
|
||||||
DIAG(F("Websock in: %x %x %x %x %x %x %x %x"),
|
if (Diag::WEBSOCKET) DIAG(F("Websock in: %x %x %x %x %x %x %x %x"),
|
||||||
buffer[0],buffer[1],buffer[2],buffer[3],
|
buffer[0],buffer[1],buffer[2],buffer[3],
|
||||||
buffer[4],buffer[5],buffer[6]);
|
buffer[4],buffer[5],buffer[6]);
|
||||||
|
|
||||||
@ -156,11 +156,11 @@ byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) {
|
|||||||
payloadLength=(buffer[3]<<8)|(buffer[2]);
|
payloadLength=(buffer[3]<<8)|(buffer[2]);
|
||||||
mask=buffer+4;
|
mask=buffer+4;
|
||||||
}
|
}
|
||||||
DIAG(F("Websock op=%x mb=%b pl=%d m=%x %x %x %x"), opcode, maskbit, payloadLength,
|
if (Diag::WEBSOCKET) DIAG(F("Websock op=%x mb=%b pl=%d m=%x %x %x %x"), opcode, maskbit, payloadLength,
|
||||||
mask[0],mask[1],mask[2], mask[3]);
|
mask[0],mask[1],mask[2], mask[3]);
|
||||||
|
|
||||||
if (opcode==0x89) { // ping
|
if (opcode==0x89) { // ping
|
||||||
DIAG(F("Websocket ping"));
|
DIAG(F("Websock ping"));
|
||||||
buffer[0]=0x8a; // pong.. and send it back
|
buffer[0]=0x8a; // pong.. and send it back
|
||||||
ring->mark(clientId &0x7f); // dont readjust
|
ring->mark(clientId &0x7f); // dont readjust
|
||||||
ring->print((char *)buffer);
|
ring->print((char *)buffer);
|
||||||
@ -169,7 +169,7 @@ byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (opcode!=0x81) {
|
if (opcode!=0x81) {
|
||||||
DIAG(F("Websocket unknown opcode 0x%x"),opcode);
|
DIAG(F("Websock unknown opcode 0x%x"),opcode);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +178,8 @@ byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) {
|
|||||||
payload[i]^=mask[i%4];
|
payload[i]^=mask[i%4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Diag::WEBSOCKET) DIAG(F("Websoc payload=%s"),payload);
|
||||||
|
|
||||||
return payload; // payload will be parsed as normal
|
return payload; // payload will be parsed as normal
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,9 @@ void WifiInboundHandler::loop1() {
|
|||||||
int count=inboundRing->count();
|
int count=inboundRing->count();
|
||||||
if (Diag::WIFI) DIAG(F("Wifi EXEC: %d %d:"),clientId,count);
|
if (Diag::WIFI) DIAG(F("Wifi EXEC: %d %d:"),clientId,count);
|
||||||
byte cmd[count+1];
|
byte cmd[count+1];
|
||||||
for (int i=0;i<count;i++) cmd[i]=inboundRing->read();
|
// Copy raw bytes to avoid websocket masked data being
|
||||||
|
// confused with a ram-saving flash insert marker.
|
||||||
|
for (int i=0;i<count;i++) cmd[i]=inboundRing->readRawByte();
|
||||||
cmd[count]=0;
|
cmd[count]=0;
|
||||||
if (Diag::WIFI) DIAG(F("%e"),cmd);
|
if (Diag::WIFI) DIAG(F("%e"),cmd);
|
||||||
|
|
||||||
@ -238,7 +240,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
|||||||
dataLength--;
|
dataLength--;
|
||||||
if (dataLength == 0) {
|
if (dataLength == 0) {
|
||||||
// Nothing found, this input is lost
|
// Nothing found, this input is lost
|
||||||
DIAG(F("Wifi prescan not found"));
|
DIAG(F("Wifi prescan for websock not found"));
|
||||||
inboundRing->commit();
|
inboundRing->commit();
|
||||||
loopState = ANYTHING;
|
loopState = ANYTHING;
|
||||||
}
|
}
|
||||||
@ -249,7 +251,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() {
|
|||||||
// matched the next char of the key
|
// matched the next char of the key
|
||||||
prescanPoint++;
|
prescanPoint++;
|
||||||
if (WebSocketKeyName[prescanPoint]==0) {
|
if (WebSocketKeyName[prescanPoint]==0) {
|
||||||
DIAG(F("Wifi prescan found"));
|
if (Diag::WEBSOCKET) DIAG(F("Wifi prescan found"));
|
||||||
// prescan has detected full key
|
// prescan has detected full key
|
||||||
inboundRing->print(WebSocketKeyName);
|
inboundRing->print(WebSocketKeyName);
|
||||||
loopState=IPD_POSTSCAN; // continmue as normal
|
loopState=IPD_POSTSCAN; // continmue as normal
|
||||||
|
Loading…
Reference in New Issue
Block a user