diff options
author | David Crocker <dcrocker@eschertech.com> | 2016-03-30 15:29:13 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2016-03-30 15:29:13 +0300 |
commit | 818e14f98470c292d678aafbda5eefe5f5f60e21 (patch) | |
tree | 0bd7ff8716241329b8531f9473c94e1745ec905f /src | |
parent | 1356abd70713d99bee4e1fbb0e183edf6a6f5398 (diff) |
Version 1.10+4
Updated with chrishamm's latest Network, Webserver and PrintMonitor
module changes
Diffstat (limited to 'src')
-rw-r--r-- | src/Configuration.h | 2 | ||||
-rw-r--r-- | src/Network.cpp | 65 | ||||
-rw-r--r-- | src/Network.h | 4 | ||||
-rw-r--r-- | src/PrintMonitor.cpp | 4 | ||||
-rw-r--r-- | src/Webserver.cpp | 95 | ||||
-rw-r--r-- | src/Webserver.h | 8 |
6 files changed, 98 insertions, 80 deletions
diff --git a/src/Configuration.h b/src/Configuration.h index 3f9e4ce1..6aabd1d4 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -30,7 +30,7 @@ Licence: GPL #endif #ifndef VERSION -#define VERSION "1.10+3" +#define VERSION "1.10+4" #endif #ifndef DATE diff --git a/src/Network.cpp b/src/Network.cpp index 0e9154d8..51419ea4 100644 --- a/src/Network.cpp +++ b/src/Network.cpp @@ -124,9 +124,11 @@ void UnlockLWIP() lwipLocked = false; } -// Callback functions for the EMAC driver +// Callback functions for the EMAC driver and for LwIP -// Callback to report when the link has gone up or down +// Callback to report when the network interface has gone up or down. +// Note that this is only a rough indicator and may not be called when +// the IP address is changed on-the-fly! static void ethernet_status_callback(struct netif *netif) { if (netif_is_up(netif)) @@ -134,10 +136,6 @@ static void ethernet_status_callback(struct netif *netif) char ip[16]; ipaddr_ntoa_r(&(netif->ip_addr), ip, sizeof(ip)); reprap.GetPlatform()->MessageF(HOST_MESSAGE, "Network up, IP=%s\n", ip); - - // Do mDNS announcement here and not while the network is being initialised, - // because the IP address may not be assigned at that time - mdns_announce(); } else { @@ -178,8 +176,6 @@ static void conn_err(void *arg, err_t err) } } -/*-----------------------------------------------------------------------------------*/ - static err_t conn_poll(void *arg, tcp_pcb *pcb) { ConnectionState *cs = (ConnectionState*)arg; @@ -235,8 +231,6 @@ static err_t conn_poll(void *arg, tcp_pcb *pcb) return ERR_OK; } -/*-----------------------------------------------------------------------------------*/ - static err_t conn_sent(void *arg, tcp_pcb *pcb, u16_t len) { ConnectionState *cs = (ConnectionState*)arg; @@ -259,8 +253,6 @@ static err_t conn_sent(void *arg, tcp_pcb *pcb, u16_t len) return ERR_OK; } -/*-----------------------------------------------------------------------------------*/ - static err_t conn_recv(void *arg, tcp_pcb *pcb, pbuf *p, err_t err) { ConnectionState *cs = (ConnectionState*)arg; @@ -302,8 +294,6 @@ static err_t conn_recv(void *arg, tcp_pcb *pcb, pbuf *p, err_t err) return ERR_OK; } -/*-----------------------------------------------------------------------------------*/ - static err_t conn_accept(void *arg, tcp_pcb *pcb, err_t err) { LWIP_UNUSED_ARG(arg); @@ -413,7 +403,7 @@ void Network::Spin() return; } - if (state == NetworkActive) + if (state == NetworkObtainingIP || state == NetworkActive) { // Is the link still up? if (!ethernet_link_established()) @@ -425,7 +415,7 @@ void Network::Spin() return; } - // See if we can read any packets + // See if we can read any packets. They may include DHCP responses too ethernet_task(); if (resetCallback) { @@ -433,6 +423,21 @@ void Network::Spin() ethernet_set_rx_callback(ðernet_rx_callback); } + // Have we obtained a valid IP address yet? + if (state == NetworkObtainingIP) + { + const uint8_t *ip = ethernet_get_ipaddress(); + if (ip[0] != 0 && ip[1] != 0 && ip[2] != 0 && ip[3] != 0) + { + // Yes - we're good to go now + state = NetworkActive; + + // Send mDNS announcement so that some routers can perform hostname mapping + // if ths board is connected via a non-IGMP capable WiFi bridge (like the TP-Link WR701N) + mdns_announce(); + } + } + // See if we can send anything NetworkTransaction *transaction = writingTransactions; if (transaction != nullptr && sendingConnection == nullptr) @@ -476,7 +481,7 @@ void Network::Spin() { ethernet_set_configuration(platform->IPAddress(), platform->NetMask(), platform->GateWay()); } - state = NetworkActive; + state = NetworkObtainingIP; } UnlockLWIP(); @@ -615,6 +620,7 @@ void Network::ConnectionClosed(ConnectionState* cs, bool closeConnection) tcp_poll(pcb, nullptr, TCP_WRITE_TIMEOUT / TCP_SLOW_INTERVAL / TCP_MAX_SEND_RETRIES); if (pcb != nullptr && closeConnection) { + tcp_err(pcb, nullptr); tcp_close(pcb); } cs->pcb = nullptr; @@ -697,6 +703,7 @@ bool Network::ConnectionClosedGracefully(ConnectionState *cs) tcp_sent(cs->pcb, nullptr); tcp_recv(cs->pcb, nullptr); tcp_poll(cs->pcb, nullptr, TCP_WRITE_TIMEOUT / TCP_SLOW_INTERVAL / TCP_MAX_SEND_RETRIES); + tcp_err(cs->pcb, nullptr); tcp_close(cs->pcb); cs->pcb = nullptr; @@ -736,7 +743,7 @@ const uint8_t *Network::IPAddress() const void Network::SetIPAddress(const uint8_t ipAddress[], const uint8_t netmask[], const uint8_t gateway[]) { - if (state == NetworkActive) + if (state == NetworkObtainingIP || state == NetworkActive) { // This performs IP changes on-the-fly ethernet_set_configuration(ipAddress, netmask, gateway); @@ -878,22 +885,20 @@ uint16_t Network::GetHttpPort() const void Network::SetHttpPort(uint16_t port) { - if (state == NetworkActive && port != httpPort) + if (port != httpPort) { - // Close old HTTP port + // Close the old HTTP PCB and create a new one tcp_close(http_pcb); + httpPort = port; + httpd_init(); - // Create a new one for the new port - tcp_pcb* pcb = tcp_new(); - tcp_bind(pcb, IP_ADDR_ANY, port); - http_pcb = tcp_listen(pcb); - tcp_accept(http_pcb, conn_accept); - - // Update mDNS services + // Update mDNS service mdns_services[MDNS_HTTP_SERVICE_INDEX].port = port; - mdns_announce(); + if (state == NetworkActive) + { + mdns_announce(); + } } - httpPort = port; } // Close FTP data port and purge associated PCB @@ -1488,7 +1493,7 @@ void NetworkTransaction::Discard() { if (reprap.Debug(moduleNetwork)) { - reprap.GetPlatform()->MessageF(HOST_MESSAGE, "Network: Discard() is handling a graceful disconnect for cs=%08x\n", (unsigned int)cs); + reprap.GetPlatform()->Message(HOST_MESSAGE, "Network: Discard() is handling a graceful disconnect\n"); } reprap.GetNetwork()->ConnectionClosed(cs, false); } diff --git a/src/Network.h b/src/Network.h index 9f80cb85..3cee3d45 100644 --- a/src/Network.h +++ b/src/Network.h @@ -15,6 +15,7 @@ Separated out from Platform.h by dc42 and extended by zpl #include <climits> #include "lwipopts.h" + #include "OutputMemory.h" // This class handles the network - typically an Ethernet. @@ -41,7 +42,6 @@ const uint16_t DEFAULT_HTTP_PORT = 80; const uint16_t FTP_PORT = 21; const uint16_t TELNET_PORT = 23; - /****************************************************************************************************/ struct tcp_pcb; @@ -201,7 +201,7 @@ class Network NetworkTransaction * volatile readyTransactions; NetworkTransaction * volatile writingTransactions; - enum { NetworkInactive, NetworkEstablishingLink, NetworkActive } state; + enum { NetworkInactive, NetworkEstablishingLink, NetworkObtainingIP, NetworkActive } state; bool isEnabled; volatile bool resetCallback; char hostname[16]; // Limit DHCP hostname to 15 characters + terminating 0 diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp index 3d5f29f0..d1caa5d5 100644 --- a/src/PrintMonitor.cpp +++ b/src/PrintMonitor.cpp @@ -593,7 +593,7 @@ bool PrintMonitor::GetFileInfoResponse(const char *filename, OutputBuffer *&resp if (filename != nullptr && filename[0] != 0) { GCodeFileInfo info; - if (!GetFileInfo("0:/", filename, info)) + if (!GetFileInfo(FS_PREFIX, filename, info)) { // This may take a few runs... return false; @@ -681,7 +681,7 @@ void PrintMonitor::StopParsing(const char *filename) { if (parseState != notParsing && StringEquals(filenameBeingParsed, filename)) { - if (!printingFileParsed) + if (filenameBeingPrinted[0] != 0 && !printingFileParsed) { // If this is the file we're parsing for internal purposes, don't bother with this request return; diff --git a/src/Webserver.cpp b/src/Webserver.cpp index 02290b20..8106d2e7 100644 --- a/src/Webserver.cpp +++ b/src/Webserver.cpp @@ -89,7 +89,6 @@ const char* badEscapeResponse = "bad escape"; //******************************************************************************************** - // Constructor and initialisation Webserver::Webserver(Platform* p, Network *n) : platform(p), network(n), webserverActive(false) { @@ -103,6 +102,7 @@ void Webserver::Init() // initialise the webserver class longWait = platform->Time(); webserverActive = true; + readingConnection = nullptr; // initialise all protocol handlers httpInterpreter->ResetState(); @@ -110,7 +110,6 @@ void Webserver::Init() telnetInterpreter->ResetState(); } - // Deal with input/output from/to the client (if any) void Webserver::Spin() { @@ -136,7 +135,7 @@ void Webserver::Spin() telnetInterpreter->Spin(); // See if we have new data to process - currentTransaction = network->GetTransaction(); + currentTransaction = network->GetTransaction(readingConnection); if (currentTransaction != nullptr) { // Take care of different protocol types here @@ -209,7 +208,8 @@ void Webserver::Spin() // Process other messages (if we can) else if (interpreter != httpInterpreter || httpInterpreter->IsReady()) { - for(size_t i = 0; i < 500; i++) + readingConnection = currentTransaction->GetConnection(); + for(size_t i = 0; i < TCP_MSS / 3; i++) { char c; if (currentTransaction->Read(c)) @@ -218,20 +218,29 @@ void Webserver::Spin() // calling either Commit(), Discard() or Defer() if (interpreter->CharFromClient(c)) { + readingConnection = nullptr; break; } } else { - // We ran out of data before finding a complete request. - // This happens when the incoming message length exceeds the TCP MSS. - // Notify the current ProtocolInterpreter about this + // We ran out of data before finding a complete request. This happens when the incoming + // message length exceeds the TCP MSS. Notify the current ProtocolInterpreter about this, + // which will remove the current transaction too interpreter->NoMoreDataAvailable(); + readingConnection = nullptr; break; } } } } + else if (readingConnection != nullptr) + { + // We failed to find a transaction for a reading connection. + // This should never happen, but if it does, terminate this connection instantly + platform->Message(HOST_MESSAGE, "Error: Transaction for reading connection not found\n"); + readingConnection->Terminate(); + } network->Unlock(); // unlock LWIP again } platform->ClassReport(longWait); @@ -364,6 +373,12 @@ void Webserver::ConnectionLost(const ConnectionState *cs) platform->MessageF(HOST_MESSAGE, "ConnectionLost called for local port %d (remote port %d)\n", localPort, cs->GetRemotePort()); } interpreter->ConnectionLost(cs); + + // Don't process any more data from this connection if has gone down + if (readingConnection == cs) + { + readingConnection = nullptr; + } } @@ -405,6 +420,13 @@ void ProtocolInterpreter::ConnectionEstablished() webserver->currentTransaction->Discard(); } +void ProtocolInterpreter::NoMoreDataAvailable() +{ + // Request is not complete yet, but don't care. Interpreters that do not explicitly + // overwrite this method don't support more than one connected client anyway + webserver->currentTransaction->Discard(); +} + // Start writing to a new file bool ProtocolInterpreter::StartUpload(FileStore *file, const char *fileName) { @@ -514,7 +536,7 @@ Webserver::HttpInterpreter::HttpInterpreter(Platform *p, Webserver *ws, Network { gcodeReadIndex = gcodeWriteIndex = 0; gcodeReply = new OutputStack(); - processingDeferredRequest = false; + deferredRequestConnection = nullptr; seq = 0; } @@ -877,11 +899,12 @@ bool Webserver::HttpInterpreter::IsReady() } // Are we still processing a deferred request? - if (processingDeferredRequest && deferredRequestConnection == webserver->currentTransaction->GetConnection()) + if (deferredRequestConnection == webserver->currentTransaction->GetConnection()) { if (deferredRequestConnection->IsConnected()) { - // Process more of this request + // Process more of this request. If it doesn't finish this time, it will be appended to the list + // of ready transactions again, which will ensure it can be processed later again ProcessDeferredRequest(); } else @@ -997,9 +1020,9 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff } else if (StringEquals(request, "fileinfo")) { - if (processingDeferredRequest) + if (deferredRequestConnection != nullptr) { - // Don't allow multiple requests to be processed at once + // Don't allow multiple deferred requests to be processed at once webserver->currentTransaction->Defer(true); } else @@ -1076,14 +1099,16 @@ void Webserver::HttpInterpreter::NoMoreDataAvailable() void Webserver::HttpInterpreter::ConnectionLost(const ConnectionState *cs) { // Make sure deferred requests are cancelled - if (processingDeferredRequest && deferredRequestConnection == cs) + if (deferredRequestConnection == cs) { - if (filenameBeingProcessed[0] != 0) - { - // Only stop the parsing process if the filename is valid - reprap.GetPrintMonitor()->StopParsing(filenameBeingProcessed); - } - processingDeferredRequest = false; + reprap.GetPrintMonitor()->StopParsing(filenameBeingProcessed); + deferredRequestConnection = nullptr; + } + + // If we couldn't read an entire request from a connection, reset our state here again + if (webserver->readingConnection == cs) + { + ResetState(); } // Deal with aborted POST uploads. Note that we also check the remote port here, @@ -1756,7 +1781,7 @@ void Webserver::HttpInterpreter::HandleGCodeReply(const char *reply) void Webserver::HttpInterpreter::ProcessDeferredRequest() { OutputBuffer *jsonResponse = nullptr; - bool doingDeferredRequest = processingDeferredRequest; + const ConnectionState *lastDeferredConnection = deferredRequestConnection; // At the moment only file info requests are deferred. // Parsing the file may take a while, so keep LwIP running while we're waiting @@ -1765,13 +1790,14 @@ void Webserver::HttpInterpreter::ProcessDeferredRequest() while (!network->Lock()); // Because LwIP was unlocked before, there is a chance that the ConnectionLost() call has already - // stopped the file parsing. Check this special case - NetworkTransaction *transaction = webserver->currentTransaction; - if (doingDeferredRequest == processingDeferredRequest) + // stopped the file parsing. Check this special case here + if (lastDeferredConnection == deferredRequestConnection) { - processingDeferredRequest = !gotFileInfo; + NetworkTransaction *transaction = webserver->currentTransaction; if (gotFileInfo) { + deferredRequestConnection = nullptr; + // Got it - send the response now transaction->Write("HTTP/1.1 200 OK\n"); transaction->Write("Cache-Control: no-cache, no-store, must-revalidate\n"); @@ -1790,9 +1816,13 @@ void Webserver::HttpInterpreter::ProcessDeferredRequest() transaction->Defer(false); } } + else + { + // Clean up again if we cannot send the response at all + OutputBuffer::ReleaseAll(jsonResponse); + } } - //******************************************************************************************** // //************************* FTP interpreter for the Webserver class ************************** @@ -1954,12 +1984,6 @@ void Webserver::FtpInterpreter::ResetState() state = idle; } -void Webserver::FtpInterpreter::NoMoreDataAvailable() -{ - clientPointer = 0; - SendReply(422, "Incomplete or too long request", true); -} - bool Webserver::FtpInterpreter::DoingFastUpload() const { return (IsUploading() && webserver->currentTransaction->GetLocalPort() == network->GetDataPort()); @@ -2572,15 +2596,6 @@ void Webserver::TelnetInterpreter::ResetState() clientPointer = 0; } -void Webserver::TelnetInterpreter::NoMoreDataAvailable() -{ - clientPointer = 0; - - NetworkTransaction *transaction = webserver->currentTransaction; - transaction->Write("Invalid or too long request\r\n"); - transaction->Commit(true); -} - void Webserver::TelnetInterpreter::ProcessLine() { NetworkTransaction *transaction = network->GetTransaction(); diff --git a/src/Webserver.h b/src/Webserver.h index 6f554c3b..3ec60303 100644 --- a/src/Webserver.h +++ b/src/Webserver.h @@ -85,7 +85,7 @@ class ProtocolInterpreter virtual void ConnectionEstablished(); virtual void ConnectionLost(const ConnectionState *cs) { } virtual bool CharFromClient(const char c) = 0; - virtual void NoMoreDataAvailable() = 0; + virtual void NoMoreDataAvailable(); virtual bool DoingFastUpload() const; virtual void DoFastUpload(); @@ -250,8 +250,7 @@ class Webserver uint32_t postFileLength, uploadedBytes; // How many POST bytes do we expect and how many have already been written? // Deferred requests (rr_fileinfo) - bool processingDeferredRequest; // Are we processing a transaction multiple times to retrieve information? - ConnectionState *deferredRequestConnection; // Which connection expects a response? + ConnectionState * volatile deferredRequestConnection; // Which connection expects a response for a deferred request? char filenameBeingProcessed[FILENAME_LENGTH]; // The filename being processed (for rr_fileinfo) void ProcessDeferredRequest(); @@ -268,7 +267,6 @@ class Webserver void ConnectionEstablished() override; void ConnectionLost(const ConnectionState *cs) override; bool CharFromClient(const char c) override; - void NoMoreDataAvailable() override; void ResetState(); bool DoingFastUpload() const override; @@ -314,7 +312,6 @@ class Webserver void ConnectionEstablished() override; void ConnectionLost(const ConnectionState *cs) override; bool CharFromClient(const char c) override; - void NoMoreDataAvailable() override; void ResetState(); bool GCodeAvailable() const; @@ -364,6 +361,7 @@ class Webserver Network* network; bool webserverActive; NetworkTransaction *currentTransaction; + ConnectionState * volatile readingConnection; float longWait; }; |