Skip to content

Commit 1b6f90c

Browse files
committed
make socket/port states thread-safe
1 parent 561b982 commit 1b6f90c

File tree

4 files changed

+47
-35
lines changed

4 files changed

+47
-35
lines changed

src/Ethernet.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ EthernetClass::EthernetClass(arduino::SPIClass& spibus, uint8_t sspin)
2929
_dhcp{nullptr},
3030
_spibus(spibus),
3131
_sspin(sspin),
32-
_w5100(_spibus, _sspin) {}
32+
_w5100(_spibus, _sspin),
33+
_state{} {}
3334

3435
EthernetClass::~EthernetClass() {
3536
if (_dhcp) {

src/Ethernet.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ enum EthernetHardwareStatus {
6868
EthernetW5500
6969
};
7070

71+
typedef struct {
72+
uint16_t RX_RSR; // Number of bytes received
73+
uint16_t RX_RD; // Address to read
74+
uint16_t TX_FSR; // Free space ready for transmit
75+
uint8_t RX_inc; // how much have we advanced RX_RD
76+
} socketstate_t;
77+
7178
class EthernetUDP;
7279
class EthernetClient;
7380
class EthernetServer;
@@ -80,6 +87,7 @@ class EthernetClass {
8087
arduino::SPIClass& _spibus;
8188
uint8_t _sspin;
8289
W5100 _w5100;
90+
socketstate_t _state[MAX_SOCK_NUM];
8391
public:
8492
EthernetClass(arduino::SPIClass& spibus, uint8_t sspin);
8593

@@ -280,7 +288,7 @@ class EthernetServer : public Server {
280288
uint16_t _port;
281289
public:
282290
EthernetServer(Ethernet& ethernet, uint16_t port)
283-
: _ethernet(ethernet), _port(port) { }
291+
: _ethernet(ethernet), _port(port), server_port{} { }
284292
EthernetClient available();
285293
EthernetClient accept();
286294
virtual void begin();
@@ -290,8 +298,8 @@ class EthernetServer : public Server {
290298
using Print::write;
291299
//void statusreport();
292300

293-
// TODO: make private when socket allocation moves to EthernetClass
294-
static uint16_t server_port[MAX_SOCK_NUM];
301+
private:
302+
uint16_t server_port[MAX_SOCK_NUM];
295303
};
296304

297305

src/EthernetServer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@
2222
#include "Ethernet.h"
2323
#include "utility/w5100.h"
2424

25-
uint16_t EthernetServer::server_port[MAX_SOCK_NUM];
25+
//uint16_t EthernetServer::server_port[MAX_SOCK_NUM];
2626

2727

2828
void EthernetServer::begin()
2929
{
3030
uint8_t sockindex = _ethernet.socketBegin(SnMR::TCP, _port);
3131
if (sockindex < MAX_SOCK_NUM) {
32+
server_port[sockindex] = 0;
3233
if (_ethernet.socketListen(sockindex)) {
3334
server_port[sockindex] = _port;
3435
} else {

src/socket.cpp

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern void yield(void);
3131
// TODO: randomize this when not using DHCP, but how?
3232
static uint16_t local_port = 49152; // 49152 to 65535
3333

34+
#if 0
3435
typedef struct {
3536
uint16_t RX_RSR; // Number of bytes received
3637
uint16_t RX_RD; // Address to read
@@ -39,6 +40,7 @@ typedef struct {
3940
} socketstate_t;
4041

4142
static socketstate_t state[MAX_SOCK_NUM];
43+
#endif
4244

4345

4446

@@ -96,7 +98,7 @@ uint8_t EthernetClass::socketBegin(uint8_t protocol, uint16_t port)
9698
_w5100.execCmdSn(s, Sock_CLOSE);
9799
makesocket:
98100
//Serial.printf("W5000socket %d\n", s);
99-
EthernetServer::server_port[s] = 0;
101+
//_server_port[s] = 0;
100102
delayMicroseconds(250); // TODO: is this needed??
101103
_w5100.writeSnMR(s, protocol);
102104
_w5100.writeSnIR(s, 0xFF);
@@ -108,11 +110,11 @@ uint8_t EthernetClass::socketBegin(uint8_t protocol, uint16_t port)
108110
_w5100.writeSnPORT(s, local_port);
109111
}
110112
_w5100.execCmdSn(s, Sock_OPEN);
111-
state[s].RX_RSR = 0;
112-
state[s].RX_RD = _w5100.readSnRX_RD(s); // always zero?
113-
state[s].RX_inc = 0;
114-
state[s].TX_FSR = 0;
115-
//Serial.printf("W5000socket prot=%d, RX_RD=%d\n", _w5100.readSnMR(s), state[s].RX_RD);
113+
_state[s].RX_RSR = 0;
114+
_state[s].RX_RD = _w5100.readSnRX_RD(s); // always zero?
115+
_state[s].RX_inc = 0;
116+
_state[s].TX_FSR = 0;
117+
//Serial.printf("W5000socket prot=%d, RX_RD=%d\n", _w5100.readSnMR(s), _state[s].RX_RD);
116118
_spibus.endTransaction();
117119
return s;
118120
}
@@ -160,7 +162,7 @@ uint8_t EthernetClass::socketBeginMulticast(uint8_t protocol, IPAddress ip, uint
160162
_w5100.execCmdSn(s, Sock_CLOSE);
161163
makesocket:
162164
//Serial.printf("W5000socket %d\n", s);
163-
EthernetServer::server_port[s] = 0;
165+
//_server_port[s] = 0;
164166
delayMicroseconds(250); // TODO: is this needed??
165167
_w5100.writeSnMR(s, protocol);
166168
_w5100.writeSnIR(s, 0xFF);
@@ -180,11 +182,11 @@ uint8_t EthernetClass::socketBeginMulticast(uint8_t protocol, IPAddress ip, uint
180182
_w5100.writeSnDPORT(s, port);
181183
_w5100.writeSnDHAR(s, mac);
182184
_w5100.execCmdSn(s, Sock_OPEN);
183-
state[s].RX_RSR = 0;
184-
state[s].RX_RD = _w5100.readSnRX_RD(s); // always zero?
185-
state[s].RX_inc = 0;
186-
state[s].TX_FSR = 0;
187-
//Serial.printf("W5000socket prot=%d, RX_RD=%d\n", _w5100.readSnMR(s), state[s].RX_RD);
185+
_state[s].RX_RSR = 0;
186+
_state[s].RX_RD = _w5100.readSnRX_RD(s); // always zero?
187+
_state[s].RX_inc = 0;
188+
_state[s].TX_FSR = 0;
189+
//Serial.printf("W5000socket prot=%d, RX_RD=%d\n", _w5100.readSnMR(s), _state[s].RX_RD);
188190
_spibus.endTransaction();
189191
return s;
190192
}
@@ -298,42 +300,42 @@ void EthernetClass::read_data(uint8_t s, uint16_t src, uint8_t *dst, uint16_t le
298300
int EthernetClass::socketRecv(uint8_t s, uint8_t *buf, int16_t len)
299301
{
300302
// Check how much data is available
301-
int ret = state[s].RX_RSR;
303+
int ret = _state[s].RX_RSR;
302304
_spibus.beginTransaction(SPI_ETHERNET_SETTINGS);
303305
if (ret < len) {
304306
uint16_t rsr = getSnRX_RSR(s);
305-
ret = rsr - state[s].RX_inc;
306-
state[s].RX_RSR = ret;
307-
//Serial.printf("Sock_RECV, RX_RSR=%d, RX_inc=%d\n", ret, state[s].RX_inc);
307+
ret = rsr - _state[s].RX_inc;
308+
_state[s].RX_RSR = ret;
309+
//Serial.printf("Sock_RECV, RX_RSR=%d, RX_inc=%d\n", ret, _state[s].RX_inc);
308310
}
309311
if (ret == 0) {
310312
// No data available.
311313
uint8_t status = _w5100.readSnSR(s);
312314
if ( status == SnSR::LISTEN || status == SnSR::CLOSED ||
313315
status == SnSR::CLOSE_WAIT ) {
314316
// The remote end has closed its side of the connection,
315-
// so this is the eof state
317+
// so this is the eof _state
316318
ret = 0;
317319
} else {
318320
// The connection is still up, but there's no data waiting to be read
319321
ret = -1;
320322
}
321323
} else {
322324
if (ret > len) ret = len; // more data available than buffer length
323-
uint16_t ptr = state[s].RX_RD;
325+
uint16_t ptr = _state[s].RX_RD;
324326
if (buf) read_data(s, ptr, buf, ret);
325327
ptr += ret;
326-
state[s].RX_RD = ptr;
327-
state[s].RX_RSR -= ret;
328-
uint16_t inc = state[s].RX_inc + ret;
329-
if (inc >= 250 || state[s].RX_RSR == 0) {
330-
state[s].RX_inc = 0;
328+
_state[s].RX_RD = ptr;
329+
_state[s].RX_RSR -= ret;
330+
uint16_t inc = _state[s].RX_inc + ret;
331+
if (inc >= 250 || _state[s].RX_RSR == 0) {
332+
_state[s].RX_inc = 0;
331333
_w5100.writeSnRX_RD(s, ptr);
332334
_w5100.execCmdSn(s, Sock_RECV);
333335
//Serial.printf("Sock_RECV cmd, RX_RD=%d, RX_RSR=%d\n",
334-
// state[s].RX_RD, state[s].RX_RSR);
336+
// _state[s].RX_RD, _state[s].RX_RSR);
335337
} else {
336-
state[s].RX_inc = inc;
338+
_state[s].RX_inc = inc;
337339
}
338340
}
339341
_spibus.endTransaction();
@@ -343,13 +345,13 @@ int EthernetClass::socketRecv(uint8_t s, uint8_t *buf, int16_t len)
343345

344346
uint16_t EthernetClass::socketRecvAvailable(uint8_t s)
345347
{
346-
uint16_t ret = state[s].RX_RSR;
348+
uint16_t ret = _state[s].RX_RSR;
347349
if (ret == 0) {
348350
_spibus.beginTransaction(SPI_ETHERNET_SETTINGS);
349351
uint16_t rsr = getSnRX_RSR(s);
350352
_spibus.endTransaction();
351-
ret = rsr - state[s].RX_inc;
352-
state[s].RX_RSR = ret;
353+
ret = rsr - _state[s].RX_inc;
354+
_state[s].RX_RSR = ret;
353355
//Serial.printf("sockRecvAvailable s=%d, RX_RSR=%d\n", s, ret);
354356
}
355357
return ret;
@@ -361,7 +363,7 @@ uint8_t EthernetClass::socketPeek(uint8_t s)
361363
{
362364
uint8_t b;
363365
_spibus.beginTransaction(SPI_ETHERNET_SETTINGS);
364-
uint16_t ptr = state[s].RX_RD;
366+
uint16_t ptr = _state[s].RX_RD;
365367
_w5100.read((ptr & _w5100.SMASK) + _w5100.RBASE(s), &b, 1);
366368
_spibus.endTransaction();
367369
return b;
@@ -381,7 +383,7 @@ uint16_t EthernetClass::getSnTX_FSR(uint8_t s)
381383
while (1) {
382384
val = _w5100.readSnTX_FSR(s);
383385
if (val == prev) {
384-
state[s].TX_FSR = val;
386+
_state[s].TX_FSR = val;
385387
return val;
386388
}
387389
prev = val;

0 commit comments

Comments
 (0)