Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/DuetNG/DuetEthernet/Network.cpp')
-rw-r--r--src/DuetNG/DuetEthernet/Network.cpp307
1 files changed, 114 insertions, 193 deletions
diff --git a/src/DuetNG/DuetEthernet/Network.cpp b/src/DuetNG/DuetEthernet/Network.cpp
index 4f742cb8..5f7bd72c 100644
--- a/src/DuetNG/DuetEthernet/Network.cpp
+++ b/src/DuetNG/DuetEthernet/Network.cpp
@@ -20,21 +20,23 @@ void Network::SetIPAddress(const uint8_t p_ipAddress[], const uint8_t p_netmask[
Network::Network(Platform* p)
: platform(p), lastTickMillis(0),
- freeTransactions(nullptr), readyTransactions(nullptr), writingTransactions(nullptr),
httpPort(DefaultHttpPort), state(NetworkState::disabled), activated(false)
{
- SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway);
- strcpy(hostname, HOSTNAME);
}
void Network::Init()
{
- // Ensure that the chip is in the reset state
+ // Ensure that the W5500 chip is in the reset state
pinMode(EspResetPin, OUTPUT_LOW);
state = NetworkState::disabled;
longWait = platform->Time();
lastTickMillis = millis();
- InitSockets();
+
+ NetworkBuffer::AllocateBuffers(NetworkBufferCount);
+ NetworkTransaction::AllocateTransactions(NetworkTransactionCount);
+
+ SetIPAddress(DefaultIpAddress, DefaultNetMask, DefaultGateway);
+ strcpy(hostname, HOSTNAME);
}
// This is called at the end of config.g processing.
@@ -53,7 +55,8 @@ void Network::Exit()
Stop();
}
-void Network::Spin()
+// Main spin loop. If 'full' is true then we are being called from the main spin loop. If false then we are being called during HSMCI idle time.
+void Network::Spin(bool full)
{
switch(state)
{
@@ -63,9 +66,8 @@ void Network::Spin()
break;
case NetworkState::establishingLink:
- if (wizphy_getphylink() == PHY_LINK_ON)
+ if (full && wizphy_getphylink() == PHY_LINK_ON)
{
-
usingDhcp = (ipAddress[0] == 0 && ipAddress[1] == 0 && ipAddress[2] == 0 && ipAddress[3] == 0);
if (usingDhcp)
{
@@ -85,38 +87,44 @@ void Network::Spin()
break;
case NetworkState::obtainingIP:
- if (wizphy_getphylink() == PHY_LINK_ON)
+ if (full)
{
- const uint32_t now = millis();
- if (now - lastTickMillis >= 1000)
+ if (wizphy_getphylink() == PHY_LINK_ON)
{
- lastTickMillis += 1000;
- DHCP_time_handler();
+ const uint32_t now = millis();
+ if (now - lastTickMillis >= 1000)
+ {
+ lastTickMillis += 1000;
+ DHCP_time_handler();
+ }
+ const DhcpRunResult ret = DHCP_run();
+ if (ret == DhcpRunResult::DHCP_IP_ASSIGN)
+ {
+ debugPrintf("IP address obtained, network running\n");
+ getSIPR(ipAddress);
+ // Send mDNS announcement so that some routers can perform hostname mapping
+ // if this board is connected via a non-IGMP capable WiFi bridge (like the TP-Link WR701N)
+ //mdns_announce();
+ InitSockets();
+ state = NetworkState::active;
+ }
}
- const DhcpRunResult ret = DHCP_run();
- if (ret == DhcpRunResult::DHCP_IP_ASSIGN)
+ else
{
- debugPrintf("IP address obtained, network running\n");
- getSIPR(ipAddress);
- // Send mDNS announcement so that some routers can perform hostname mapping
- // if this board is connected via a non-IGMP capable WiFi bridge (like the TP-Link WR701N)
- //mdns_announce();
- InitSockets();
- state = NetworkState::active;
+ debugPrintf("Lost phy link\n");
+ DHCP_stop();
+ TerminateSockets();
+ state = NetworkState::establishingLink;
}
}
- else
- {
- DHCP_stop();
- TerminateSockets();
- state = NetworkState::establishingLink;
- }
break;
case NetworkState::active:
+ // Check that the link is still up
if (wizphy_getphylink() == PHY_LINK_ON)
{
- if (usingDhcp)
+ // Maintain DHCP
+ if (full && usingDhcp)
{
const uint32_t now = millis();
if (now - lastTickMillis >= 1000)
@@ -127,50 +135,28 @@ void Network::Spin()
const DhcpRunResult ret = DHCP_run();
if (ret == DhcpRunResult::DHCP_IP_CHANGED)
{
+ debugPrintf("IP address changed\n");
getSIPR(ipAddress);
}
}
- sockets[nextSocketToPoll].Poll();
+ // Poll the next TCP socket
+ sockets[nextSocketToPoll].Poll(full);
+
+ // Move on to the next TCP socket for next time
++nextSocketToPoll;
if (nextSocketToPoll == NumTcpSockets)
{
nextSocketToPoll = 0;
}
-#if 0
- // See if we can send anything
- NetworkTransaction *transaction = writingTransactions;
- if (transaction != nullptr /*&& sendingConnection == nullptr*/ )
- {
- if (transaction->GetNext() != nullptr)
- {
- // Data is supposed to be sent and the last packet has been acknowledged.
- // Rotate the transactions so every client is served even while multiple files are sent
- NetworkTransaction *next = transaction->GetNext();
- writingTransactions = next;
- AppendTransaction(&writingTransactions, transaction);
- transaction = next;
- }
-
- if (transaction->Send())
- {
- // This transaction can be released, do this here
- writingTransactions = transaction->GetNext();
- PrependTransaction(&freeTransactions, transaction);
-
- // If there is more data to write on this connection, do it sometime soon
- NetworkTransaction *nextWrite = transaction->GetNextWrite();
- if (nextWrite != nullptr)
- {
- PrependTransaction(&writingTransactions, nextWrite);
- }
- }
- }
-#endif
}
- else
+ else if (full)
{
- DHCP_stop();
+ debugPrintf("Lost phy link\n");
+ if (usingDhcp)
+ {
+ DHCP_stop();
+ }
TerminateSockets();
state = NetworkState::establishingLink;
}
@@ -236,7 +222,7 @@ void Network::Disable()
if (activated && state != NetworkState::disabled)
{
Stop();
- platform->Message(GENERIC_MESSAGE, "WiFi server stopped\n");
+ platform->Message(GENERIC_MESSAGE, "Network stopped\n");
}
}
@@ -289,180 +275,103 @@ void Network::SetHostname(const char *name)
bool Network::Lock()
{
- //TODO
return true;
}
void Network::Unlock()
{
- //TODO
}
bool Network::InLwip() const
{
- //TODO
return false;
}
// This is called by the web server to get the next networking transaction.
//
-// If cs is NULL, the transaction from the head of readyTransactions will be retrieved.
-// If cs is not NULL, the first transaction with the matching connection will be returned.
+// If conn is NoConnection, the transaction from the head of readyTransactions will be retrieved.
+// If conn is not NoConnection, the first transaction with the matching connection will be returned.
//
-// This method also ensures that the retrieved transaction is moved to the first item of
-// readyTransactions, so that a subsequent call with a NULL cs parameter will return exactly
-// the same instance.
+// This method also ensures that a subsequent call with a null connection parameter will return exactly the same instance.
NetworkTransaction *Network::GetTransaction(Connection conn)
{
-#if 1
- return nullptr;
-#else
- // See if there is any transaction at all
- NetworkTransaction *transaction = readyTransactions;
- if (transaction == nullptr)
- {
- return nullptr;
- }
-
- // If no specific connection is specified or if the first item already matches the
- // connection we are looking for, just return it
- if (cs == nullptr || transaction->GetConnection() == cs)
- {
- return transaction;
- }
-
- // We are looking for a specific transaction, but it's not the first item.
- // Search for it and move it to the head of readyTransactions
- NetworkTransaction *previous = transaction;
- for(NetworkTransaction *item = transaction->next; item != nullptr; item = item->next)
+ if (state == NetworkState::active)
{
- if (item->GetConnection() == cs)
+ if (conn != NoConnection)
{
- previous->next = item->next;
- item->next = readyTransactions;
- readyTransactions = item;
- return item;
+ NetworkTransaction *tr = conn->GetTransaction();
+ if (tr != nullptr && !tr->IsSending())
+ {
+ currentTransactionSocketNumber = conn->GetNumber();
+ return tr;
+ }
+ return nullptr;
}
- previous = item;
- }
-
- // We failed to find a valid transaction for the given connection
- return nullptr;
-#endif
-}
-void Network::AppendTransaction(NetworkTransaction* * list, NetworkTransaction *r)
-{
- r->next = nullptr;
- while (*list != nullptr)
- {
- list = &((*list)->next);
+ size_t socketNum = currentTransactionSocketNumber;
+ do
+ {
+ NetworkTransaction *tr = sockets[socketNum].GetTransaction();
+ if (tr != nullptr && !tr->IsSending())
+ {
+ currentTransactionSocketNumber = socketNum;
+ return tr;
+ }
+ ++socketNum;
+ if (socketNum == NumTcpSockets)
+ {
+ socketNum = 0;
+ }
+ } while (socketNum != currentTransactionSocketNumber);
}
- *list = r;
-}
-void Network::PrependTransaction(NetworkTransaction* * list, NetworkTransaction *r)
-{
- r->next = *list;
- *list = r;
+ return nullptr;
}
-void Network::OpenDataPort(uint16_t port)
+void Network::OpenDataPort(Port port)
{
- //TODO
-#if 0
- closingDataPort = false;
- tcp_pcb* pcb = tcp_new();
- tcp_bind(pcb, IP_ADDR_ANY, port);
- ftp_pasv_pcb = tcp_listen(pcb);
- tcp_accept(ftp_pasv_pcb, conn_accept);
-#endif
+ sockets[FtpSocketNumber].Init(FtpSocketNumber, port);
+ sockets[FtpSocketNumber].Poll(false);
}
-uint16_t Network::GetDataPort() const
+Port Network::GetDataPort() const
{
-#if 1
- return 0; //TODO
-#else
- return (closingDataPort || (ftp_pasv_pcb == nullptr) ? 0 : ftp_pasv_pcb->local_port);
-#endif
+ return sockets[FtpSocketNumber].GetLocalPort();
}
// Close FTP data port and purge associated PCB
void Network::CloseDataPort()
{
- //TODO
-#if 0
- // See if it's already being closed
- if (closingDataPort)
- {
- return;
- }
- closingDataPort = true;
-
- // Close remote connection of our data port or do it as soon as the last packet has been sent
- if (dataCs != nullptr)
- {
- NetworkTransaction *mySendingTransaction = dataCs->sendingTransaction;
- if (mySendingTransaction != nullptr)
- {
- mySendingTransaction->Close();
- return;
- }
- }
-
- // We can close it now, so do it here
- if (ftp_pasv_pcb != nullptr)
- {
- tcp_accept(ftp_pasv_pcb, nullptr);
- tcp_close(ftp_pasv_pcb);
- ftp_pasv_pcb = nullptr;
- }
- closingDataPort = false;
-#endif
-}
-
-// These methods keep track of our connections in case we need to send to one of them
-void Network::SaveDataConnection()
-{
-// dataCs = readyTransactions->cs->GetNumber();
+ sockets[FtpSocketNumber].Close();
}
-void Network::SaveFTPConnection()
+bool Network::AcquireFTPTransaction()
{
-// ftpCs = readyTransactions->cs->GetNumber();
+ return AcquireTransaction(FtpSocketNumber);
}
-void Network::SaveTelnetConnection()
+bool Network::AcquireDataTransaction()
{
-// telnetCs = readyTransactions->cs->GetNumber();
+ return AcquireTransaction(FtpDataSocketNumber);
}
-bool Network::AcquireFTPTransaction()
+bool Network::AcquireTelnetTransaction()
{
-#if 1
- return false; //TODO
-#else
- return AcquireTransaction(ftpCs);
-#endif
+ return AcquireTransaction(TelnetSocketNumber);
}
-bool Network::AcquireDataTransaction()
+bool Network::AcquireTransaction(SocketNumber skt)
{
-#if 1
- return false; //TODO
-#else
- return AcquireTransaction(dataCs);
-#endif
-}
+ if ( sockets[skt].GetTransaction() != nullptr
+ && sockets[skt].GetTransaction()->GetStatus() != TransactionStatus::sending
+ && sockets[skt].GetTransaction()->GetStatus() != TransactionStatus::finished
+ )
+ {
+ currentTransactionSocketNumber = skt;
+ return true;
+ }
-bool Network::AcquireTelnetTransaction()
-{
-#if 1
- return false; //TODO
-#else
- return AcquireTransaction(telnetCs);
-#endif
+ return false;
}
void Network::InitSockets()
@@ -474,7 +383,7 @@ void Network::InitSockets()
sockets[FtpSocketNumber].Init(FtpSocketNumber, FTP_PORT);
sockets[FtpDataSocketNumber].Init(FtpDataSocketNumber, 0); // FTP data port is allocated dynamically
sockets[TelnetSocketNumber].Init(TelnetSocketNumber, TELNET_PORT);
- nextSocketToProcess = nextSocketToPoll = 0;
+ nextSocketToPoll = currentTransactionSocketNumber = 0;
}
void Network::TerminateSockets()
@@ -483,11 +392,23 @@ void Network::TerminateSockets()
{
sockets[skt].Terminate();
}
+}
+void Network::Defer(NetworkTransaction *tr)
+{
+ const Socket *skt = tr->GetConnection();
+ if (skt != nullptr && skt->GetNumber() == currentTransactionSocketNumber)
+ {
+ ++currentTransactionSocketNumber;
+ if (currentTransactionSocketNumber == NumTcpSockets)
+ {
+ currentTransactionSocketNumber = 0;
+ }
+ }
}
-/*static*/ uint16_t Network::GetLocalPort(Connection conn) { return conn->GetLocalPort(); }
-/*static*/ uint16_t Network::GetRemotePort(Connection conn) { return conn->GetRemotePort(); }
+/*static*/ Port Network::GetLocalPort(Connection conn) { return conn->GetLocalPort(); }
+/*static*/ Port Network::GetRemotePort(Connection conn) { return conn->GetRemotePort(); }
/*static*/ uint32_t Network::GetRemoteIP(Connection conn) { return conn->GetRemoteIP(); }
/*static*/ bool Network::IsConnected(Connection conn) { return conn->IsConnected(); }
/*static*/ bool Network::IsTerminated(Connection conn) { return conn->IsTerminated(); }