Version 1.10+4
Updated with chrishamm's latest Network, Webserver and PrintMonitor module changes
This commit is contained in:
parent
1356abd707
commit
818e14f984
7 changed files with 98 additions and 80 deletions
BIN
Release/RepRapFirmware-1.10+4-dc42.bin
Normal file
BIN
Release/RepRapFirmware-1.10+4-dc42.bin
Normal file
Binary file not shown.
|
@ -30,7 +30,7 @@ Licence: GPL
|
|||
#endif
|
||||
|
||||
#ifndef VERSION
|
||||
#define VERSION "1.10+3"
|
||||
#define VERSION "1.10+4"
|
||||
#endif
|
||||
|
||||
#ifndef DATE
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Reference in a new issue