diff options
author | David Crocker <dcrocker@eschertech.com> | 2017-03-28 20:55:22 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2017-03-28 21:35:35 +0300 |
commit | 66b7ee9ae2189e9ae09ce2c72327d570d551fe2a (patch) | |
tree | 5f5cd70f39b80004436b08f36566cc4f594982be /src/Duet | |
parent | c95223c75d2946f6008a46f92f0d678106c1550c (diff) |
Version 1.18RC1
Merged in chrishamm's code queue and input buffer code
Increased heater tuning timeout for finding peak temperatire from 60 to
120 seconds
Implemented M204
Increased precision of reported coordinates to 3 decimal places
PanelDue status responses continue to be sent while executing
M109/116/190/191 commands
Diffstat (limited to 'src/Duet')
-rw-r--r-- | src/Duet/Webserver.cpp | 266 | ||||
-rw-r--r-- | src/Duet/Webserver.h | 35 |
2 files changed, 38 insertions, 263 deletions
diff --git a/src/Duet/Webserver.cpp b/src/Duet/Webserver.cpp index d21fd99b..74c6f4b4 100644 --- a/src/Duet/Webserver.cpp +++ b/src/Duet/Webserver.cpp @@ -259,34 +259,6 @@ void Webserver::Diagnostics(MessageType mtype) telnetInterpreter->Diagnostics(mtype); } -bool Webserver::GCodeAvailable(const WebSource source) const -{ - switch (source) - { - case WebSource::HTTP: - return httpInterpreter->GCodeAvailable(); - - case WebSource::Telnet: - return telnetInterpreter->GCodeAvailable(); - } - - return false; -} - -char Webserver::ReadGCode(const WebSource source) -{ - switch (source) - { - case WebSource::HTTP: - return httpInterpreter->ReadGCode(); - - case WebSource::Telnet: - return telnetInterpreter->ReadGCode(); - } - - return 0; -} - void Webserver::HandleGCodeReply(const WebSource source, OutputBuffer *reply) { switch (source) @@ -315,20 +287,6 @@ void Webserver::HandleGCodeReply(const WebSource source, const char *reply) } } -uint16_t Webserver::GetGCodeBufferSpace(const WebSource source) const -{ - switch (source) - { - case WebSource::HTTP: - return httpInterpreter->GetGCodeBufferSpace(); - - case WebSource::Telnet: - return telnetInterpreter->GetGCodeBufferSpace(); - } - - return 0; -} - // Handle immediate disconnects here (cs will be freed after this call) // May be called by ISR, but not while LwIP is NOT locked void Webserver::ConnectionLost(Connection conn) @@ -521,7 +479,6 @@ bool ProtocolInterpreter::FinishUpload(uint32_t fileLength) Webserver::HttpInterpreter::HttpInterpreter(Platform *p, Webserver *ws, Network *n) : ProtocolInterpreter(p, ws, n), state(doingCommandWord), numSessions(0), clientsServed(0) { - gcodeReadIndex = gcodeWriteIndex = 0; gcodeReply = new OutputStack(); deferredRequestConnection = NoConnection; seq = 0; @@ -751,6 +708,7 @@ void Webserver::HttpInterpreter::SendFile(const char* nameOfFileToSend, bool isW transaction->Write("Cache-Control: no-cache, no-store, must-revalidate\n"); transaction->Write("Pragma: no-cache\n"); transaction->Write("Expires: 0\n"); + transaction->Write("Access-Control-Allow-Origin: *\n"); } const char* contentType; @@ -830,6 +788,7 @@ void Webserver::HttpInterpreter::SendGCodeReply() transaction->Write("Cache-Control: no-cache, no-store, must-revalidate\n"); transaction->Write("Pragma: no-cache\n"); transaction->Write("Expires: 0\n"); + transaction->Write("Access-Control-Allow-Origin: *\n"); transaction->Write("Content-Type: text/plain\n"); transaction->Printf("Content-Length: %u\n", gcodeReply->DataLength()); transaction->Write("Connection: close\n\n"); @@ -888,16 +847,8 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command) return; } - bool keepOpen = false; bool mayKeepOpen; - if (numQualKeys == 0) - { - GetJsonResponse(command, jsonResponse, mayKeepOpen); - } - else - { - GetJsonResponse(command, jsonResponse, mayKeepOpen); - } + GetJsonResponse(command, jsonResponse, mayKeepOpen); // Check special cases of deferred requests (rr_fileinfo) and rejected messages NetworkTransaction *transaction = webserver->currentTransaction; @@ -908,7 +859,7 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command) } // Send the JSON response - + bool keepOpen = false; if (mayKeepOpen) { // Check that the browser wants to persist the connection too @@ -927,6 +878,7 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command) transaction->Write("Cache-Control: no-cache, no-store, must-revalidate\n"); transaction->Write("Pragma: no-cache\n"); transaction->Write("Expires: 0\n"); + transaction->Write("Access-Control-Allow-Origin: *\n"); transaction->Write("Content-Type: application/json\n"); transaction->Printf("Content-Length: %u\n", (jsonResponse != nullptr) ? jsonResponse->Length() : 0); transaction->Printf("Connection: %s\n\n", keepOpen ? "keep-alive" : "close"); @@ -1011,8 +963,9 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff } else if (StringEquals(request, "gcode") && GetKeyValue("gcode") != nullptr) { - LoadGcodeBuffer(GetKeyValue("gcode")); - response->printf("{\"buff\":%u}", GetGCodeBufferSpace()); + RegularGCodeInput * const httpInput = reprap.GetGCodes()->GetHTTPInput(); + httpInput->Put(HTTP_MESSAGE, GetKeyValue("gcode")); + response->printf("{\"buff\":%u}", httpInput->BufferSpaceLeft()); } else if (StringEquals(request, "upload")) { @@ -1548,7 +1501,27 @@ bool Webserver::HttpInterpreter::ProcessMessage() ResetState(); return true; } - else if (IsAuthenticated() && StringEquals(commandWords[0], "POST")) + + if (StringEquals(commandWords[0], "OPTIONS")) + { + NetworkTransaction *transaction = webserver->currentTransaction; + + transaction->Write("HTTP/1.1 200 OK\n"); + transaction->Write("Allow: OPTIONS, GET, POST\n"); + transaction->Write("Cache-Control: no-cache, no-store, must-revalidate\n"); + transaction->Write("Pragma: no-cache\n"); + transaction->Write("Expires: 0\n"); + transaction->Write("Access-Control-Allow-Origin: *\n"); + transaction->Write("Access-Control-Allow-Headers: Content-Type\n"); + transaction->Write("Content-Length: 0\n"); + transaction->Write("\n"); + transaction->Commit(false); + + ResetState(); + return true; + } + + if (IsAuthenticated() && StringEquals(commandWords[0], "POST")) { const bool isUploadRequest = (StringEquals(commandWords[1], KO_START "upload")) || (commandWords[1][0] == '/' && StringEquals(commandWords[1] + 1, KO_START "upload")); @@ -1715,114 +1688,6 @@ bool Webserver::HttpInterpreter::RemoveAuthentication() return false; } -// Process a received string of gcodes -void Webserver::HttpInterpreter::LoadGcodeBuffer(const char* gc) -{ - char gcodeTempBuf[GCODE_LENGTH]; - uint16_t gtp = 0; - bool inComment = false; - for (;;) - { - char c = *gc++; - if (c == 0) - { - gcodeTempBuf[gtp] = 0; - ProcessGcode(gcodeTempBuf); - return; - } - - if (c == '\n') - { - gcodeTempBuf[gtp] = 0; - ProcessGcode(gcodeTempBuf); - gtp = 0; - inComment = false; - } - else - { - if (c == ';') - { - inComment = true; - } - - if (gtp == ARRAY_UPB(gcodeTempBuf)) - { - // gcode is too long, we haven't room for another character and a null - if (c != ' ' && !inComment) - { - platform->Message(HOST_MESSAGE, "Error: GCode local buffer overflow in HTTP webserver.\n"); - return; - } - // else we're either in a comment or the current character is a space. - // If we're in a comment, we'll silently truncate it. - // If the current character is a space, we'll wait until we see a non-comment character before reporting an error, - // in case the next character is end-of-line or the start of a comment. - } - else - { - gcodeTempBuf[gtp++] = c; - } - } - } -} - -// Process a null-terminated gcode -// We intercept one M Codes so we can deal with emergencies. That -// way things don't get out of sync, and - as a file name can contain -// a valid G code (!) - confusion is avoided. -void Webserver::HttpInterpreter::ProcessGcode(const char* gc) -{ - if (StringStartsWith(gc, "M112") && !isdigit(gc[4])) // emergency stop - { - reprap.EmergencyStop(); - gcodeReadIndex = gcodeWriteIndex; // clear the buffer - reprap.GetGCodes()->Reset(); - } - else - { - StoreGcodeData(gc, strlen(gc) + 1); - } -} - -// Process a received string of gcodes -void Webserver::HttpInterpreter::StoreGcodeData(const char* data, uint16_t len) -{ - if (len > GetGCodeBufferSpace()) - { - platform->Message(HOST_MESSAGE, "Error: GCode buffer overflow in HTTP Webserver!\n"); - } - else - { - uint16_t remaining = gcodeBufferLength - gcodeWriteIndex; - if (len <= remaining) - { - memcpy(gcodeBuffer + gcodeWriteIndex, data, len); - } - else - { - memcpy(gcodeBuffer + gcodeWriteIndex, data, remaining); - memcpy(gcodeBuffer, data + remaining, len - remaining); - } - gcodeWriteIndex = (gcodeWriteIndex + len) % gcodeBufferLength; - } -} - -// Feeding G Codes to the GCodes class -char Webserver::HttpInterpreter::ReadGCode() -{ - char c; - if (gcodeReadIndex == gcodeWriteIndex) - { - c = 0; - } - else - { - c = gcodeBuffer[gcodeReadIndex]; - gcodeReadIndex = (gcodeReadIndex + 1u) % gcodeBufferLength; - } - return c; -} - // Handle a G Code reply from the GCodes class void Webserver::HttpInterpreter::HandleGCodeReply(OutputBuffer *reply) { @@ -1891,6 +1756,7 @@ void Webserver::HttpInterpreter::ProcessDeferredRequest() transaction->Write("Cache-Control: no-cache, no-store, must-revalidate\n"); transaction->Write("Pragma: no-cache\n"); transaction->Write("Expires: 0\n"); + transaction->Write("Access-Control-Allow-Origin: *\n"); transaction->Write("Content-Type: application/json\n"); transaction->Printf("Content-Length: %u\n", (jsonResponse != nullptr) ? jsonResponse->Length() : 0); transaction->Printf("Connection: close\n\n"); @@ -2295,7 +2161,6 @@ void Webserver::FtpInterpreter::ProcessLine() { SendReply(500, "Unknown command."); } - break; case waitingForPasvPort: @@ -2310,7 +2175,6 @@ void Webserver::FtpInterpreter::ProcessLine() { webserver->currentTransaction->Defer(DeferralMode::ResetData); } - break; case pasvPortConnected: @@ -2566,7 +2430,7 @@ void Webserver::FtpInterpreter::ChangeDirectory(const char *newDirectory) //******************************************************************************************** Webserver::TelnetInterpreter::TelnetInterpreter(Platform *p, Webserver *ws, Network *n) - : ProtocolInterpreter(p, ws, n), connectedClients(0), processNextLine(false), gcodeReadIndex(0), gcodeWriteIndex(0), gcodeReply(nullptr) + : ProtocolInterpreter(p, ws, n), connectedClients(0), processNextLine(false), gcodeReply(nullptr) { ResetState(); } @@ -2638,7 +2502,8 @@ bool Webserver::TelnetInterpreter::CanParseData() } // In order to support TCP streaming mode, check if we can store any more data at this time - if (GetGCodeBufferSpace() < clientPointer + 1) + RegularGCodeInput * const telnetInput = reprap.GetGCodes()->GetTelnetInput(); + if (telnetInput->BufferSpaceLeft() < clientPointer + 1) { webserver->currentTransaction->Defer(DeferralMode::DeferOnly); return false; @@ -2697,7 +2562,8 @@ bool Webserver::TelnetInterpreter::CharFromClient(char c) { // This line is complete, do we have enough space left to store it? clientMessage[clientPointer] = 0; - if (GetGCodeBufferSpace() < clientPointer + 1) + RegularGCodeInput * const telnetInput = reprap.GetGCodes()->GetTelnetInput(); + if (telnetInput->BufferSpaceLeft() < clientPointer + 1) { // No - defer this transaction, so we can process more of it next time webserver->currentTransaction->Defer(DeferralMode::DeferOnly); @@ -2731,7 +2597,6 @@ void Webserver::TelnetInterpreter::ResetState() state = idle; connectTime = 0; clientPointer = 0; - gcodeReadIndex = gcodeWriteIndex; // clear the buffer } // Usually we should not try to send any data here, because that would purge the packet's @@ -2774,70 +2639,15 @@ bool Webserver::TelnetInterpreter::ProcessLine() transaction->Commit(false); return true; } + // All other codes are stored for the GCodes class - ProcessGcode(clientMessage); + RegularGCodeInput * const telnetInput = reprap.GetGCodes()->GetTelnetInput(); + telnetInput->Put(TELNET_MESSAGE, clientMessage); break; } return false; } -// Process a null-terminated gcode -// We intercept one M Codes so we can deal with emergencies. That -// way things don't get out of sync, and - as a file name can contain -// a valid G code (!) - confusion is avoided. -void Webserver::TelnetInterpreter::ProcessGcode(const char* gc) -{ - if (StringStartsWith(gc, "M112") && !isdigit(gc[4])) // emergency stop - { - reprap.EmergencyStop(); - gcodeReadIndex = gcodeWriteIndex; // clear the buffer - reprap.GetGCodes()->Reset(); - } - else - { - StoreGcodeData(gc, strlen(gc) + 1); - } -} - -// Process a received string of gcodes -void Webserver::TelnetInterpreter::StoreGcodeData(const char* data, uint16_t len) -{ - if (len > GetGCodeBufferSpace()) - { - platform->Message(HOST_MESSAGE, "Error: GCode buffer overflow in Telnet Webserver!\n"); - } - else - { - uint16_t remaining = gcodeBufferLength - gcodeWriteIndex; - if (len <= remaining) - { - memcpy(gcodeBuffer + gcodeWriteIndex, data, len); - } - else - { - memcpy(gcodeBuffer + gcodeWriteIndex, data, remaining); - memcpy(gcodeBuffer, data + remaining, len - remaining); - } - gcodeWriteIndex = (gcodeWriteIndex + len) % gcodeBufferLength; - } -} - -// Feeding G Codes to the GCodes class -char Webserver::TelnetInterpreter::ReadGCode() -{ - char c; - if (gcodeReadIndex == gcodeWriteIndex) - { - c = 0; - } - else - { - c = gcodeBuffer[gcodeReadIndex]; - gcodeReadIndex = (gcodeReadIndex + 1u) % gcodeBufferLength; - } - return c; -} - // Handle a G-Code reply from the GCodes class; replace \n with \r\n void Webserver::TelnetInterpreter::HandleGCodeReply(OutputBuffer *reply) { diff --git a/src/Duet/Webserver.h b/src/Duet/Webserver.h index 3e4f2c30..698f6ea4 100644 --- a/src/Duet/Webserver.h +++ b/src/Duet/Webserver.h @@ -130,15 +130,10 @@ public: void Exit(); void Diagnostics(MessageType mtype); - bool GCodeAvailable(const WebSource source) const; - char ReadGCode(const WebSource source); void HandleGCodeReply(const WebSource source, OutputBuffer *reply); void HandleGCodeReply(const WebSource source, const char *reply); uint32_t GetReplySeq() const; - // Returns the available G-Code buffer space of the HTTP interpreter (may be dropped in a future version) - uint16_t GetGCodeBufferSpace(const WebSource source) const; - void ConnectionLost(Connection conn /*const ConnectionState *cs*/); void ConnectionError(); @@ -161,11 +156,8 @@ protected: bool DoingFastUpload() const override; void DoFastUpload(); - bool GCodeAvailable() const; - char ReadGCode(); void HandleGCodeReply(OutputBuffer *reply); void HandleGCodeReply(const char *reply); - uint16_t GetGCodeBufferSpace() const; uint32_t GetReplySeq() const; private: @@ -234,17 +226,7 @@ protected: bool RemoveAuthentication(); const char* GetKeyValue(const char *key) const; // return the value of the specified key, or nullptr if not present - // Deal with incoming G-Codes - - char gcodeBuffer[gcodeBufferLength]; - uint16_t gcodeReadIndex, gcodeWriteIndex; // head and tail indices into gcodeBuffer - - void LoadGcodeBuffer(const char* gc); - void ProcessGcode(const char* gc); - void StoreGcodeData(const char* data, uint16_t len); - // Responses from GCodes class - uint32_t seq; // Sequence number for G-Code replies OutputStack *gcodeReply; @@ -318,11 +300,8 @@ protected: bool CharFromClient(const char c) override; void ResetState(); - bool GCodeAvailable() const; - char ReadGCode(); void HandleGCodeReply(OutputBuffer *reply); void HandleGCodeReply(const char *reply); - uint16_t GetGCodeBufferSpace() const; void SendGCodeReply(); @@ -345,16 +324,7 @@ protected: bool ProcessLine(); - // Deal with incoming G-Codes - - char gcodeBuffer[gcodeBufferLength]; - uint16_t gcodeReadIndex, gcodeWriteIndex; // head and tail indices into gcodeBuffer - - void ProcessGcode(const char* gc); - void StoreGcodeData(const char* data, uint16_t len); - // Converted response from GCodes class (NL -> CRNL) - OutputBuffer * volatile gcodeReply; }; TelnetInterpreter *telnetInterpreter; @@ -376,11 +346,6 @@ inline bool ProtocolInterpreter::IsUploading() const { return uploadState != not inline uint32_t Webserver::GetReplySeq() const { return httpInterpreter->GetReplySeq(); } -inline uint16_t Webserver::HttpInterpreter::GetGCodeBufferSpace() const { return (gcodeReadIndex - gcodeWriteIndex - 1u) % gcodeBufferLength; } -inline bool Webserver::HttpInterpreter::GCodeAvailable() const { return gcodeReadIndex != gcodeWriteIndex; } inline uint32_t Webserver::HttpInterpreter::GetReplySeq() const { return seq; } -inline uint16_t Webserver::TelnetInterpreter::GetGCodeBufferSpace() const { return (gcodeReadIndex - gcodeWriteIndex - 1u) % gcodeBufferLength; } -inline bool Webserver::TelnetInterpreter::GCodeAvailable() const { return gcodeReadIndex != gcodeWriteIndex; } - #endif |