diff options
author | David Crocker <dcrocker@eschertech.com> | 2018-02-28 19:37:07 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2018-02-28 19:45:25 +0300 |
commit | fa55cdada75c00cac180e26a31e151ed18093abd (patch) | |
tree | 282a59f5bdc524a8e3a8214b64b77cbb440a14b9 /src/Networking | |
parent | 3b2c5340e1b8a399335c0e2b0dbe68aff55ec168 (diff) |
Version 1.21RC3
Upgrade notes:
- On Cartesian and CoreXY printers, normal G0 and G1 moves are no longer
allowed before the corresponding axes have been homed. In particular, if
your homex.g, homey.g and homeall.g files raise Z a little at the start
and lower it at the end, you will need to add the S2 parameter to those
G1 Z moves. Otherwise the G1 Z move will be refused unless Z has already
been homed and the homing macro will be terminated.
New features:
- On Cartesian and CoreXY printers, normal movement commands are no
longer permitted until the corresponding axes have been homed
- Illegal movement commands in a print file or macro file cause the file
to be terminated and heaters/spindle motors/lasers to be turned off;
except that when the printer is in FDM mode, G0 and G1 moves outside the
movement limits are just truncated as before
- The M39 command reports the SD card cluster size
- If GCode attempts to set the temperature of a non-existent bed or
chamber heater to zero (to turn it off), the error message that would
normally be generated is suppressed
- G60 command to set a restore point is implemented
- M671 command now supports the F (fudge factor) parameter
- The standstill current fraction can now be set on the Duet Maestro
build
- M118 support added (thanks chrishamm)
- When using external stepper drivers the DIR signal is no longer
changed before the step pulse has ended
- The M452, M453 and M573 commands now support the I1 parameter to
invert the laser, spindle or extrusion signal polarity
Bug fixes
- Duet Ethernet only: fixed bugs in the DHCP client code that could
cause the printer to become very slow
- G2 and G3 arc moves are terminated if the attempt to exceed the axis
limits
- When multi-touch Z probe mode is enabled, the recovery time is applied
before all probing movements, not just the first one
- Z probe mode 9 (for BLTouch) ow works in multi-touch mode
- During simulation the status is set to "Simulating" instead of
"Printing"
- M556 with a zero S parameter no longer messes up the coordinate
calculations
- When large files were uploaded or copied to the SD card and the
cluster size was small, HTTP requests could time out while DWC attempted
to get the information for those files
- The Duet3D rotating magnet filament monitor is supported again
- FTP didn't work reliable in 1.21RC2
- Endstops 5 thru 9 on a DueX2/DueX5 board can now be used for simple
filament sensors
- When resuming a paused print the first move executed was sometimes
incorrect
Diffstat (limited to 'src/Networking')
19 files changed, 201 insertions, 489 deletions
diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.cpp b/src/Networking/ESP8266WiFi/WiFiInterface.cpp index 564637d2..3b8bfaa1 100644 --- a/src/Networking/ESP8266WiFi/WiFiInterface.cpp +++ b/src/Networking/ESP8266WiFi/WiFiInterface.cpp @@ -121,7 +121,7 @@ static void EspTransferRequestIsr(CallbackParameter) static inline void EnableEspInterrupt() { - attachInterrupt(EspDataReadyPin, EspTransferRequestIsr, RISING, nullptr); + attachInterrupt(EspDataReadyPin, EspTransferRequestIsr, INTERRUPT_MODE_RISING, nullptr); } static inline void DisableEspInterrupt() @@ -673,12 +673,10 @@ void WiFiInterface::Spin(bool full) // Check for debug info received from the WiFi module if (debugPrintPending) { -#if 0 if (reprap.Debug(moduleWiFi)) { debugPrintf("WiFi: %s\n", debugMessageBuffer.Pointer()); } -#endif debugMessageBuffer.Clear(); debugPrintPending = false; } @@ -1197,11 +1195,6 @@ void WiFiInterface::TerminateDataPort() } } -void WiFiInterface::DataPortClosing() -{ - StopListening(ftpDataPort); -} - #if USE_PDC static Pdc *spi_pdc; #endif diff --git a/src/Networking/ESP8266WiFi/WiFiInterface.h b/src/Networking/ESP8266WiFi/WiFiInterface.h index 35561f7c..a77573a2 100644 --- a/src/Networking/ESP8266WiFi/WiFiInterface.h +++ b/src/Networking/ESP8266WiFi/WiFiInterface.h @@ -44,8 +44,8 @@ public: void Exit() override; void Spin(bool full) override; void Diagnostics(MessageType mtype) override; - void Start() override; - void Stop() override; + void Start(); + void Stop(); GCodeResult EnableInterface(int mode, const StringRef& ssid, const StringRef& reply) override; // enable or disable the network GCodeResult EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) override; @@ -65,7 +65,6 @@ public: void OpenDataPort(Port port) override; void TerminateDataPort() override; - void DataPortClosing() override; // The remaining functions are specific to the WiFi version GCodeResult HandleWiFiCode(int mcode, GCodeBuffer &gb, const StringRef& reply, OutputBuffer*& longReply); diff --git a/src/Networking/FtpResponder.cpp b/src/Networking/FtpResponder.cpp index 42086913..635bf362 100644 --- a/src/Networking/FtpResponder.cpp +++ b/src/Networking/FtpResponder.cpp @@ -128,8 +128,6 @@ bool FtpResponder::Spin() outBuf->copy("226 Transfer complete.\r\n"); } Commit(ResponderState::reading); - - // Close the data port again CloseDataPort(); } else @@ -891,7 +889,6 @@ void FtpResponder::CloseDataPort() if (dataSocket != nullptr) { - dataSocket->GetInterface()->DataPortClosing(); dataSocket->Close(); // close it gracefully dataSocket = nullptr; } diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp index 9d129ecd..c203cf28 100644 --- a/src/Networking/LwipEthernet/LwipEthernetInterface.cpp +++ b/src/Networking/LwipEthernet/LwipEthernetInterface.cpp @@ -657,17 +657,6 @@ void LwipEthernetInterface::TerminateDataPort() } } -// Stop listening on a port -void LwipEthernetInterface::DataPortClosing() -{ - // This is currently called only for the FTP data port - if (listeningPcbs[NumProtocols] != nullptr) - { - tcp_close(listeningPcbs[NumProtocols]); - listeningPcbs[NumProtocols] = nullptr; - } -} - void LwipEthernetInterface::InitSockets() { for (size_t i = 0; i < NumProtocols; ++i) diff --git a/src/Networking/LwipEthernet/LwipEthernetInterface.h b/src/Networking/LwipEthernet/LwipEthernetInterface.h index c816e573..6acdfae1 100644 --- a/src/Networking/LwipEthernet/LwipEthernetInterface.h +++ b/src/Networking/LwipEthernet/LwipEthernetInterface.h @@ -36,8 +36,6 @@ public: void Spin(bool full) override; void Interrupt() override; void Diagnostics(MessageType mtype) override; - void Start() override; - void Stop() override; GCodeResult EnableInterface(int mode, const StringRef& ssid, const StringRef& reply) override; // enable or disable the network GCodeResult EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) override; @@ -60,7 +58,6 @@ public: void OpenDataPort(Port port) override; void TerminateDataPort() override; - void DataPortClosing() override; private: enum class NetworkState @@ -73,6 +70,8 @@ private: active // network running }; + void Start(); + void Stop(); void InitSockets(); void TerminateSockets(); diff --git a/src/Networking/Network.cpp b/src/Networking/Network.cpp index 3dd42c52..18586b72 100644 --- a/src/Networking/Network.cpp +++ b/src/Networking/Network.cpp @@ -228,31 +228,6 @@ GCodeResult Network::GetNetworkState(unsigned int interface, const StringRef& re return GCodeResult::error; } -// Start up the network -void Network::Start(unsigned int interface) -{ - if (interface < NumNetworkInterfaces) - { - interfaces[interface]->Start(); - } -} - -// Stop the network -void Network::Stop(unsigned int interface) -{ -#if 0 // chrishamm: I wonder if this is actually needed - when sockets are disabled their state changes anyway - for (NetworkResponder *r = responders; r != nullptr; r = r->GetNext()) - { - r->Terminate(AnyProtocol); - } -#endif - - if (interface < NumNetworkInterfaces && interfaces[interface] != nullptr) - { - interfaces[interface]->Stop(); - } -} - bool Network::IsWiFiInterface(unsigned int interface) const { return interface < NumNetworkInterfaces && interfaces[interface]->IsWiFiInterface(); diff --git a/src/Networking/Network.h b/src/Networking/Network.h index 6cd2d268..308ec272 100644 --- a/src/Networking/Network.h +++ b/src/Networking/Network.h @@ -45,9 +45,6 @@ public: void Interrupt(); void Diagnostics(MessageType mtype); bool InNetworkStack() const; - - void Start(unsigned int interface); - void Stop(unsigned int interface); bool IsWiFiInterface(unsigned int interface) const; GCodeResult EnableInterface(unsigned int interface, int mode, const StringRef& ssid, const StringRef& reply); diff --git a/src/Networking/NetworkInterface.h b/src/Networking/NetworkInterface.h index a292d34b..6e10ea4f 100644 --- a/src/Networking/NetworkInterface.h +++ b/src/Networking/NetworkInterface.h @@ -20,8 +20,6 @@ public: virtual void Spin(bool full) = 0; virtual void Interrupt() { }; virtual void Diagnostics(MessageType mtype) = 0; - virtual void Start() = 0; - virtual void Stop() = 0; virtual GCodeResult EnableInterface(int mode, const StringRef& ssid, const StringRef& reply) = 0; virtual GCodeResult GetNetworkState(const StringRef& reply) = 0; @@ -42,7 +40,6 @@ public: virtual void OpenDataPort(Port port) = 0; virtual void TerminateDataPort() = 0; - virtual void DataPortClosing() = 0; protected: Port portNumbers[NumProtocols]; // port number used for each protocol diff --git a/src/Networking/Socket.h b/src/Networking/Socket.h index aa0aa324..d7525e8e 100644 --- a/src/Networking/Socket.h +++ b/src/Networking/Socket.h @@ -21,14 +21,15 @@ class NetworkInterface; class Socket { public: - Socket(NetworkInterface *iface) : interface(iface), localPort(0), remotePort(0), remoteIPAddress(0) { } + Socket(NetworkInterface *iface) : interface(iface), localPort(0), remotePort(0), remoteIPAddress(0), state(SocketState::disabled) { } NetworkInterface *GetInterface() const { return interface; } - virtual void Poll(bool full) = 0; Port GetLocalPort() const { return localPort; } uint32_t GetRemoteIP() const { return remoteIPAddress; } Port GetRemotePort() const { return remotePort; } NetworkProtocol GetProtocol() const { return protocol; } + + virtual void Poll(bool full) = 0; virtual void Close() = 0; virtual void Terminate() = 0; virtual void TerminateAndDisable() = 0; @@ -52,9 +53,9 @@ protected: aborted }; - NetworkInterface *interface; + NetworkInterface * const interface; Port localPort, remotePort; // The local and remote ports - NetworkProtocol protocol; // What protocol this socket is for + NetworkProtocol protocol; // What protocol this socket is for uint32_t remoteIPAddress; // The remote IP address SocketState state; }; diff --git a/src/Networking/W5500Ethernet/W5500Interface.cpp b/src/Networking/W5500Ethernet/W5500Interface.cpp index 27cf6185..7cb191b0 100644 --- a/src/Networking/W5500Ethernet/W5500Interface.cpp +++ b/src/Networking/W5500Ethernet/W5500Interface.cpp @@ -277,7 +277,7 @@ void W5500Interface::Spin(bool full) { // IP address is all zeros, so use DHCP // debugPrintf("Link established, getting IP address\n"); - DHCP_init(DhcpSocketNumber, reprap.GetNetwork().GetHostname()); + DHCP_init(DhcpSocketNumber, platform.Random(), reprap.GetNetwork().GetHostname()); lastTickMillis = millis(); state = NetworkState::obtainingIP; } @@ -344,7 +344,7 @@ void W5500Interface::Spin(bool full) DHCP_time_handler(); } const DhcpRunResult ret = DHCP_run(); - if (ret == DhcpRunResult::DHCP_IP_CHANGED) + if (ret == DhcpRunResult::DHCP_IP_CHANGED || ret == DhcpRunResult::DHCP_IP_ASSIGN) { // debugPrintf("IP address changed\n"); getSIPR(ipAddress); @@ -440,13 +440,6 @@ void W5500Interface::InitSockets() nextSocketToPoll = 0; } -// The following is called by the FTP responder to stop listening on the FTP data port -// For the W5500 listening stop automatically when the port is terminated, so we don't need anything here -void W5500Interface::DataPortClosing() -{ - // nothing needed here -} - void W5500Interface::TerminateSockets() { for (SocketNumber skt = 0; skt < NumW5500TcpSockets; ++skt) diff --git a/src/Networking/W5500Ethernet/W5500Interface.h b/src/Networking/W5500Ethernet/W5500Interface.h index 69fa1433..3f20b7ab 100644 --- a/src/Networking/W5500Ethernet/W5500Interface.h +++ b/src/Networking/W5500Ethernet/W5500Interface.h @@ -40,8 +40,6 @@ public: void Exit() override; void Spin(bool full) override; void Diagnostics(MessageType mtype) override; - void Start() override; - void Stop() override; GCodeResult EnableInterface(int mode, const StringRef& ssid, const StringRef& reply) override; // enable or disable the network GCodeResult EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) override; @@ -60,7 +58,6 @@ public: void OpenDataPort(Port port) override; void TerminateDataPort() override; - void DataPortClosing() override; private: enum class NetworkState @@ -73,6 +70,8 @@ private: active // network running }; + void Start(); + void Stop(); void InitSockets(); void TerminateSockets(); diff --git a/src/Networking/W5500Ethernet/W5500Socket.cpp b/src/Networking/W5500Ethernet/W5500Socket.cpp index 03340d58..8e200352 100644 --- a/src/Networking/W5500Ethernet/W5500Socket.cpp +++ b/src/Networking/W5500Ethernet/W5500Socket.cpp @@ -17,7 +17,7 @@ const unsigned int MaxBuffersPerSocket = 4; W5500Socket::W5500Socket(NetworkInterface *iface) - : Socket(iface), receivedData(nullptr), state(SocketState::disabled) + : Socket(iface), receivedData(nullptr) { } @@ -171,12 +171,13 @@ void W5500Socket::Poll(bool full) state = SocketState::connected; sendOutstanding = false; } - else + else if (millis() - whenConnected >= FindResponderTimeout) { - if (millis() - whenConnected >= FindResponderTimeout) + if (reprap.Debug(moduleNetwork)) { - Terminate(); + debugPrintf("Timed out waiting for resonder for port %u\n", localPort); } + Terminate(); } } @@ -213,14 +214,16 @@ void W5500Socket::ReceiveData() { // debugPrintf("%u available\n", len); NetworkBuffer * const lastBuffer = NetworkBuffer::FindLast(receivedData); - if (lastBuffer != nullptr && (lastBuffer->SpaceLeft() >= len || (lastBuffer->SpaceLeft() != 0 && NetworkBuffer::Count(receivedData) >= MaxBuffersPerSocket))) + // NOTE: reading only part of the received data doesn't work because the wizchip doesn't track the buffer pointer properly. + // We could probably make it work by tracking the buffer pointer ourselves, just as we do when sending data, and using wiz_recv_data_at. + if (lastBuffer != nullptr && lastBuffer->SpaceLeft() >= len) { - const size_t lengthToRead = min<size_t>((size_t)len, lastBuffer->SpaceLeft()); - wiz_recv_data(socketNum, lastBuffer->UnwrittenData(), (uint16_t)lengthToRead); - lastBuffer->dataLength += lengthToRead; + wiz_recv_data(socketNum, lastBuffer->UnwrittenData(), len); + ExecCommand(socketNum, Sn_CR_RECV); + lastBuffer->dataLength += len; if (reprap.Debug(moduleNetwork)) { - debugPrintf("Received %u bytes\n", (unsigned int)lengthToRead); + debugPrintf("Appended %u bytes\n", (unsigned int)len); } } else if (NetworkBuffer::Count(receivedData) < MaxBuffersPerSocket) diff --git a/src/Networking/W5500Ethernet/W5500Socket.h b/src/Networking/W5500Ethernet/W5500Socket.h index d9799e4f..bc00827f 100644 --- a/src/Networking/W5500Ethernet/W5500Socket.h +++ b/src/Networking/W5500Ethernet/W5500Socket.h @@ -18,47 +18,29 @@ class W5500Socket : public Socket public: W5500Socket(NetworkInterface *iface); void Init(SocketNumber s, Port serverPort, NetworkProtocol p); - void TerminateAndDisable(); - void Poll(bool full); - Port GetLocalPort() const { return localPort; } - uint32_t GetRemoteIP() const { return remoteIPAddress; } - Port GetRemotePort() const { return remotePort; } - void Close(); - void Terminate(); - bool ReadChar(char& c); - bool ReadBuffer(const uint8_t *&buffer, size_t &len); - void Taken(size_t len); - bool CanRead() const; - bool CanSend() const; - size_t Send(const uint8_t *data, size_t length); - void Send(); -private: - enum class SocketState : uint8_t - { - disabled, - inactive, - listening, - connected, - clientDisconnecting, - closing, - aborted - }; + void Poll(bool full) override; + void Close() override; + void Terminate() override; + void TerminateAndDisable() override; + bool ReadChar(char& c) override; + bool ReadBuffer(const uint8_t *&buffer, size_t &len) override; + void Taken(size_t len) override; + bool CanRead() const override; + bool CanSend() const override; + size_t Send(const uint8_t *data, size_t length) override; + void Send() override; +private: void ReInit(); void ReceiveData(); void DiscardReceivedData(); - Port localPort, remotePort; // The local and remote ports - NetworkProtocol protocol; // What protocol this socket is for - uint32_t remoteIPAddress; // The remote IP address NetworkBuffer *receivedData; // List of buffers holding received data - //invariant(!receivedData->IsEmpty()) uint32_t whenConnected; bool persistConnection; // Do we expect this connection to stay alive? bool isTerminated; // Will be true if the connection has gone down unexpectedly (TCP RST) SocketNumber socketNum; // The W5500 socket number we are using - SocketState state; bool sendOutstanding; // True if we have written data to the socket but not flushed it bool isSending; // True if we have written data to the W5500 to send and have not yet seen success or timeout uint16_t wizTxBufferPtr; // Current offset into the Wizchip send buffer, if sendOutstanding is true diff --git a/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.cpp b/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.cpp index b077e76e..364133f5 100644 --- a/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.cpp +++ b/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.cpp @@ -161,11 +161,20 @@ void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) const uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); WIZCHIP_READ_BUF(addrsel, wizdata, len); ptr += len; - - setSn_RX_RD(sn,ptr); + setSn_RX_RD(sn, ptr); } } +// Function wiz_recv_data only works if we read the entire received data. +// This function should get round that, but the caller will have to track the received buffer pointer. +void wiz_recv_data_at(uint8_t sn, uint8_t *wizdata, uint16_t len, uint16_t ptr) +{ + if (len != 0) + { + const uint32_t addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); + WIZCHIP_READ_BUF(addrsel, wizdata, len); + } +} void wiz_recv_ignore(uint8_t sn, uint16_t len) { diff --git a/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.h b/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.h index 022419a3..e14c71ab 100644 --- a/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.h +++ b/src/Networking/W5500Ethernet/Wiznet/Ethernet/W5500/w5500.h @@ -2287,6 +2287,9 @@ void wiz_send_data_at(uint8_t sn, const uint8_t *wizdata, uint16_t len, uint16_t */ void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); +// Alternative to wiz_recv_data to work around an apparent bug +void wiz_recv_data_at(uint8_t sn, uint8_t *wizdata, uint16_t len, uint16_t ptr); + /** * @ingroup Basic_IO_function * @brief It discard the received data in RX memory. diff --git a/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.cpp b/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.cpp index bfaa9694..01320fa8 100644 --- a/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.cpp +++ b/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.cpp @@ -90,6 +90,11 @@ uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; if(len == 0) return SOCKERR_DATALEN; \ }while(0); \ +bool IsSending(uint8_t sn) +{ + return (sock_is_sending & (1u << sn)) != 0; +} + void ExecCommand(uint8_t sn, uint8_t cmd) { setSn_CR(sn, cmd); @@ -248,146 +253,11 @@ int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port) return SOCK_OK; } -int8_t disconnect(uint8_t sn) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - ExecCommand(sn, Sn_CR_DISCON); - - sock_is_sending &= ~(1<<sn); - if (sock_io_mode & (1<<sn)) - { - return SOCK_BUSY; - } - while(getSn_SR(sn) != SOCK_CLOSED) - { - if (getSn_IR(sn) & Sn_IR_TIMEOUT) - { - close(sn); - return SOCKERR_TIMEOUT; - } - } - return SOCK_OK; -} - void disconnectNoWait(uint8_t sn) { ExecCommand(sn, Sn_CR_DISCON); } -int32_t send(uint8_t sn, uint8_t * buf, uint16_t len) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKDATA(); - uint8_t tmp = getSn_SR(sn); - if (tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) - { - return SOCKERR_SOCKSTATUS; - } - if ( sock_is_sending & (1<<sn) ) - { - tmp = getSn_IR(sn); - if (tmp & Sn_IR_SENDOK) - { - setSn_IR(sn, Sn_IR_SENDOK); - sock_is_sending &= ~(1<<sn); - } - else if(tmp & Sn_IR_TIMEOUT) - { - close(sn); - return SOCKERR_TIMEOUT; - } - else - { - return SOCK_BUSY; - } - } - uint16_t freesize = getSn_TxMAX(sn); - if (len > freesize) - { - len = freesize; // check size not to exceed MAX size. - } - while(1) - { - freesize = getSn_TX_FSR(sn); - tmp = getSn_SR(sn); - if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) - { - close(sn); - return SOCKERR_SOCKSTATUS; - } - if ( (sock_io_mode & (1<<sn)) && (len > freesize) ) - { - return SOCK_BUSY; - } - if (len <= freesize) - { - break; - } - DEBUG_PRINTF("Socket %u need %u free %u\n", sn, len, freesize); - } - wiz_send_data(sn, buf, len); - - ExecCommand(sn, Sn_CR_SEND); - sock_is_sending |= (1 << sn); - return (int32_t)len; -} - - -int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len) -{ - CHECK_SOCKMODE(Sn_MR_TCP); - CHECK_SOCKDATA(); - - uint16_t recvsize = getSn_RxMAX(sn); - if (recvsize < len) - { - len = recvsize; - } - - while(1) - { - recvsize = getSn_RX_RSR(sn); - const uint8_t tmp = getSn_SR(sn); - if (tmp != SOCK_ESTABLISHED) - { - if (tmp == SOCK_CLOSE_WAIT) - { - if (recvsize != 0) - { - break; - } - else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) - { - close(sn); - return SOCKERR_SOCKSTATUS; - } - } - else - { - close(sn); - return SOCKERR_SOCKSTATUS; - } - } - if ((sock_io_mode & (1<<sn)) && (recvsize == 0)) - { - return SOCK_BUSY; - } - if (recvsize != 0) - { - break; - } - }; - - if (recvsize < len) - { - len = recvsize; - } - wiz_recv_data(sn, buf, len); - ExecCommand(sn, Sn_CR_RECV); - - return (int32_t)len; -} - int32_t sendto(uint8_t sn, const uint8_t * buf, uint16_t len, const uint8_t * addr, uint16_t port) { switch(getSn_MR(sn) & 0x0F) @@ -426,49 +296,41 @@ int32_t sendto(uint8_t sn, const uint8_t * buf, uint16_t len, const uint8_t * ad len = freesize; // check size not to exceed MAX size. } - while(1) + freesize = getSn_TX_FSR(sn); + if (getSn_SR(sn) == SOCK_CLOSED) { - freesize = getSn_TX_FSR(sn); - if (getSn_SR(sn) == SOCK_CLOSED) - { - return SOCKERR_SOCKCLOSED; - } - if ( (sock_io_mode & (1<<sn)) && (len > freesize) ) - { - return SOCK_BUSY; - } - if (len <= freesize) - { - break; - } - DEBUG_PRINTF("Socket %u need %u free %u\n", sn, len, freesize); - }; + return SOCKERR_SOCKCLOSED; + } + if (len > freesize) + { + return SOCK_BUSY; + } wiz_send_data(sn, buf, len); ExecCommand(sn, Sn_CR_SEND); + sock_is_sending |= 1u << sn; + return (int32_t)len; +} - while(1) +int32_t CheckSendComplete(uint8_t sn) +{ + const uint8_t tmp = getSn_IR(sn); + if (tmp & Sn_IR_SENDOK) { - const uint8_t tmp = getSn_IR(sn); - if (tmp & Sn_IR_SENDOK) - { - setSn_IR(sn, Sn_IR_SENDOK); - break; - } - else if(tmp & Sn_IR_TIMEOUT) - { - setSn_IR(sn, Sn_IR_TIMEOUT); - return SOCKERR_TIMEOUT; - } - DEBUG_PRINTF("Socket %u waiting for send to complete, IR=%02x\n", sn, tmp); -#ifdef _SOCKET_DEBUG_ - delay(10); // to avoid too many messages -#endif + setSn_IR(sn, Sn_IR_SENDOK); + sock_is_sending &= ~(1u << sn); + return SOCK_OK; } - return (int32_t)len; + else if(tmp & Sn_IR_TIMEOUT) + { + setSn_IR(sn, Sn_IR_TIMEOUT); + sock_is_sending &= ~(1u << sn); + return SOCKERR_TIMEOUT; + } + DEBUG_PRINTF("Socket %u waiting for send to complete, IR=%02x\n", sn, tmp); + return SOCK_BUSY; } - int32_t recvfrom(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) { const uint8_t mr = getSn_MR(sn); diff --git a/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.h b/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.h index f85c645e..167711de 100644 --- a/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.h +++ b/src/Networking/W5500Ethernet/Wiznet/Ethernet/socketlib.h @@ -209,75 +209,15 @@ int8_t listen(uint8_t sn); */ int8_t connect(uint8_t sn, uint8_t * addr, uint16_t port); -/** - * @ingroup WIZnet_socket_APIs - * @brief Try to disconnect a connection socket. - * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. - * @note It is valid only in TCP server or client mode. \n - * In block io mode, it does not return until disconnection is completed. \n - * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n - - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @return @b Success : @ref SOCK_OK \n - * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCK_BUSY - Socket is busy. - */ -int8_t disconnect(uint8_t sn); - void disconnectNoWait(uint8_t sn); /** * @ingroup WIZnet_socket_APIs - * @brief Send data to the connected peer in TCP socket. - * @details It is used to send outgoing data to the connected socket. - * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n - * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param buf Pointer buffer containing data to be sent. - * @param len The byte length of data in buf. - * @return @b Success : The sent data size \n - * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_TIMEOUT - Timeout occurred \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t send(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs - * @brief Receive data from the connected peer. - * @details It is used to read incoming data from the connected socket.\n - * It waits for data as much as the application wants to receive. - * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n - * In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer. \n - * In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. \n - * - * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. - * @param buf Pointer buffer to read incoming data. - * @param len The max data length of data in buf. - * @return @b Success : The real received data size \n - * @b Fail :\n - * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n - * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n - * @ref SOCKERR_SOCKNUM - Invalid socket number \n - * @ref SOCKERR_DATALEN - zero data length \n - * @ref SOCK_BUSY - Socket is busy. - */ -int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len); - -/** - * @ingroup WIZnet_socket_APIs * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n * Even if the connectionless socket has been previously connected to a specific address, * the address and port number parameters override the destination address for that particular datagram only. - * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>. - * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. + * @note In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. * * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. * @param buf Pointer buffer to send outgoing data. @@ -285,7 +225,7 @@ int32_t recv(uint8_t sn, uint8_t * buf, uint16_t len); * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. * @param port Destination port number. * - * @return @b Success : The sent data size \n + * @return @b Success : The queued sent data size \n * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n @@ -419,67 +359,11 @@ typedef enum */ int8_t ctlsocket(uint8_t sn, ctlsock_type cstype, void* arg); -/** - * @ingroup WIZnet_socket_APIs - * @brief set socket options - * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. - * - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to <I>sotype</I>. \n - * <table> - * <tr> <td> @b sotype </td> <td> @b data type</td><td>@b value</td></tr> - * <tr> <td> @ref SO_TTL </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> - * <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> - * <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr> - * <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr> - * <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> - * <tr> <td> @ref SO_KEEPALIVESEND </td> <td> null </td><td> null </td></tr> - * <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> - * </table> - * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n - */ -int8_t setsockopt(uint8_t sn, sockopt_type sotype, void* arg); +// Check whether we are sending on a socket +bool IsSending(uint8_t sn); -/** - * @ingroup WIZnet_socket_APIs - * @brief get socket options - * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type - * @param sn socket number - * @param sotype socket option type. refer to @ref sockopt_type - * @param arg Data type and value is determined according to <I>sotype</I>. \n - * <table> - * <tr> <td> @b sotype </td> <td>@b data type</td><td>@b value</td></tr> - * <tr> <td> @ref SO_FLAG </td> <td> uint8_t </td><td> @ref SF_ETHER_OWN, etc... </td> </tr> - * <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> - * <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr> - * <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr> - * <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> </td></tr> - * <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> - * <tr> <td> @ref SO_SENDBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> - * <tr> <td> @ref SO_RECVBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> - * <tr> <td> @ref SO_STATUS </td> <td> uint8_t </td><td> @ref SOCK_ESTABLISHED, etc.. </td></tr> - * <tr> <td> @ref SO_REMAINSIZE </td> <td> uint16_t </td><td> 0~ 65535 </td></tr> - * <tr> <td> @ref SO_PACKINFO </td> <td> uint8_t </td><td> @ref PACK_FIRST, etc... </td></tr> - * </table> - * @return - * - @b Success : @ref SOCK_OK \n - * - @b Fail - * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n - * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n - * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n - * @note - * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n - * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, - * This means the zero byte UDP data(UDP Header only) received. - */ -int8_t getsockopt(uint8_t sn, sockopt_type sotype, void* arg); +// Check whether sending on a socket is complete +int32_t CheckSendComplete(uint8_t sn); // pre(IsSending()) // Execute a command void ExecCommand(uint8_t sn, uint8_t cmd); diff --git a/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp b/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp index 661ea0f3..5b325645 100644 --- a/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp +++ b/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.cpp @@ -65,13 +65,18 @@ extern "C" void debugPrintf(const char *fmt, ...); #endif /* DHCP state machine. */ -#define STATE_DHCP_INIT 0 ///< Initialize -#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER -#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK -#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased -#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP -#define STATE_DHCP_RELEASE 5 ///< No use -#define STATE_DHCP_STOP 6 ///< Stop processing DHCP +enum class DhcpState : uint8_t +{ + init = 0, ///< Initialize + discover, ///< send DISCOVER and wait OFFER + request, ///< send REQUEST and wait ACK or NACK + leased, ///< Received ACK and IP leased + rerequest, ///< send REQUEST for maintaining leased IP + release, ///< No use + stop, ///< Stop processing DHCP + checkingIpConflict, ///< Waiting for send to conflicting IP to complete + delaying +}; #define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG #define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG @@ -81,6 +86,7 @@ extern "C" void debugPrintf(const char *fmt, ...); #define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG /* DHCP message type */ +#define DHCP_NOTYPE 0 // must be different from all of the following #define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG #define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG #define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG @@ -207,14 +213,16 @@ uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP -int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state -int8_t dhcp_retry_count = 0; +DhcpState dhcp_state = DhcpState::init; // DHCP state +int8_t dhcp_retry_count; + +uint32_t dhcp_lease_time; +volatile uint32_t dhcp_tick_1s; // unit 1 second +uint32_t dhcp_tick_next; -uint32_t dhcp_lease_time = INFINITE_LEASETIME; -volatile uint32_t dhcp_tick_1s = 0; // unit 1 second -uint32_t dhcp_tick_next = DHCP_WAIT_TIME ; +uint32_t DHCP_XID; // Any number -uint32_t DHCP_XID; // Any number +int32_t dhcpLastSendStatus; static RIP_MSG dhcpMessageBuffer; RIP_MSG* const pDHCPMSG = &dhcpMessageBuffer; // Buffer pointer for DHCP processing @@ -245,7 +253,7 @@ void send_DHCP_REQUEST(void); void send_DHCP_DECLINE(void); /* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ -bool check_DHCP_leasedIP(void); +void check_DHCP_leasedIP(void); /* check the timeout in DHCP process */ DhcpRunResult check_DHCP_timeout(void); @@ -416,7 +424,7 @@ void send_DHCP_DISCOVER(void) DEBUG_PRINTF("> Send DHCP_DISCOVER\n"); - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + (void)sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); DEBUG_PRINTF("Sent\n"); } @@ -427,7 +435,7 @@ void send_DHCP_REQUEST(void) makeDHCPMSG(); uint8_t ip[4]; - if (dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) + if (dhcp_state == DhcpState::leased || dhcp_state == DhcpState::rerequest) { *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); @@ -465,7 +473,7 @@ void send_DHCP_REQUEST(void) pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; - if (ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) + if (dhcp_state != DhcpState::leased && dhcp_state != DhcpState::rerequest) { pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; pDHCPMSG->OPT[k++] = 0x04; @@ -510,7 +518,7 @@ void send_DHCP_REQUEST(void) DEBUG_PRINTF("> Send DHCP_REQUEST\n"); - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + (void)sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); } /* SEND DHCP DHCPDECLINE */ @@ -568,13 +576,13 @@ void send_DHCP_DECLINE(void) DEBUG_PRINTF("\n> Send DHCP_DECLINE\n"); - sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + (void)sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); } /* PARSE REPLY pDHCPMSG */ int8_t parseDHCPMSG(void) { - uint8_t type = 0; + uint8_t type = DHCP_NOTYPE; uint16_t len; if ((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) { @@ -587,9 +595,9 @@ int8_t parseDHCPMSG(void) uint16_t svr_port; len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); - DEBUG_PRINTF("DHCP message : %d.%d.%d.%d(%d) %d received. \n", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3],svr_port, len); + DEBUG_PRINTF("DHCP message : %d.%d.%d.%d(%d) %d received. \n", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3], svr_port, len); - if (svr_port == DHCP_SERVER_PORT) + if (svr_port == DHCP_SERVER_PORT && len > 240) { // compare mac address if ( (pDHCPMSG->chaddr[0] == DHCP_CHADDR[0]) && (pDHCPMSG->chaddr[1] == DHCP_CHADDR[1]) @@ -687,7 +695,7 @@ int8_t parseDHCPMSG(void) DhcpRunResult DHCP_run(void) { - if (dhcp_state == STATE_DHCP_STOP) + if (dhcp_state == DhcpState::stop) { return DhcpRunResult::DHCP_STOPPED; } @@ -698,20 +706,29 @@ DhcpRunResult DHCP_run(void) } DhcpRunResult ret = DhcpRunResult::DHCP_RUNNING; + if (IsSending(DHCP_SOCKET)) + { + dhcpLastSendStatus = CheckSendComplete(DHCP_SOCKET); + if (dhcpLastSendStatus == SOCK_BUSY) + { + return ret; + } + } + const uint8_t type = parseDHCPMSG(); switch (dhcp_state) { - case STATE_DHCP_INIT: + case DhcpState::init: DHCP_allocated_ip[0] = 0; DHCP_allocated_ip[1] = 0; DHCP_allocated_ip[2] = 0; DHCP_allocated_ip[3] = 0; send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; + dhcp_state = DhcpState::discover; break; - case STATE_DHCP_DISCOVER: + case DhcpState::discover: if (type == DHCP_OFFER) { DEBUG_PRINTF("> Receive DHCP_OFFER\n"); @@ -721,7 +738,7 @@ DhcpRunResult DHCP_run(void) DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; send_DHCP_REQUEST(); - dhcp_state = STATE_DHCP_REQUEST; + dhcp_state = DhcpState::request; } else { @@ -729,31 +746,32 @@ DhcpRunResult DHCP_run(void) } break; - case STATE_DHCP_REQUEST : + case DhcpState::request: if (type == DHCP_ACK) { - DEBUG_PRINTF("> Receive DHCP_ACK\n"); - if (check_DHCP_leasedIP()) + DEBUG_PRINTF("> Receive DHCP_ACK, lease time = %u\n", (unsigned int)dhcp_lease_time); + uint8_t currentIp[4]; + getSIPR(currentIp); + if (memcmp(DHCP_allocated_ip, currentIp, 4) == 0) { - // Network info assignment from DHCP - dhcp_ip_assign(); + // We have been given the IP address we are already using. + // Don't check for an address conflict, because I have a suspicion that we end up replying to the ARP request ourselves. + dhcp_ip_assign(); // in case gateway or subnet mask have changed reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_LEASED; + dhcp_state = DhcpState::leased; ret = DhcpRunResult::DHCP_IP_ASSIGN; } else { - // IP address conflict occurred - reset_DHCP_timeout(); - dhcp_ip_conflict(); - dhcp_state = STATE_DHCP_INIT; + check_DHCP_leasedIP(); + dhcp_state = DhcpState::checkingIpConflict; } } else if (type == DHCP_NAK) { DEBUG_PRINTF("> Receive DHCP_NACK\n"); reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_DISCOVER; + dhcp_state = DhcpState::discover; } else { @@ -761,11 +779,40 @@ DhcpRunResult DHCP_run(void) } break; - case STATE_DHCP_LEASED : + case DhcpState::checkingIpConflict: + if (dhcpLastSendStatus == SOCKERR_TIMEOUT) + { + // UDP send Timeout occurred, so allocated IP address is unique, DHCP Success + DEBUG_PRINTF("\n> Check leased IP - OK\n"); + dhcp_ip_assign(); + reset_DHCP_timeout(); + dhcp_state = DhcpState::leased; + ret = DhcpRunResult::DHCP_IP_ASSIGN; + } + else + { + // Received ARP reply, so IP address conflict has occurred, DHCP Failed + send_DHCP_DECLINE(); + dhcp_ip_conflict(); + reset_DHCP_timeout(); + dhcp_state = DhcpState::delaying; + } + break; + + case DhcpState::delaying: + // Had IP address conflict. Delay before trying again. + if (dhcp_tick_1s > 3) + { + reset_DHCP_timeout(); + dhcp_state = DhcpState::init; + } + break; + + case DhcpState::leased : ret = DhcpRunResult::DHCP_IP_LEASED; if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) { - DEBUG_PRINTF("> Maintains the IP address \n"); + DEBUG_PRINTF("> Maintain the IP address \n"); OLD_allocated_ip[0] = DHCP_allocated_ip[0]; OLD_allocated_ip[1] = DHCP_allocated_ip[1]; OLD_allocated_ip[2] = DHCP_allocated_ip[2]; @@ -775,11 +822,11 @@ DhcpRunResult DHCP_run(void) send_DHCP_REQUEST(); reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_REREQUEST; + dhcp_state = DhcpState::rerequest; } break; - case STATE_DHCP_REREQUEST : + case DhcpState::rerequest: ret = DhcpRunResult::DHCP_IP_LEASED; if (type == DHCP_ACK) { @@ -798,13 +845,13 @@ DhcpRunResult DHCP_run(void) DEBUG_PRINTF(">IP is continued.\n"); } reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_LEASED; + dhcp_state = DhcpState::leased; } else if (type == DHCP_NAK) { DEBUG_PRINTF("> Receive DHCP_NACK, Failed to maintain ip\n"); reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_DISCOVER; + dhcp_state = DhcpState::discover; } else { @@ -822,7 +869,7 @@ DhcpRunResult DHCP_run(void) void DHCP_stop(void) { close(DHCP_SOCKET); - dhcp_state = STATE_DHCP_STOP; + dhcp_state = DhcpState::stop; } DhcpRunResult check_DHCP_timeout(void) @@ -835,18 +882,18 @@ DhcpRunResult check_DHCP_timeout(void) { switch ( dhcp_state ) { - case STATE_DHCP_DISCOVER : + case DhcpState::discover : DEBUG_PRINTF("<<timeout>> state : STATE_DHCP_DISCOVER\n"); send_DHCP_DISCOVER(); break; - case STATE_DHCP_REQUEST : + case DhcpState::request : DEBUG_PRINTF("<<timeout>> state : STATE_DHCP_REQUEST\n"); send_DHCP_REQUEST(); break; - case STATE_DHCP_REREQUEST : + case DhcpState::rerequest : DEBUG_PRINTF("<<timeout>> state : STATE_DHCP_REREQUEST\n"); send_DHCP_REQUEST(); @@ -865,14 +912,15 @@ DhcpRunResult check_DHCP_timeout(void) { // exceeded retry count switch(dhcp_state) { - case STATE_DHCP_DISCOVER: - dhcp_state = STATE_DHCP_INIT; + case DhcpState::discover: + dhcp_state = DhcpState::init; ret = DhcpRunResult::DHCP_FAILED; break; - case STATE_DHCP_REQUEST: - case STATE_DHCP_REREQUEST: + case DhcpState::request: + case DhcpState::rerequest: + case DhcpState::checkingIpConflict: send_DHCP_DISCOVER(); - dhcp_state = STATE_DHCP_DISCOVER; + dhcp_state = DhcpState::discover; break; default : break; @@ -882,43 +930,22 @@ DhcpRunResult check_DHCP_timeout(void) return ret; } -bool check_DHCP_leasedIP(void) +void check_DHCP_leasedIP(void) { - uint8_t tmp; - int32_t ret; - //WIZchip RCR value changed for ARP Timeout count control - tmp = getRCR(); + const uint8_t tmp = getRCR(); setRCR(0x03); // IP conflict detection : ARP request - ARP reply // Broadcasting ARP Request for check the IP conflict using UDP sendto() function // TODO the following takes 620ms to time out - hanging for this long isn't very nice - ret = sendto(DHCP_SOCKET, (const uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); + sendto(DHCP_SOCKET, (const uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); // RCR value restore setRCR(tmp); - - if (ret == SOCKERR_TIMEOUT) - { - // UDP send Timeout occurred : allocated IP address is unique, DHCP Success - DEBUG_PRINTF("\n> Check leased IP - OK\n"); - return true; - } - else - { - // Received ARP reply or etc : IP address conflict occur, DHCP Failed - send_DHCP_DECLINE(); - - ret = dhcp_tick_1s; - //TODO can't tolerate a 1 to 2 second wait here - while((dhcp_tick_1s - ret) < 2) { } // wait for 1s over; wait to complete to send DECLINE message; - - return false; - } } -void DHCP_init(uint8_t s, const char *hname) +void DHCP_init(uint8_t s, uint32_t seed, const char *hname) { strncpy(HOST_NAME, hname, sizeof(HOST_NAME)); HOST_NAME[sizeof(HOST_NAME) - 1] = 0; @@ -939,8 +966,11 @@ void DHCP_init(uint8_t s, const char *hname) setSHAR(DHCP_CHADDR); } - DHCP_SOCKET = s; // SOCK_DHCP - DHCP_XID = 0x12345678; + DHCP_SOCKET = s; + reset_DHCP_timeout(); + dhcp_lease_time = INFINITE_LEASETIME; + DHCP_XID = seed; + dhcpLastSendStatus = SOCK_OK; // WIZchip Netinfo Clear setSIPR(zeroip); @@ -948,7 +978,7 @@ void DHCP_init(uint8_t s, const char *hname) setGAR(zeroip); reset_DHCP_timeout(); - dhcp_state = STATE_DHCP_INIT; + dhcp_state = DhcpState::init; } /* Rset the DHCP timeout count and retry count. */ diff --git a/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.h b/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.h index 4f238b6e..6148b5eb 100644 --- a/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.h +++ b/src/Networking/W5500Ethernet/Wiznet/Internet/DHCP/dhcp.h @@ -77,7 +77,7 @@ enum class DhcpRunResult : uint8_t * @param s - socket number * @param hname - null-terminated host name string */ -void DHCP_init(uint8_t s, const char *hname); +void DHCP_init(uint8_t s, uint32_t seed, const char *hname); /* * @brief DHCP 1s Tick Timer handler |