47
47
48
48
#define PPP_CLOSE_TIMEOUT_MS (4000)
49
49
50
+ typedef enum {
51
+ STATE_INACTIVE ,
52
+ STATE_ACTIVE ,
53
+ STATE_ERROR ,
54
+ STATE_CONNECTING ,
55
+ STATE_CONNECTED ,
56
+ } network_ppp_state_t ;
57
+
50
58
typedef struct _ppp_if_obj_t {
51
59
mp_obj_base_t base ;
52
- bool active ;
53
- bool connected ;
60
+ int error_code ;
54
61
volatile bool clean_close ;
55
62
ppp_pcb * pcb ;
56
63
mp_obj_t stream ;
57
64
SemaphoreHandle_t inactiveWaitSem ;
58
65
volatile TaskHandle_t client_task_handle ;
59
66
struct netif pppif ;
67
+ network_ppp_state_t state ;
60
68
} ppp_if_obj_t ;
61
69
62
70
const mp_obj_type_t ppp_if_type ;
@@ -68,18 +76,26 @@ static void ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
68
76
switch (err_code ) {
69
77
case PPPERR_NONE :
70
78
#if CONFIG_LWIP_IPV6
71
- self -> connected = (pppif -> ip_addr .u_addr .ip4 .addr != 0 );
79
+ if (pppif -> ip_addr .u_addr .ip4 .addr != 0 ) {
80
+ self -> state = STATE_CONNECTED ;
81
+ }
72
82
#else
73
- self -> connected = (pppif -> ip_addr .addr != 0 );
83
+ if (pppif -> ip_addr .addr != 0 ) {
84
+ self -> state = STATE_CONNECTED ;
85
+ }
74
86
#endif // CONFIG_LWIP_IPV6
75
87
break ;
76
88
case PPPERR_USER :
89
+ if (self -> state >= STATE_ERROR ) {
90
+ // Indicate that we are no longer connected and thus
91
+ // only need to free the PPP PCB, not close it.
92
+ self -> state = STATE_ACTIVE ;
93
+ }
77
94
self -> clean_close = true;
78
95
break ;
79
- case PPPERR_CONNECT :
80
- self -> connected = false;
81
- break ;
82
96
default :
97
+ self -> state = STATE_ERROR ;
98
+ self -> error_code = err_code ;
83
99
break ;
84
100
}
85
101
}
@@ -90,16 +106,46 @@ static mp_obj_t ppp_make_new(mp_obj_t stream) {
90
106
}
91
107
92
108
ppp_if_obj_t * self = mp_obj_malloc_with_finaliser (ppp_if_obj_t , & ppp_if_type );
109
+ self -> state = STATE_INACTIVE ;
93
110
self -> stream = stream ;
94
- self -> active = false;
95
- self -> connected = false;
111
+ self -> pcb = NULL ;
96
112
self -> clean_close = false;
97
113
self -> client_task_handle = NULL ;
98
114
99
115
return MP_OBJ_FROM_PTR (self );
100
116
}
101
117
MP_DEFINE_CONST_FUN_OBJ_1 (esp_network_ppp_make_new_obj , ppp_make_new );
102
118
119
+ static mp_obj_t ppp_delete (mp_obj_t self_in ) {
120
+ ppp_if_obj_t * self = MP_OBJ_TO_PTR (self_in );
121
+ if (self -> state >= STATE_ACTIVE ) {
122
+ if (self -> state >= STATE_ERROR ) {
123
+ // Still connected over the stream.
124
+ // Force the connection to close, with nocarrier=1.
125
+ self -> state = STATE_INACTIVE ;
126
+ pppapi_close (self -> pcb , 1 );
127
+ uint32_t t0 = mp_hal_ticks_ms ();
128
+ while (!self -> clean_close && mp_hal_ticks_ms () - t0 < PPP_CLOSE_TIMEOUT_MS ) {
129
+ mp_hal_delay_ms (10 );
130
+ }
131
+
132
+ // Shutdown task
133
+ xTaskNotifyGive (self -> client_task_handle );
134
+ t0 = mp_hal_ticks_ms ();
135
+ while (self -> client_task_handle != NULL && mp_hal_ticks_ms () - t0 < PPP_CLOSE_TIMEOUT_MS ) {
136
+ mp_hal_delay_ms (10 );
137
+ }
138
+ }
139
+ // Free PPP PCB and reset state.
140
+ self -> state = STATE_INACTIVE ;
141
+ pppapi_free (self -> pcb );
142
+ self -> pcb = NULL ;
143
+ self -> clean_close = false;
144
+ }
145
+ return mp_const_none ;
146
+ }
147
+ MP_DEFINE_CONST_FUN_OBJ_1 (ppp_delete_obj , ppp_delete );
148
+
103
149
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL (5 , 4 , 0 )
104
150
static u32_t ppp_output_callback (ppp_pcb * pcb , const void * data , u32_t len , void * ctx )
105
151
#else
@@ -141,72 +187,29 @@ static void pppos_client_task(void *self_in) {
141
187
}
142
188
}
143
189
144
- static mp_obj_t ppp_active (size_t n_args , const mp_obj_t * args ) {
145
- ppp_if_obj_t * self = MP_OBJ_TO_PTR (args [0 ]);
146
-
147
- if (n_args > 1 ) {
148
- if (mp_obj_is_true (args [1 ])) {
149
- if (self -> active ) {
150
- return mp_const_true ;
151
- }
152
-
153
- self -> pcb = pppapi_pppos_create (& self -> pppif , ppp_output_callback , ppp_status_cb , self );
154
-
155
- if (self -> pcb == NULL ) {
156
- mp_raise_msg (& mp_type_RuntimeError , MP_ERROR_TEXT ("init failed" ));
157
- }
158
- self -> active = true;
159
- } else {
160
- if (!self -> active ) {
161
- return mp_const_false ;
162
- }
163
-
164
- if (self -> client_task_handle != NULL ) { // is connecting or connected?
165
- // Wait for PPPERR_USER, with timeout
166
- pppapi_close (self -> pcb , 0 );
167
- uint32_t t0 = mp_hal_ticks_ms ();
168
- while (!self -> clean_close && mp_hal_ticks_ms () - t0 < PPP_CLOSE_TIMEOUT_MS ) {
169
- mp_hal_delay_ms (10 );
170
- }
171
-
172
- // Shutdown task
173
- xTaskNotifyGive (self -> client_task_handle );
174
- t0 = mp_hal_ticks_ms ();
175
- while (self -> client_task_handle != NULL && mp_hal_ticks_ms () - t0 < PPP_CLOSE_TIMEOUT_MS ) {
176
- mp_hal_delay_ms (10 );
177
- }
178
- }
179
-
180
- // Release PPP
181
- pppapi_free (self -> pcb );
182
- self -> pcb = NULL ;
183
- self -> active = false;
184
- self -> connected = false;
185
- self -> clean_close = false;
186
- }
187
- }
188
- return mp_obj_new_bool (self -> active );
189
- }
190
- static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (ppp_active_obj , 1 , 2 , ppp_active ) ;
191
-
192
190
static mp_obj_t ppp_connect_py (size_t n_args , const mp_obj_t * args , mp_map_t * kw_args ) {
193
191
enum { ARG_authmode , ARG_username , ARG_password };
194
192
static const mp_arg_t allowed_args [] = {
195
- { MP_QSTR_authmode , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = PPPAUTHTYPE_NONE } },
196
- { MP_QSTR_username , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
197
- { MP_QSTR_password , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
193
+ { MP_QSTR_security , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = PPPAUTHTYPE_NONE } },
194
+ { MP_QSTR_user , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
195
+ { MP_QSTR_key , MP_ARG_KW_ONLY | MP_ARG_OBJ , {.u_rom_obj = MP_ROM_NONE } },
198
196
};
199
197
200
198
mp_arg_val_t parsed_args [MP_ARRAY_SIZE (allowed_args )];
201
199
mp_arg_parse_all (n_args - 1 , args + 1 , kw_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , parsed_args );
202
200
203
201
ppp_if_obj_t * self = MP_OBJ_TO_PTR (args [0 ]);
204
202
205
- if (!self -> active ) {
206
- mp_raise_msg (& mp_type_OSError , MP_ERROR_TEXT ("must be active" ));
203
+ if (self -> state == STATE_INACTIVE ) {
204
+ self -> pcb = pppapi_pppos_create (& self -> pppif , ppp_output_callback , ppp_status_cb , self );
205
+
206
+ if (self -> pcb == NULL ) {
207
+ mp_raise_msg (& mp_type_RuntimeError , MP_ERROR_TEXT ("init failed" ));
208
+ }
209
+ self -> state = STATE_ACTIVE ;
207
210
}
208
211
209
- if (self -> client_task_handle != NULL ) {
212
+ if (self -> client_task_handle != NULL || self -> state == STATE_CONNECTING || self -> state == STATE_CONNECTED ) {
210
213
mp_raise_OSError (MP_EALREADY );
211
214
}
212
215
@@ -238,17 +241,35 @@ static mp_obj_t ppp_connect_py(size_t n_args, const mp_obj_t *args, mp_map_t *kw
238
241
mp_raise_msg (& mp_type_RuntimeError , MP_ERROR_TEXT ("failed to create worker task" ));
239
242
}
240
243
244
+ self -> state = STATE_CONNECTING ;
245
+
241
246
return mp_const_none ;
242
247
}
243
248
MP_DEFINE_CONST_FUN_OBJ_KW (ppp_connect_obj , 1 , ppp_connect_py );
244
249
245
- static mp_obj_t ppp_delete (mp_obj_t self_in ) {
250
+ static mp_obj_t ppp_disconnect_py (mp_obj_t self_in ) {
246
251
ppp_if_obj_t * self = MP_OBJ_TO_PTR (self_in );
247
- mp_obj_t args [] = {self , mp_const_false };
248
- ppp_active (2 , args );
252
+
253
+ if (self -> client_task_handle != NULL || self -> state == STATE_CONNECTING || self -> state == STATE_CONNECTED ) {
254
+ // Wait for PPPERR_USER, with timeout
255
+ pppapi_close (self -> pcb , 0 );
256
+ uint32_t t0 = mp_hal_ticks_ms ();
257
+ while (!self -> clean_close && mp_hal_ticks_ms () - t0 < PPP_CLOSE_TIMEOUT_MS ) {
258
+ mp_hal_delay_ms (10 );
259
+ }
260
+
261
+ // Shutdown task
262
+ xTaskNotifyGive (self -> client_task_handle );
263
+ t0 = mp_hal_ticks_ms ();
264
+ while (self -> client_task_handle != NULL && mp_hal_ticks_ms () - t0 < PPP_CLOSE_TIMEOUT_MS ) {
265
+ mp_hal_delay_ms (10 );
266
+ }
267
+ }
268
+
269
+ self -> clean_close = false;
249
270
return mp_const_none ;
250
271
}
251
- MP_DEFINE_CONST_FUN_OBJ_1 (ppp_delete_obj , ppp_delete );
272
+ static MP_DEFINE_CONST_FUN_OBJ_1 (ppp_disconnect_obj , ppp_disconnect_py ) ;
252
273
253
274
static mp_obj_t ppp_ifconfig (size_t n_args , const mp_obj_t * args ) {
254
275
ppp_if_obj_t * self = MP_OBJ_TO_PTR (args [0 ]);
@@ -321,13 +342,18 @@ static mp_obj_t ppp_ipconfig(size_t n_args, const mp_obj_t *args, mp_map_t *kwar
321
342
static MP_DEFINE_CONST_FUN_OBJ_KW (ppp_ipconfig_obj , 1 , ppp_ipconfig ) ;
322
343
323
344
static mp_obj_t ppp_status (mp_obj_t self_in ) {
324
- return mp_const_none ;
345
+ ppp_if_obj_t * self = MP_OBJ_TO_PTR (self_in );
346
+ if (self -> state == STATE_ERROR ) {
347
+ return MP_OBJ_NEW_SMALL_INT (- self -> error_code );
348
+ } else {
349
+ return MP_OBJ_NEW_SMALL_INT (self -> state );
350
+ }
325
351
}
326
352
static MP_DEFINE_CONST_FUN_OBJ_1 (ppp_status_obj , ppp_status ) ;
327
353
328
354
static mp_obj_t ppp_isconnected (mp_obj_t self_in ) {
329
355
ppp_if_obj_t * self = MP_OBJ_TO_PTR (self_in );
330
- return mp_obj_new_bool (self -> connected );
356
+ return mp_obj_new_bool (self -> state == STATE_CONNECTED );
331
357
}
332
358
static MP_DEFINE_CONST_FUN_OBJ_1 (ppp_isconnected_obj , ppp_isconnected ) ;
333
359
@@ -386,18 +412,25 @@ static mp_obj_t ppp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
386
412
}
387
413
static MP_DEFINE_CONST_FUN_OBJ_KW (ppp_config_obj , 1 , ppp_config ) ;
388
414
415
+ static mp_obj_t ppp_poll (size_t n_args , const mp_obj_t * args ) {
416
+ mp_raise_msg (& mp_type_RuntimeError , MP_ERROR_TEXT ("Method not supported on ESP32" ));
417
+ }
418
+ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (ppp_poll_obj , 1 , 2 , ppp_poll ) ;
419
+
389
420
static const mp_rom_map_elem_t ppp_if_locals_dict_table [] = {
390
- { MP_ROM_QSTR (MP_QSTR_active ), MP_ROM_PTR (& ppp_active_obj ) },
421
+ { MP_ROM_QSTR (MP_QSTR___del__ ), MP_ROM_PTR (& ppp_delete_obj ) },
422
+ { MP_ROM_QSTR (MP_QSTR_config ), MP_ROM_PTR (& ppp_config_obj ) },
423
+ { MP_ROM_QSTR (MP_QSTR_status ), MP_ROM_PTR (& ppp_status_obj ) },
391
424
{ MP_ROM_QSTR (MP_QSTR_connect ), MP_ROM_PTR (& ppp_connect_obj ) },
425
+ { MP_ROM_QSTR (MP_QSTR_disconnect ), MP_ROM_PTR (& ppp_disconnect_obj ) },
392
426
{ MP_ROM_QSTR (MP_QSTR_isconnected ), MP_ROM_PTR (& ppp_isconnected_obj ) },
393
- { MP_ROM_QSTR (MP_QSTR_status ), MP_ROM_PTR (& ppp_status_obj ) },
394
- { MP_ROM_QSTR (MP_QSTR_config ), MP_ROM_PTR (& ppp_config_obj ) },
395
427
{ MP_ROM_QSTR (MP_QSTR_ifconfig ), MP_ROM_PTR (& ppp_ifconfig_obj ) },
396
428
{ MP_ROM_QSTR (MP_QSTR_ipconfig ), MP_ROM_PTR (& ppp_ipconfig_obj ) },
397
- { MP_ROM_QSTR (MP_QSTR___del__ ), MP_ROM_PTR (& ppp_delete_obj ) },
398
- { MP_ROM_QSTR (MP_QSTR_AUTH_NONE ), MP_ROM_INT (PPPAUTHTYPE_NONE ) },
399
- { MP_ROM_QSTR (MP_QSTR_AUTH_PAP ), MP_ROM_INT (PPPAUTHTYPE_PAP ) },
400
- { MP_ROM_QSTR (MP_QSTR_AUTH_CHAP ), MP_ROM_INT (PPPAUTHTYPE_CHAP ) },
429
+ { MP_ROM_QSTR (MP_QSTR_poll ), MP_ROM_PTR (& ppp_poll_obj ) },
430
+
431
+ { MP_ROM_QSTR (MP_QSTR_SEC_NONE ), MP_ROM_INT (PPPAUTHTYPE_NONE ) },
432
+ { MP_ROM_QSTR (MP_QSTR_SEC_PAP ), MP_ROM_INT (PPPAUTHTYPE_PAP ) },
433
+ { MP_ROM_QSTR (MP_QSTR_SEC_CHAP ), MP_ROM_INT (PPPAUTHTYPE_CHAP ) },
401
434
};
402
435
static MP_DEFINE_CONST_DICT (ppp_if_locals_dict , ppp_if_locals_dict_table ) ;
403
436
0 commit comments