Skip to content

Commit

Permalink
Support outgoing connections
Browse files Browse the repository at this point in the history
  • Loading branch information
rechrtb committed Dec 15, 2022
1 parent 695f2bf commit 7b82cc6
Show file tree
Hide file tree
Showing 13 changed files with 340 additions and 44 deletions.
8 changes: 7 additions & 1 deletion src/GCodes/GCodes2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3787,7 +3787,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeEx
{
const int port = (gb.Seen('R')) ? gb.GetIValue() : -1;
const int secure = (gb.Seen('T')) ? gb.GetIValue() : -1;
result = reprap.GetNetwork().EnableProtocol(interface, protocol, port, secure, reply);
IPAddress ip;
if (gb.Seen('H'))
{
gb.GetIPAddress(ip);
}
result = reprap.GetNetwork().EnableProtocol(interface, protocol, port,
ip.GetV4LittleEndian(), secure, reply);
}
else
{
Expand Down
63 changes: 53 additions & 10 deletions src/Networking/ESP8266WiFi/WiFiInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ WiFiInterface::WiFiInterface(Platform& p) noexcept

for (size_t i = 0; i < NumProtocols; ++i)
{
ipAddresses[i] = AnyIp;
portNumbers[i] = DefaultPortNumbers[i];
protocolEnabled[i] = (i == HttpProtocol);
}
Expand Down Expand Up @@ -359,7 +360,7 @@ void WiFiInterface::Init() noexcept
currentSocket = 0;
}

GCodeResult WiFiInterface::EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) noexcept
GCodeResult WiFiInterface::EnableProtocol(NetworkProtocol protocol, int port, uint32_t ip, int secure, const StringRef& reply) noexcept
{
if (secure != 0 && secure != -1)
{
Expand All @@ -370,19 +371,22 @@ GCodeResult WiFiInterface::EnableProtocol(NetworkProtocol protocol, int port, in
const TcpPort portToUse = (port < 0) ? DefaultPortNumbers[protocol] : port;
MutexLocker lock(interfaceMutex);

if (portToUse != portNumbers[protocol] && GetState() == NetworkState::active)
if ((portToUse != portNumbers[protocol] || ip != ipAddresses[protocol]) && GetState() == NetworkState::active)
{
// We need to shut down and restart the protocol if it is active because the port number has changed
// We need to shut down and restart the protocol if it is active because the port number has changed.
// Note that clients will probably be unable to close their connections gracefully.
ShutdownProtocol(protocol);
protocolEnabled[protocol] = false;
}
ipAddresses[protocol] = ip;
portNumbers[protocol] = portToUse;
if (!protocolEnabled[protocol])
{
protocolEnabled[protocol] = true;
if (GetState() == NetworkState::active)
{
StartProtocol(protocol);
// Only start listeners here, connection requests for clients are made in the main loop.
ListenProtocol(protocol);
// mDNS announcement is done by the WiFi Server firmware
}
}
Expand All @@ -394,13 +398,13 @@ GCodeResult WiFiInterface::EnableProtocol(NetworkProtocol protocol, int port, in
return GCodeResult::error;
}

GCodeResult WiFiInterface::DisableProtocol(NetworkProtocol protocol, const StringRef& reply) noexcept
GCodeResult WiFiInterface::DisableProtocol(NetworkProtocol protocol, const StringRef& reply, bool shutdown) noexcept
{
if (protocol < NumProtocols)
{
MutexLocker lock(interfaceMutex);

if (GetState() == NetworkState::active)
if (shutdown && GetState() == NetworkState::active)
{
ShutdownProtocol(protocol);
}
Expand All @@ -413,7 +417,7 @@ GCodeResult WiFiInterface::DisableProtocol(NetworkProtocol protocol, const Strin
return GCodeResult::error;
}

void WiFiInterface::StartProtocol(NetworkProtocol protocol) noexcept
void WiFiInterface::ListenProtocol(NetworkProtocol protocol) noexcept
{
MutexLocker lock(interfaceMutex);

Expand All @@ -436,6 +440,18 @@ void WiFiInterface::StartProtocol(NetworkProtocol protocol) noexcept
}
}

void WiFiInterface::ConnectProtocol(NetworkProtocol protocol) noexcept
{
MutexLocker lock(interfaceMutex);

switch(protocol)
{

default:
break;
}
}

void WiFiInterface::ShutdownProtocol(NetworkProtocol protocol) noexcept
{
MutexLocker lock(interfaceMutex);
Expand Down Expand Up @@ -808,6 +824,22 @@ void WiFiInterface::Spin() noexcept
}
else if (currentMode == WiFiState::connected || currentMode == WiFiState::runningAsAccessPoint)
{
// Maintain client connections
for (uint8_t p = 0; p < NumProtocols; p++)
{
if (protocolEnabled[p])
{
if (reprap.GetNetwork().StartClient(this, p))
{
ConnectProtocol(p);
}
}
else
{
reprap.GetNetwork().StopClient(this, p);
}
}

// Find the next socket to poll
const size_t startingSocket = currentSocket;
do
Expand All @@ -831,6 +863,7 @@ void WiFiInterface::Spin() noexcept
currentSocket = 0;
}


// Check if the data port needs to be closed
if (closeDataPort)
{
Expand Down Expand Up @@ -1440,7 +1473,7 @@ void WiFiInterface::InitSockets() noexcept
{
if (protocolEnabled[i])
{
StartProtocol(i);
ListenProtocol(i);
}
}
currentSocket = 0;
Expand All @@ -1454,11 +1487,11 @@ void WiFiInterface::TerminateSockets() noexcept
}
}

void WiFiInterface::TerminateSockets(TcpPort port) noexcept
void WiFiInterface::TerminateSockets(TcpPort port, bool local) noexcept
{
for (WiFiSocket *socket : sockets)
{
if (socket->GetLocalPort() == port)
if ((local ? socket->GetLocalPort() : socket->GetRemotePort()) == port)
{
socket->Terminate();
}
Expand Down Expand Up @@ -2026,6 +2059,16 @@ void WiFiInterface::SendListenCommand(TcpPort port, NetworkProtocol protocol, un
SendCommand(NetworkCommand::networkListen, 0, 0, 0, &lcb, sizeof(lcb), nullptr, 0);
}

void WiFiInterface::SendConnectCommand(TcpPort remotePort, NetworkProtocol protocol, uint32_t remoteIp) noexcept
{
ListenOrConnectData lcb;
memset(&lcb, 0, sizeof(lcb));
lcb.port = remotePort;
lcb.protocol = protocol;
lcb.remoteIp = remoteIp;
SendCommand(NetworkCommand::connCreate, 0, 0, 0, &lcb, sizeof(lcb), nullptr, 0);
}

// Stop listening on a port
void WiFiInterface::StopListening(TcpPort port) noexcept
{
Expand Down
15 changes: 10 additions & 5 deletions src/Networking/ESP8266WiFi/WiFiInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class WiFiInterface : public NetworkInterface
void Stop() noexcept;

GCodeResult EnableInterface(int mode, const StringRef& ssid, const StringRef& reply) noexcept override; // enable or disable the network
GCodeResult EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) noexcept override;
GCodeResult DisableProtocol(NetworkProtocol protocol, const StringRef& reply) noexcept override;
GCodeResult EnableProtocol(NetworkProtocol protocol, int port, uint32_t ip, int secure, const StringRef& reply) noexcept override;
GCodeResult DisableProtocol(NetworkProtocol protocol, const StringRef& reply, bool shutdown = true) noexcept override;
GCodeResult ReportProtocols(const StringRef& reply) const noexcept override;

GCodeResult GetNetworkState(const StringRef& reply) noexcept override;
Expand Down Expand Up @@ -100,12 +100,15 @@ class WiFiInterface : public NetworkInterface
private:
void InitSockets() noexcept;
void TerminateSockets() noexcept;
void TerminateSockets(TcpPort port) noexcept;
void TerminateSockets(TcpPort port, bool local = true) noexcept;
void StopListening(TcpPort port) noexcept;

void StartProtocol(NetworkProtocol protocol) noexcept
// Protocol socket operations - listen for incoming connections,
// create outgoing connection, kill existing listeners & connections.
void ListenProtocol(NetworkProtocol protocol) noexcept
pre(protocol < NumProtocols);
void ConnectProtocol(NetworkProtocol protocol) noexcept
pre(protocol < NumProtocols);

void ShutdownProtocol(NetworkProtocol protocol) noexcept
pre(protocol < NumProtocols);

Expand All @@ -124,6 +127,7 @@ class WiFiInterface : public NetworkInterface
}

void SendListenCommand(TcpPort port, NetworkProtocol protocol, unsigned int maxConnections) noexcept;
void SendConnectCommand(TcpPort port, NetworkProtocol protocol, uint32_t ip) noexcept;
void GetNewStatus() noexcept;
void spi_slave_dma_setup(uint32_t dataOutSize, uint32_t dataInSize) noexcept;

Expand All @@ -144,6 +148,7 @@ class WiFiInterface : public NetworkInterface
WiFiSocket *sockets[NumWiFiTcpSockets];
size_t currentSocket;

uint32_t ipAddresses[NumProtocols];
TcpPort portNumbers[NumProtocols]; // port number used for each protocol
TcpPort ftpDataPort;
bool closeDataPort;
Expand Down
50 changes: 39 additions & 11 deletions src/Networking/ESP8266WiFi/WiFiSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void WiFiSocket::Init(SocketNumber n) noexcept
// Close a connection when the last packet has been sent
void WiFiSocket::Close() noexcept
{
if (state == SocketState::connected || state == SocketState::clientDisconnecting)
if (state == SocketState::connected || state == SocketState::connecting || state == SocketState::peerDisconnecting)
{
const int32_t reply = GetInterface()->SendCommand(NetworkCommand::connClose, socketNum, 0, 0, nullptr, 0, nullptr, 0);
if (reply == ResponseEmpty)
Expand Down Expand Up @@ -65,7 +65,7 @@ void WiFiSocket::Terminate() noexcept
bool WiFiSocket::CanRead() const noexcept
{
return (state == SocketState::connected)
|| (state == SocketState::clientDisconnecting && (hasMoreDataPending || (receivedData != nullptr && receivedData->TotalRemaining() != 0)));
|| (state == SocketState::peerDisconnecting && (hasMoreDataPending || (receivedData != nullptr && receivedData->TotalRemaining() != 0)));
}

// Return true if we can send data to this socket
Expand Down Expand Up @@ -139,12 +139,32 @@ void WiFiSocket::Poll() noexcept

switch (resp.Value().state)
{
case ConnState::connecting:
{
// This state might get skipped, if the socket connected before it can be polled
// in this state. This shouldn't matter, as there is no important logic in this
// state, other than to check if we're here a bit too long.
if (state == SocketState::connecting)
{
// Check for timeout
if (millis() - whenInState >= ConnectTimeout)
{
Close();
}
}
else
{
whenInState = millis();
state = SocketState::connecting;
}
}
break;
case ConnState::otherEndClosed:
// Check for further incoming packets before this socket is finally closed.
// This must be done to ensure that FTP uploads are not cut off.
ReceiveData(resp.Value().bytesAvailable);

if (state == SocketState::clientDisconnecting)
if (state == SocketState::peerDisconnecting)
{
if (!CanRead())
{
Expand All @@ -155,15 +175,15 @@ void WiFiSocket::Poll() noexcept
}
else if (state != SocketState::inactive)
{
state = SocketState::clientDisconnecting;
state = SocketState::peerDisconnecting;
if (reprap.Debug(moduleNetwork))
{
debugPrintf("Client disconnected on socket %u\n", socketNum);
debugPrintf("Peer disconnected on socket %u\n", socketNum);
}
break;
}
// We can get here if a client has sent very little data and then instantly closed
// the connection, e.g. when an FTP client transferred very small files over the
// We can get here if a peer has sent very little data and then instantly closed
// the connection, e.g. when an FTP peer transferred very small files over the
// data port. In such cases we must notify the responder about this transmission!
// no break

Expand All @@ -181,20 +201,28 @@ void WiFiSocket::Poll() noexcept
if (state != SocketState::waitingForResponder)
{
WiFiInterface *iface = static_cast<WiFiInterface *>(interface);
protocol = iface->GetProtocolByLocalPort(localPort);
if (isdigit(iface->wiFiServerVersion[0]) && iface->wiFiServerVersion[0] >= '2')
{
// On version 2 onwards, this is a valid field ConnStatusResponse.
protocol = resp.Value().protocol;
}
else
{
protocol = iface->GetProtocolByLocalPort(localPort);
}

whenConnected = millis();
whenInState = millis();
state = SocketState::waitingForResponder;
}
if (reprap.GetNetwork().FindResponder(this, protocol))
{
state = (resp.Value().state == ConnState::connected) ? SocketState::connected : SocketState::clientDisconnecting;
state = (resp.Value().state == ConnState::connected) ? SocketState::connected : SocketState::peerDisconnecting;
if (reprap.Debug(moduleNetwork))
{
debugPrintf("Found responder\n");
}
}
else if (millis() - whenConnected >= FindResponderTimeout)
else if (millis() - whenInState >= FindResponderTimeout)
{
Terminate();
if (reprap.Debug(moduleNetwork))
Expand Down
5 changes: 3 additions & 2 deletions src/Networking/ESP8266WiFi/WiFiSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ class WiFiSocket : public Socket
enum class SocketState : uint8_t
{
inactive,
connecting,
waitingForResponder,
connected,
clientDisconnecting,
peerDisconnecting,
closing,
broken
};
Expand All @@ -56,7 +57,7 @@ class WiFiSocket : public Socket

NetworkBuffer *receivedData; // List of buffers holding received data
bool hasMoreDataPending; // If there is more data left to read when the buffered data has been processed
uint32_t whenConnected;
uint32_t whenInState; // General purpose timekeeping value for duration spent in various socket states
uint16_t txBufferSpace; // How much free transmit buffer space the WiFi mofule reported
SocketNumber socketNum; // The WiFi socket number we are using
SocketState state;
Expand Down
6 changes: 3 additions & 3 deletions src/Networking/LwipEthernet/LwipEthernetInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void LwipEthernetInterface::Init() noexcept
macAddress = platform.GetDefaultMacAddress();
}

GCodeResult LwipEthernetInterface::EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) noexcept
GCodeResult LwipEthernetInterface::EnableProtocol(NetworkProtocol protocol, int port, uint32_t ip, int secure, const StringRef& reply) noexcept
{
if (secure != 0 && secure != -1)
{
Expand Down Expand Up @@ -192,11 +192,11 @@ GCodeResult LwipEthernetInterface::EnableProtocol(NetworkProtocol protocol, int
return GCodeResult::error;
}

GCodeResult LwipEthernetInterface::DisableProtocol(NetworkProtocol protocol, const StringRef& reply) noexcept
GCodeResult LwipEthernetInterface::DisableProtocol(NetworkProtocol protocol, const StringRef& reply, bool shutdown) noexcept
{
if (protocol < NumProtocols)
{
if (GetState() == NetworkState::active)
if (shutdown && GetState() == NetworkState::active)
{
ShutdownProtocol(protocol);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Networking/LwipEthernet/LwipEthernetInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ class LwipEthernetInterface : public NetworkInterface
void Diagnostics(MessageType mtype) noexcept override;

GCodeResult EnableInterface(int mode, const StringRef& ssid, const StringRef& reply) noexcept override; // enable or disable the network
GCodeResult EnableProtocol(NetworkProtocol protocol, int port, int secure, const StringRef& reply) noexcept override;
GCodeResult DisableProtocol(NetworkProtocol protocol, const StringRef& reply) noexcept override;
GCodeResult EnableProtocol(NetworkProtocol protocol, int port, uint32_t ip, int secure, const StringRef& reply) noexcept override;
GCodeResult DisableProtocol(NetworkProtocol protocol, const StringRef& reply, bool shutdown = true) noexcept override;
GCodeResult ReportProtocols(const StringRef& reply) const noexcept override;

GCodeResult GetNetworkState(const StringRef& reply) noexcept override;
Expand Down
Loading

0 comments on commit 7b82cc6

Please sign in to comment.