Skip to content

Commit c0aa5d4

Browse files
committed
Implement socket_bind and socket_accept
1 parent 44fb447 commit c0aa5d4

File tree

4 files changed

+173
-30
lines changed

4 files changed

+173
-30
lines changed

ESP8266/ESP8266.cpp

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
#include "ESP8266.h"
1818

19-
ESP8266::ESP8266(PinName tx, PinName rx, bool debug)
20-
: _serial(tx, rx, 1024), _parser(_serial)
19+
ESP8266::ESP8266(PinName tx, PinName rx, Callback<void(SignalingAction, int)> signalingCallback, bool debug)
20+
: _serial(tx, rx, 1024), _parser(_serial), _signalingCallback(signalingCallback)
2121
, _packets(0), _packets_end(&_packets)
2222
{
2323
_serial.baud(115200);
@@ -30,11 +30,11 @@ int ESP8266::get_firmware_version()
3030
int version;
3131
if(_parser.recv("SDK version:%d", &version) && _parser.recv("OK")) {
3232
return version;
33-
} else {
33+
} else {
3434
// Older firmware versions do not prefix the version with "SDK version: "
3535
return -1;
3636
}
37-
37+
3838
}
3939

4040
bool ESP8266::startup(int mode)
@@ -51,6 +51,18 @@ bool ESP8266::startup(int mode)
5151

5252
_parser.oob("+IPD", this, &ESP8266::_packet_handler);
5353

54+
_parser.oob("0,CONNECT", this, &ESP8266::_incoming_socket_opened0);
55+
_parser.oob("1,CONNECT", this, &ESP8266::_incoming_socket_opened1);
56+
_parser.oob("2,CONNECT", this, &ESP8266::_incoming_socket_opened2);
57+
_parser.oob("3,CONNECT", this, &ESP8266::_incoming_socket_opened3);
58+
_parser.oob("4,CONNECT", this, &ESP8266::_incoming_socket_opened4);
59+
60+
_parser.oob("0,CLOSED", this, &ESP8266::_incoming_socket_closed0);
61+
_parser.oob("1,CLOSED", this, &ESP8266::_incoming_socket_closed1);
62+
_parser.oob("2,CLOSED", this, &ESP8266::_incoming_socket_closed2);
63+
_parser.oob("3,CLOSED", this, &ESP8266::_incoming_socket_closed3);
64+
_parser.oob("4,CLOSED", this, &ESP8266::_incoming_socket_closed4);
65+
5466
return success;
5567
}
5668

@@ -320,3 +332,23 @@ bool ESP8266::recv_ap(nsapi_wifi_ap_t *ap)
320332

321333
return ret;
322334
}
335+
336+
bool ESP8266::bind(const SocketAddress& address)
337+
{
338+
return _parser.send("AT+CIPSERVER=1,%d", address.get_port())
339+
&& _parser.recv("OK");
340+
}
341+
342+
void ESP8266::_incoming_socket_opened(int8_t socket_id)
343+
{
344+
printf("Incoming socket opened %d\n", socket_id);
345+
346+
_signalingCallback(ESP8266_SOCKET_CONNECT, socket_id);
347+
}
348+
349+
void ESP8266::_incoming_socket_closed(int8_t socket_id)
350+
{
351+
printf("Incoming socket closed %d\n", socket_id);
352+
353+
_signalingCallback(ESP8266_SOCKET_CLOSE, socket_id);
354+
}

ESP8266/ESP8266.h

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,26 @@
1919

2020
#include "ATParser.h"
2121

22+
enum SignalingAction {
23+
ESP8266_SOCKET_CONNECT,
24+
ESP8266_SOCKET_CLOSE
25+
};
26+
2227
/** ESP8266Interface class.
2328
This is an interface to a ESP8266 radio.
2429
*/
2530
class ESP8266
2631
{
2732
public:
28-
ESP8266(PinName tx, PinName rx, bool debug=false);
33+
ESP8266(PinName tx, PinName rx, Callback<void(SignalingAction, int)> signalingCallback, bool debug=false);
2934

3035
/**
3136
* Check firmware version of ESP8266
3237
*
3338
* @return integer firmware version or -1 if firmware query command gives outdated response
3439
*/
3540
int get_firmware_version(void);
36-
41+
3742
/**
3843
* Startup the ESP8266
3944
*
@@ -97,7 +102,7 @@ class ESP8266
97102

98103
/** Get the local network mask
99104
*
100-
* @return Null-terminated representation of the local network mask
105+
* @return Null-terminated representation of the local network mask
101106
* or null if no network mask has been recieved
102107
*/
103108
const char *getNetmask();
@@ -123,7 +128,7 @@ class ESP8266
123128
* see @a nsapi_error
124129
*/
125130
int scan(WiFiAccessPoint *res, unsigned limit);
126-
131+
127132
/**Perform a dns query
128133
*
129134
* @param name Hostname to resolve
@@ -206,9 +211,19 @@ class ESP8266
206211
attach(Callback<void()>(obj, method));
207212
}
208213

214+
/**
215+
* Start binding to a port
216+
*
217+
* @param address SocketAddress instance (only port is being used)
218+
*/
219+
bool bind(const SocketAddress& address);
220+
221+
void ping();
222+
209223
private:
210224
BufferedSerial _serial;
211225
ATParser _parser;
226+
Callback<void(SignalingAction, int)> _signalingCallback;
212227

213228
struct packet {
214229
struct packet *next;
@@ -217,12 +232,28 @@ class ESP8266
217232
// data follows
218233
} *_packets, **_packets_end;
219234
void _packet_handler();
235+
void _incoming_socket_opened(int8_t);
236+
void _incoming_socket_closed(int8_t);
220237
bool recv_ap(nsapi_wifi_ap_t *ap);
221238

222239
char _ip_buffer[16];
223240
char _gateway_buffer[16];
224241
char _netmask_buffer[16];
225242
char _mac_buffer[18];
243+
244+
// The CONNECTED OOB messages start with %d, and patching the ATParser is not worth it
245+
// Max. connections is 5 according to ESP8266_SOCKET_COUNT, if that changes, this has to change too
246+
void _incoming_socket_opened0() { _incoming_socket_opened(0); }
247+
void _incoming_socket_opened1() { _incoming_socket_opened(1); }
248+
void _incoming_socket_opened2() { _incoming_socket_opened(2); }
249+
void _incoming_socket_opened3() { _incoming_socket_opened(3); }
250+
void _incoming_socket_opened4() { _incoming_socket_opened(4); }
251+
252+
void _incoming_socket_closed0() { _incoming_socket_closed(0); }
253+
void _incoming_socket_closed1() { _incoming_socket_closed(1); }
254+
void _incoming_socket_closed2() { _incoming_socket_closed(2); }
255+
void _incoming_socket_closed3() { _incoming_socket_closed(3); }
256+
void _incoming_socket_closed4() { _incoming_socket_closed(4); }
226257
};
227258

228259
#endif

ESP8266Interface.cpp

Lines changed: 89 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@
3737

3838
// ESP8266Interface implementation
3939
ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug)
40-
: _esp(tx, rx, debug)
40+
: _esp(tx, rx, callback(this, &ESP8266Interface::signal), false)
4141
{
4242
memset(_ids, 0, sizeof(_ids));
4343
memset(_cbs, 0, sizeof(_cbs));
44+
memset(_incoming_sockets, 0, sizeof(_incoming_sockets));
4445

4546
_esp.attach(this, &ESP8266Interface::event);
4647
}
@@ -59,19 +60,19 @@ int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security
5960
int ESP8266Interface::connect()
6061
{
6162
_esp.setTimeout(ESP8266_CONNECT_TIMEOUT);
62-
63+
6364
if (!_esp.reset()) {
6465
return NSAPI_ERROR_DEVICE_ERROR;
65-
}
66-
66+
}
67+
6768
_esp.setTimeout(ESP8266_MISC_TIMEOUT);
68-
69+
6970
if (_esp.get_firmware_version() != ESP8266_VERSION) {
7071
debug("ESP8266: ERROR: Firmware incompatible with this driver.\
71-
\r\nUpdate to v%d - https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update\r\n",ESP8266_VERSION);
72+
\r\nUpdate to v%d - https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update\r\n",ESP8266_VERSION);
7273
return NSAPI_ERROR_DEVICE_ERROR;
7374
}
74-
75+
7576
_esp.setTimeout(ESP8266_CONNECT_TIMEOUT);
7677

7778
if (!_esp.startup(3)) {
@@ -164,24 +165,24 @@ int ESP8266Interface::socket_open(void **handle, nsapi_protocol_t proto)
164165
{
165166
// Look for an unused socket
166167
int id = -1;
167-
168+
168169
for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
169170
if (!_ids[i]) {
170171
id = i;
171172
_ids[i] = true;
172173
break;
173174
}
174175
}
175-
176+
176177
if (id == -1) {
177178
return NSAPI_ERROR_NO_SOCKET;
178179
}
179-
180+
180181
struct esp8266_socket *socket = new struct esp8266_socket;
181182
if (!socket) {
182183
return NSAPI_ERROR_NO_SOCKET;
183184
}
184-
185+
185186
socket->id = id;
186187
socket->proto = proto;
187188
socket->connected = false;
@@ -194,7 +195,7 @@ int ESP8266Interface::socket_close(void *handle)
194195
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
195196
int err = 0;
196197
_esp.setTimeout(ESP8266_MISC_TIMEOUT);
197-
198+
198199
if (socket->connected && !_esp.close(socket->id)) {
199200
err = NSAPI_ERROR_DEVICE_ERROR;
200201
}
@@ -207,7 +208,7 @@ int ESP8266Interface::socket_close(void *handle)
207208

208209
int ESP8266Interface::socket_bind(void *handle, const SocketAddress &address)
209210
{
210-
return NSAPI_ERROR_UNSUPPORTED;
211+
return _esp.bind(address);
211212
}
212213

213214
int ESP8266Interface::socket_listen(void *handle, int backlog)
@@ -224,38 +225,62 @@ int ESP8266Interface::socket_connect(void *handle, const SocketAddress &addr)
224225
if (!_esp.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
225226
return NSAPI_ERROR_DEVICE_ERROR;
226227
}
227-
228+
228229
socket->connected = true;
229230
return 0;
230231
}
231-
232+
232233
int ESP8266Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
233234
{
234-
return NSAPI_ERROR_UNSUPPORTED;
235+
printf("socket_accept\n");
236+
237+
while (1) {
238+
// to get the OOB messages we need to send something to the ESP8266 so the ATParser has time to
239+
// grab the packets. Send a bogus message to the module...
240+
_esp.get_firmware_version();
241+
242+
// now go through the _incoming_sockets array and see if there are unattached sockets...
243+
for (size_t ix = 0; ix < ESP8266_SOCKET_COUNT; ix++) {
244+
// printf("_incoming_sockets[ix] socket=%p connected=%d accepted=%d\n",
245+
// _incoming_sockets[ix].socket, _incoming_sockets[ix].socket && _incoming_sockets[ix].socket->connected,
246+
// _incoming_sockets[ix].accepted);
247+
if (_incoming_sockets[ix].socket && _incoming_sockets[ix].socket->connected && !_incoming_sockets[ix].accepted) {
248+
printf("accepting socket %d\n", ix);
249+
250+
*socket = _incoming_sockets[ix].socket;
251+
// addr is not used here I think...
252+
_incoming_sockets[ix].accepted = true;
253+
return 0;
254+
}
255+
}
256+
257+
wait_ms(20); // socket_accept is blocking
258+
}
259+
return 0;
235260
}
236261

237262
int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
238263
{
239264
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
240265
_esp.setTimeout(ESP8266_SEND_TIMEOUT);
241-
266+
242267
if (!_esp.send(socket->id, data, size)) {
243268
return NSAPI_ERROR_DEVICE_ERROR;
244269
}
245-
270+
246271
return size;
247272
}
248273

249274
int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
250275
{
251276
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
252277
_esp.setTimeout(ESP8266_RECV_TIMEOUT);
253-
278+
254279
int32_t recv = _esp.recv(socket->id, data, size);
255280
if (recv < 0) {
256281
return NSAPI_ERROR_WOULD_BLOCK;
257282
}
258-
283+
259284
return recv;
260285
}
261286

@@ -278,7 +303,7 @@ int ESP8266Interface::socket_sendto(void *handle, const SocketAddress &addr, con
278303
}
279304
socket->addr = addr;
280305
}
281-
306+
282307
return socket_send(socket, data, size);
283308
}
284309

@@ -295,7 +320,7 @@ int ESP8266Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *d
295320

296321
void ESP8266Interface::socket_attach(void *handle, void (*callback)(void *), void *data)
297322
{
298-
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
323+
struct esp8266_socket *socket = (struct esp8266_socket *)handle;
299324
_cbs[socket->id].callback = callback;
300325
_cbs[socket->id].data = data;
301326
}
@@ -307,3 +332,45 @@ void ESP8266Interface::event() {
307332
}
308333
}
309334
}
335+
336+
void ESP8266Interface::signal(SignalingAction action, int socket_id) {
337+
printf("ESP8266Interface::signal %d %d\n", action, socket_id);
338+
339+
if (action == ESP8266_SOCKET_CONNECT) {
340+
if (_ids[socket_id]) {
341+
// this should not be possible...
342+
printf("ESP8266_SOCKET_CONNECT for socket that already exists...\n");
343+
// return;
344+
}
345+
346+
struct esp8266_socket *socket = new struct esp8266_socket;
347+
if (!socket) {
348+
printf("ESP8266_SOCKET_CONNECT could not create socket\n");
349+
return;
350+
}
351+
352+
_ids[socket_id] = true;
353+
354+
socket->id = socket_id;
355+
socket->proto = NSAPI_TCP;
356+
socket->connected = true;
357+
358+
_incoming_sockets[socket_id].socket = socket;
359+
_incoming_sockets[socket_id].accepted = false;
360+
}
361+
else if (action == ESP8266_SOCKET_CLOSE) {
362+
// Q: should we be able to delete the socket here? probably segfaults if held in user code
363+
struct esp8266_socket *socket = _incoming_sockets[socket_id].socket;
364+
if (!socket || !socket->connected) {
365+
printf("ESP8266_SOCKET_CLOSE for socket that does not exist or is already closed\n");
366+
return;
367+
}
368+
369+
socket->connected = false;
370+
_incoming_sockets[socket_id].accepted = false;
371+
_incoming_sockets[socket_id].socket = NULL;
372+
_ids[socket_id] = false;
373+
374+
// delete socket?
375+
}
376+
}

0 commit comments

Comments
 (0)