@@ -62,6 +62,100 @@ static void _set_ctx(sock_async_ctx_t *ctx, event_queue_t *ev_queue)
6262 ctx -> queue = ev_queue ;
6363}
6464
65+ void sock_event_close (sock_async_ctx_t * async_ctx )
66+ {
67+ event_queue_t * queue = async_ctx -> queue ;
68+ if (!queue ) {
69+ /* no callback registered */
70+ return ;
71+ }
72+
73+ /* RIOTs socket API is not thread safe so we assume that wherever this is
74+ * called from it's not racing against some other socket usage.
75+ *
76+ * But we have to go stricter and assume this is called from the same thread
77+ * that processes the events. There is no way of preventing the networking
78+ * subsystem from posting socket events until the socket has been
79+ * unregistered, which is only happening when closing the socket and the
80+ * reason we're here in the first place. */
81+ assume (!queue -> waiter || thread_getpid_of (queue -> waiter ) == thread_getpid ());
82+
83+ event_cancel (async_ctx -> queue , & async_ctx -> event .super );
84+ }
85+
86+ typedef enum {
87+ #if defined(MODULE_SOCK_UDP ) || defined(DOXYGEN )
88+ SOCK_ASYNC_UDP ,
89+ #endif
90+ #if defined(MODULE_SOCK_TCP ) || defined(DOXYGEN )
91+ SOCK_ASYNC_TCP ,
92+ #endif
93+ #if defined(MODULE_SOCK_IP ) || defined(DOXYGEN )
94+ SOCK_ASYNC_IP ,
95+ #endif
96+ #if defined(MODULE_SOCK_DTLS ) || defined(DOXYGEN )
97+ SOCK_ASYNC_DTLS ,
98+ #endif
99+ } sock_async_t ;
100+
101+ typedef struct {
102+ event_t super ;
103+ sock_async_t type ;
104+ void * sock ;
105+ } _sock_close_ev ;
106+
107+ static void _sock_event_close_cb (event_t * ev )
108+ {
109+ _sock_close_ev * close_ev = container_of (ev , _sock_close_ev , super );
110+
111+ switch (close_ev -> type ) {
112+ #if defined(MODULE_SOCK_UDP ) || defined(DOXYGEN )
113+ case SOCK_ASYNC_UDP :
114+ sock_udp_close (close_ev -> sock );
115+ break ;
116+ #endif
117+ #if defined(MODULE_SOCK_TCP ) || defined(DOXYGEN )
118+ case SOCK_ASYNC_TCP :
119+ sock_tcp_disconnect (close_ev -> sock );
120+ break ;
121+ #endif
122+ #if defined(MODULE_SOCK_IP ) || defined(DOXYGEN )
123+ case SOCK_ASYNC_IP :
124+ sock_ip_close (close_ev -> sock );
125+ break ;
126+ #endif
127+ #if defined(MODULE_SOCK_DTLS ) || defined(DOXYGEN )
128+ case SOCK_ASYNC_DTLS :
129+ sock_dtls_close (close_ev -> sock );
130+ break ;
131+ #endif
132+ }
133+ }
134+
135+ static void _sock_event_close_common (void * sock , sock_async_ctx_t * async_ctx ,
136+ sock_async_t type )
137+ {
138+ _sock_close_ev ev = {
139+ .super .handler = _sock_event_close_cb ,
140+ .type = type ,
141+ .sock = sock ,
142+ };
143+
144+ if (!async_ctx -> queue ||
145+ !async_ctx -> queue -> waiter ||
146+ thread_getpid_of (async_ctx -> queue -> waiter ) == thread_getpid ()) {
147+ /* - this socket is not async OR
148+ * - there is no thread processing the event queue (in which case we
149+ * might race against @ref event_queue_claim() but so is life)
150+ * OR we are on the event queue thread. In the first case we might
151+ * block forever, in the second we surely will, so do it now. */
152+ _sock_event_close_cb (& ev .super );
153+ return ;
154+ }
155+
156+ event_post (async_ctx -> queue , & ev .super );
157+ event_sync (async_ctx -> queue );
158+ }
65159#ifdef MODULE_SOCK_DTLS
66160static void _dtls_cb (sock_dtls_t * sock , sock_async_flags_t type , void * arg )
67161{
@@ -77,6 +171,11 @@ void sock_dtls_event_init(sock_dtls_t *sock, event_queue_t *ev_queue,
77171 ctx -> event .cb .dtls = handler ;
78172 sock_dtls_set_cb (sock , _dtls_cb , handler_arg );
79173}
174+
175+ void sock_dtls_event_close (sock_dtls_t * sock )
176+ {
177+ _sock_event_close_common (sock , sock_dtls_get_async_ctx (sock ), SOCK_ASYNC_DTLS );
178+ }
80179#endif /* MODULE_SOCK_DTLS */
81180
82181#ifdef MODULE_SOCK_IP
@@ -94,6 +193,11 @@ void sock_ip_event_init(sock_ip_t *sock, event_queue_t *ev_queue,
94193 ctx -> event .cb .ip = handler ;
95194 sock_ip_set_cb (sock , _ip_cb , handler_arg );
96195}
196+
197+ void sock_ip_event_close (sock_ip_t * sock )
198+ {
199+ _sock_event_close_common (sock , sock_ip_get_async_ctx (sock ), SOCK_ASYNC_IP );
200+ }
97201#endif /* MODULE_SOCK_IP */
98202
99203#ifdef MODULE_SOCK_TCP
@@ -127,6 +231,11 @@ void sock_tcp_queue_event_init(sock_tcp_queue_t *queue, event_queue_t *ev_queue,
127231 ctx -> event .cb .tcp_queue = handler ;
128232 sock_tcp_queue_set_cb (queue , _tcp_queue_cb , handler_arg );
129233}
234+
235+ void sock_tcp_event_close (sock_tcp_t * sock )
236+ {
237+ _sock_event_close_common (sock , sock_tcp_get_async_ctx (sock ), SOCK_ASYNC_TCP );
238+ }
130239#endif /* MODULE_SOCK_TCP */
131240
132241#ifdef MODULE_SOCK_UDP
@@ -144,6 +253,12 @@ void sock_udp_event_init(sock_udp_t *sock, event_queue_t *ev_queue,
144253 ctx -> event .cb .udp = handler ;
145254 sock_udp_set_cb (sock , _udp_cb , handler_arg );
146255}
256+
257+ void sock_udp_event_close (sock_udp_t * sock )
258+ {
259+ _sock_event_close_common (sock , sock_udp_get_async_ctx (sock ), SOCK_ASYNC_UDP );
260+ }
261+
147262#endif /* MODULE_SOCK_UDP */
148263
149264/** @} */
0 commit comments