@@ -170,6 +170,7 @@ struct SocketData
170170 size_t buffer ;
171171 bool active : 1 ;
172172 bool binary : 1 ;
173+ bool read_condition : 1 ;
173174};
174175
175176struct TCPClientSocketData
@@ -237,6 +238,10 @@ void IRAM_ATTR socket_callback(struct netconn *netconn, enum netconn_evt evt, u1
237238 TRACE ("socket_callback netconn=%p, evt=%d, len=%d\n" , (void * ) netconn , evt , len );
238239
239240 // We only listen to NETCONN_EVT_RCVPLUS events
241+ // NETCONN_EVT_RCVPLUS means it's safe to perform a potentially call once
242+ // more. However, two data events (with len > 0) may be processed by a single
243+ // netconn_recv. So we're sending len as well to address the case where len
244+ // is equal to 0 and netconn_recv will return an error.
240245 if (evt == NETCONN_EVT_RCVPLUS ) {
241246 struct NetconnEvent event ;
242247 event .netconn = netconn ;
@@ -362,8 +367,10 @@ static void socket_data_init(struct SocketData *data, Context *ctx, struct netco
362367 data -> process_id = ctx -> process_id ;
363368 data -> controlling_process_pid = 0 ;
364369 data -> port = 0 ;
370+ data -> avail_bytes = 0 ;
365371 data -> active = true;
366372 data -> binary = true;
373+ data -> read_condition = false;
367374 data -> buffer = 512 ;
368375
369376 list_append (sockets , & data -> sockets_head );
@@ -679,6 +686,7 @@ static NativeHandlerResult do_receive_data(Context *ctx)
679686 return NativeContinue ;
680687 }
681688 socket_data -> avail_bytes -= data_len ;
689+ socket_data -> read_condition = false;
682690
683691 TRACE ("%*s\n" , (int ) data_len , (char * ) data );
684692
@@ -781,9 +789,22 @@ static NativeHandlerResult do_data_netconn_event(Context *ctx, int len)
781789 TRACE ("do_data_netconn_event\n" );
782790 struct SocketData * socket_data = ctx -> platform_data ;
783791
792+ socket_data -> avail_bytes += len ;
793+
794+ // We got a message saying that it's safe to call netconn_recv as it will
795+ // not block yet there is no data.
796+ if (len == 0 ) {
797+ socket_data -> read_condition = true;
798+ }
799+
800+ // If socket is in passive mode but we don't have any waiting receiver, we
801+ // should just increment the number of available bytes.
784802 if (!socket_data -> active && socket_data -> passive_receiver_process_pid == 0 ) {
785- // netconn_recv will not block
786- socket_data -> avail_bytes += len ;
803+ return NativeContinue ;
804+ }
805+
806+ // We may have already read the bytes from this event
807+ if (socket_data -> avail_bytes <= 0 && !socket_data -> read_condition ) {
787808 return NativeContinue ;
788809 }
789810 return do_receive_data (ctx );
@@ -1249,11 +1270,12 @@ static NativeHandlerResult do_recvfrom(Context *ctx, const GenMessage *gen_messa
12491270 socket_data -> passive_receiver_process_pid = pid ;
12501271 socket_data -> passive_ref_ticks = ref_ticks ;
12511272
1252- if (socket_data -> avail_bytes > 0 ) {
1253- return do_receive_data (ctx );
1273+ // There may be nothing to read.
1274+ if (socket_data -> avail_bytes <= 0 && !socket_data -> read_condition ) {
1275+ return NativeContinue ;
12541276 }
12551277
1256- return NativeContinue ;
1278+ return do_receive_data ( ctx ) ;
12571279}
12581280
12591281static void do_get_port (Context * ctx , const GenMessage * gen_message )
0 commit comments