@@ -146,6 +146,7 @@ struct UDPReceivedItem
146
146
147
147
static err_t tcp_recv_cb (void * arg , struct tcp_pcb * tpcb , struct pbuf * p , err_t err );
148
148
static void udp_recv_cb (void * arg , struct udp_pcb * pcb , struct pbuf * p , const ip_addr_t * addr , u16_t port );
149
+ static void tcp_err_cb (void * arg , err_t err );
149
150
150
151
#endif
151
152
@@ -620,6 +621,7 @@ static term nif_socket_open(Context *ctx, int argc, term argv[])
620
621
if (rsrc_obj -> socket_state & SocketStateTCP ) {
621
622
LWIP_BEGIN ();
622
623
tcp_arg (rsrc_obj -> tcp_pcb , rsrc_obj );
624
+ tcp_err (rsrc_obj -> tcp_pcb , tcp_err_cb );
623
625
tcp_recv (rsrc_obj -> tcp_pcb , tcp_recv_cb );
624
626
LWIP_END ();
625
627
} else {
@@ -996,6 +998,23 @@ static void udp_recv_cb(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip
996
998
otp_socket_lwip_enqueue (& event );
997
999
} // Otherwise socket was closed.
998
1000
}
1001
+
1002
+ // LwIP tcpip_try_callback uses queue.
1003
+ static void tcpip_try_callback_handler (struct LWIPEvent * event )
1004
+ {
1005
+ event -> tcpip_try_callback .function (event -> tcpip_try_callback .ctx );
1006
+ }
1007
+
1008
+ int tcpip_try_callback (tcpip_callback_fn function , void * ctx )
1009
+ {
1010
+ struct LWIPEvent event ;
1011
+ event .handler = tcpip_try_callback_handler ;
1012
+ event .tcpip_try_callback .function = function ;
1013
+ event .tcpip_try_callback .ctx = ctx ;
1014
+ otp_socket_lwip_enqueue (& event );
1015
+ return ERR_OK ;
1016
+ }
1017
+
999
1018
#endif
1000
1019
1001
1020
static term nif_socket_select_read (Context * ctx , int argc , term argv [])
@@ -2639,6 +2658,25 @@ static err_t tcp_connected_cb(void *arg, struct tcp_pcb *tpcb, err_t err)
2639
2658
} // else: sender died
2640
2659
return ERR_OK ;
2641
2660
}
2661
+
2662
+ static void tcp_err_cb (void * arg , err_t err )
2663
+ {
2664
+ UNUSED (err );
2665
+
2666
+ struct SocketResource * rsrc_obj = (struct SocketResource * ) arg ;
2667
+ struct RefcBinary * rsrc_refc = refc_binary_from_data (rsrc_obj );
2668
+ GlobalContext * global = rsrc_refc -> resource_type -> global ;
2669
+ int32_t target_pid = rsrc_obj -> selecting_process_id ;
2670
+ rsrc_obj -> selecting_process_id = INVALID_PROCESS_ID ;
2671
+ rsrc_obj -> socket_state = SocketStateTCPConnected ;
2672
+ if (target_pid != INVALID_PROCESS_ID ) {
2673
+ struct LWIPEvent event ;
2674
+ event .handler = trap_answer_closed ;
2675
+ event .trap_answer_closed .global = global ;
2676
+ event .trap_answer_closed .target_pid = target_pid ;
2677
+ otp_socket_lwip_enqueue (& event );
2678
+ } // else: sender died
2679
+ }
2642
2680
#endif
2643
2681
2644
2682
static term nif_socket_connect (Context * ctx , int argc , term argv [])
@@ -2741,6 +2779,9 @@ static term nif_socket_connect(Context *ctx, int argc, term argv[])
2741
2779
LWIP_END ();
2742
2780
2743
2781
if (UNLIKELY (err != ERR_OK )) {
2782
+ if (err == ERR_USE || err == ERR_RTE ) {
2783
+ return make_error_tuple (CLOSED_ATOM , ctx );
2784
+ }
2744
2785
RAISE_ERROR (OUT_OF_MEMORY_ATOM );
2745
2786
}
2746
2787
if (rsrc_obj -> socket_state & SocketStateUDP ) {
0 commit comments