diff --git a/CommandDistributor.cpp b/CommandDistributor.cpp index cdaecf5..6040514 100644 --- a/CommandDistributor.cpp +++ b/CommandDistributor.cpp @@ -58,14 +58,22 @@ template void CommandDistributor::broadcastReply(clientType t #ifdef CD_HANDLE_RING // wifi or ethernet ring streams with multiple client types RingStream * CommandDistributor::ring=0; - CommandDistributor::clientType CommandDistributor::clients[8]={ - NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE,NONE_TYPE}; + 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}; -// 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 void CommandDistributor::parse(byte clientId,byte * buffer, RingStream * stream) { - if (Diag::WIFI && Diag::CMD) - DIAG(F("Parse C=%d T=%d B=%s"),clientId, clients[clientId], buffer); + if (clientId>=sizeof (clients)) { + // Caution, diag dump of buffer could corrupt ringstream + // if headed by websocket bytes. + DIAG(F("::parse invalid client=%d"),clientId); + return; + } ring=stream; // First check if the client is not known diff --git a/CommandDistributor.h b/CommandDistributor.h index fdf6cf9..de40bdb 100644 --- a/CommandDistributor.h +++ b/CommandDistributor.h @@ -43,7 +43,7 @@ private: static StringBuffer * broadcastBufferWriter; #ifdef CD_HANDLE_RING static RingStream * ring; - static clientType clients[8]; + static clientType clients[20]; #endif public : static void parse(byte clientId,byte* buffer, RingStream * ring); diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 9a9a8a4..ecf7534 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -1252,6 +1252,10 @@ bool DCCEXParser::parseD(Print *stream, int16_t params, int16_t p[]) case "LCN"_hk: // Diag::LCN = onOff; return true; + + case "WEBSOCKET"_hk: // + Diag::WEBSOCKET = onOff; + return true; #endif #ifndef DISABLE_EEPROM case "EEPROM"_hk: // diff --git a/StringFormatter.cpp b/StringFormatter.cpp index 04846f1..35a4901 100644 --- a/StringFormatter.cpp +++ b/StringFormatter.cpp @@ -28,6 +28,7 @@ bool Diag::WITHROTTLE=false; bool Diag::ETHERNET=false; bool Diag::LCN=false; bool Diag::RAILCOM=false; +bool Diag::WEBSOCKET=false; diff --git a/StringFormatter.h b/StringFormatter.h index 259536b..c046ec7 100644 --- a/StringFormatter.h +++ b/StringFormatter.h @@ -31,6 +31,7 @@ class Diag { static bool ETHERNET; static bool LCN; static bool RAILCOM; + static bool WEBSOCKET; }; diff --git a/Websockets.cpp b/Websockets.cpp index b15477a..e582ee6 100644 --- a/Websockets.cpp +++ b/Websockets.cpp @@ -71,7 +71,7 @@ static const char b64_table[] = { bool Websockets::checkConnectionString(byte clientId,byte * cmd, RingStream * outbound ) { // 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 typically looking like this: @@ -98,14 +98,14 @@ bool Websockets::checkConnectionString(byte clientId,byte * cmd, RingStream * ou if (!endkeypos) return false; *endkeypos=0; - DIAG(F("websock key=\"%s\""),keyPos); + if (Diag::WEBSOCKET) DIAG(F("Websock key=\"%s\""),keyPos); // generate the reply key uint8_t sha1HashBin[21] = { 0 }; // 21 to make it base64 div 3 char replyKey[100]; strlcpy(replyKey,keyPos, 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; SHA1Init(&ctx); @@ -140,7 +140,7 @@ bool Websockets::checkConnectionString(byte clientId,byte * cmd, RingStream * ou byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) { // buffer should have a websocket header //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[4],buffer[5],buffer[6]); @@ -156,11 +156,11 @@ byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) { payloadLength=(buffer[3]<<8)|(buffer[2]); 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]); if (opcode==0x89) { // ping - DIAG(F("Websocket ping")); + DIAG(F("Websock ping")); buffer[0]=0x8a; // pong.. and send it back ring->mark(clientId &0x7f); // dont readjust ring->print((char *)buffer); @@ -169,7 +169,7 @@ byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) { } if (opcode!=0x81) { - DIAG(F("Websocket unknown opcode 0x%x"),opcode); + DIAG(F("Websock unknown opcode 0x%x"),opcode); return nullptr; } @@ -178,6 +178,8 @@ byte * Websockets::unmask(byte clientId,RingStream *ring, byte * buffer) { payload[i]^=mask[i%4]; } + if (Diag::WEBSOCKET) DIAG(F("Websoc payload=%s"),payload); + return payload; // payload will be parsed as normal } diff --git a/WifiInboundHandler.cpp b/WifiInboundHandler.cpp index fdc7154..d118fba 100644 --- a/WifiInboundHandler.cpp +++ b/WifiInboundHandler.cpp @@ -86,7 +86,9 @@ void WifiInboundHandler::loop1() { int count=inboundRing->count(); if (Diag::WIFI) DIAG(F("Wifi EXEC: %d %d:"),clientId,count); byte cmd[count+1]; - for (int i=0;iread(); + // Copy raw bytes to avoid websocket masked data being + // confused with a ram-saving flash insert marker. + for (int i=0;ireadRawByte(); cmd[count]=0; if (Diag::WIFI) DIAG(F("%e"),cmd); @@ -238,7 +240,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { dataLength--; if (dataLength == 0) { // Nothing found, this input is lost - DIAG(F("Wifi prescan not found")); + DIAG(F("Wifi prescan for websock not found")); inboundRing->commit(); loopState = ANYTHING; } @@ -249,7 +251,7 @@ WifiInboundHandler::INBOUND_STATE WifiInboundHandler::loop2() { // matched the next char of the key prescanPoint++; if (WebSocketKeyName[prescanPoint]==0) { - DIAG(F("Wifi prescan found")); + if (Diag::WEBSOCKET) DIAG(F("Wifi prescan found")); // prescan has detected full key inboundRing->print(WebSocketKeyName); loopState=IPD_POSTSCAN; // continmue as normal