Version 1.10+4

Updated with chrishamm's latest Network, Webserver and PrintMonitor
module changes
This commit is contained in:
David Crocker 2016-03-30 13:29:13 +01:00
parent 1356abd707
commit 818e14f984
7 changed files with 98 additions and 80 deletions

Binary file not shown.

View file

@ -30,7 +30,7 @@ Licence: GPL
#endif
#ifndef VERSION
#define VERSION "1.10+3"
#define VERSION "1.10+4"
#endif
#ifndef DATE

View file

@ -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(&ethernet_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);
}

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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;
};