29
29
30
30
#include "py/runtime.h"
31
31
32
+ #include <stdio.h>
32
33
#include <zephyr.h>
33
34
#include <net/net_context.h>
34
35
#include <net/nbuf.h>
35
36
37
+ #if 0 // print debugging info
38
+ #define DEBUG_printf printf
39
+ #else // don't print debugging info
40
+ #define DEBUG_printf (...) (void)0
41
+ #endif
42
+
36
43
typedef struct _socket_obj_t {
37
44
mp_obj_base_t base ;
38
45
struct net_context * ctx ;
46
+ struct k_fifo recv_q ;
39
47
} socket_obj_t ;
40
48
41
49
STATIC const mp_obj_type_t socket_type ;
@@ -62,6 +70,44 @@ STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct socka
62
70
sockaddr_in -> sin_port = htons (mp_obj_get_int (addr_items [1 ]));
63
71
}
64
72
73
+ // Copy data from Zephyr net_buf chain into linear buffer.
74
+ // We don't use net_nbuf_read(), because it's weird (e.g., we'd like to
75
+ // free processed data fragment ASAP, while net_nbuf_read() holds onto
76
+ // the whole fragment chain to do its deeds, and that's minor comparing
77
+ // to the fact that it copies data byte by byte).
78
+ static char * net_buf_gather (struct net_buf * buf , char * to , unsigned max_len ) {
79
+ struct net_buf * tmp = buf -> frags ;
80
+ unsigned header_len = net_nbuf_appdata (buf ) - tmp -> data ;
81
+ net_buf_pull (tmp , header_len );
82
+
83
+ while (tmp && max_len ) {
84
+ unsigned len = tmp -> len ;
85
+ if (len > max_len ) {
86
+ len = max_len ;
87
+ }
88
+ memcpy (to , tmp -> data , len );
89
+ to += len ;
90
+ max_len -= len ;
91
+ tmp = net_buf_frag_del (buf , tmp );
92
+ }
93
+
94
+ return to ;
95
+ }
96
+
97
+ // Callback for incoming packets.
98
+ static void sock_received_cb (struct net_context * context , struct net_buf * net_buf , int status , void * user_data ) {
99
+ socket_obj_t * socket = (socket_obj_t * )user_data ;
100
+ DEBUG_printf ("recv cb: context: %p, status: %d, buf: %p" , context , status , net_buf );
101
+ if (net_buf ) {
102
+ DEBUG_printf (" (sz=%d, l=%d), token: %p" , net_buf -> size , net_buf -> len , net_nbuf_token (net_buf ));
103
+ }
104
+ DEBUG_printf ("\n" );
105
+
106
+ // net_buf->frags will be overwritten by fifo, so save it
107
+ net_nbuf_set_token (net_buf , net_buf -> frags );
108
+ k_fifo_put (& socket -> recv_q , net_buf );
109
+ }
110
+
65
111
// Methods
66
112
67
113
STATIC void socket_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
@@ -79,6 +125,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t
79
125
80
126
socket_obj_t * socket = m_new_obj_with_finaliser (socket_obj_t );
81
127
socket -> base .type = type ;
128
+ k_fifo_init (& socket -> recv_q );
82
129
83
130
int family = AF_INET ;
84
131
int socktype = SOCK_STREAM ;
@@ -114,6 +161,8 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
114
161
parse_inet_addr (socket , addr_in , & sockaddr );
115
162
116
163
RAISE_ERRNO (net_context_bind (socket -> ctx , & sockaddr , sizeof (sockaddr )));
164
+ DEBUG_printf ("Setting recv cb after bind\n" );
165
+ RAISE_ERRNO (net_context_recv (socket -> ctx , sock_received_cb , K_NO_WAIT , socket ));
117
166
return mp_const_none ;
118
167
}
119
168
STATIC MP_DEFINE_CONST_FUN_OBJ_2 (socket_bind_obj , socket_bind );
@@ -126,6 +175,8 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
126
175
parse_inet_addr (socket , addr_in , & sockaddr );
127
176
128
177
RAISE_ERRNO (net_context_connect (socket -> ctx , & sockaddr , sizeof (sockaddr ), NULL , K_FOREVER , NULL ));
178
+ DEBUG_printf ("Setting recv cb after connect()\n" );
179
+ RAISE_ERRNO (net_context_recv (socket -> ctx , sock_received_cb , K_NO_WAIT , socket ));
129
180
return mp_const_none ;
130
181
}
131
182
STATIC MP_DEFINE_CONST_FUN_OBJ_2 (socket_connect_obj , socket_connect );
@@ -149,6 +200,41 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
149
200
}
150
201
STATIC MP_DEFINE_CONST_FUN_OBJ_2 (socket_send_obj , socket_send );
151
202
203
+ STATIC mp_obj_t socket_recv (mp_obj_t self_in , mp_obj_t len_in ) {
204
+ socket_obj_t * socket = self_in ;
205
+ socket_check_closed (socket );
206
+
207
+ enum net_sock_type sock_type = net_context_get_type (socket -> ctx );
208
+ mp_int_t max_len = mp_obj_get_int (len_in );
209
+ unsigned recv_len ;
210
+ vstr_t vstr ;
211
+
212
+ if (sock_type == SOCK_DGRAM ) {
213
+
214
+ struct net_buf * net_buf = k_fifo_get (& socket -> recv_q , K_FOREVER );
215
+ // Restore ->frags overwritten by fifo
216
+ net_buf -> frags = net_nbuf_token (net_buf );
217
+
218
+ recv_len = net_nbuf_appdatalen (net_buf );
219
+ DEBUG_printf ("recv: net_buf=%p, appdatalen: %d\n" , net_buf , recv_len );
220
+
221
+ if (recv_len > max_len ) {
222
+ recv_len = max_len ;
223
+ }
224
+
225
+ vstr_init_len (& vstr , recv_len );
226
+ net_buf_gather (net_buf , vstr .buf , recv_len );
227
+ net_nbuf_unref (net_buf );
228
+
229
+ } else {
230
+ mp_not_implemented ("" );
231
+ }
232
+
233
+ mp_obj_t ret = mp_obj_new_str_from_vstr (& mp_type_bytes , & vstr );
234
+ return ret ;
235
+ }
236
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2 (socket_recv_obj , socket_recv );
237
+
152
238
STATIC mp_obj_t socket_close (mp_obj_t self_in ) {
153
239
socket_obj_t * socket = self_in ;
154
240
if (socket -> ctx != NULL ) {
@@ -165,6 +251,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
165
251
{ MP_OBJ_NEW_QSTR (MP_QSTR_bind ), (mp_obj_t )& socket_bind_obj },
166
252
{ MP_OBJ_NEW_QSTR (MP_QSTR_connect ), (mp_obj_t )& socket_connect_obj },
167
253
{ MP_OBJ_NEW_QSTR (MP_QSTR_send ), (mp_obj_t )& socket_send_obj },
254
+ { MP_OBJ_NEW_QSTR (MP_QSTR_recv ), (mp_obj_t )& socket_recv_obj },
168
255
};
169
256
STATIC MP_DEFINE_CONST_DICT (socket_locals_dict , socket_locals_dict_table );
170
257
0 commit comments