Skip to content

Commit eb8b42a

Browse files
committed
Add basic error handling
1 parent 9602ee6 commit eb8b42a

File tree

18 files changed

+194
-48
lines changed

18 files changed

+194
-48
lines changed

ports/esp32s2/bindings/espidf/__init__.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "py/obj.h"
2828
#include "py/runtime.h"
2929

30+
#include "bindings/espidf/__init__.h"
31+
3032
#include "esp-idf/components/heap/include/esp_heap_caps.h"
3133

3234
//| """Direct access to a few ESP-IDF details. This module *should not* include any functionality
@@ -63,12 +65,41 @@ STATIC mp_obj_t espidf_heap_caps_get_largest_free_block(void) {
6365
}
6466
MP_DEFINE_CONST_FUN_OBJ_0(espidf_heap_caps_get_largest_free_block_obj, espidf_heap_caps_get_largest_free_block);
6567

68+
//| class MemoryError(MemoryError):
69+
//| """Raised when an ESP IDF memory allocation fails."""
70+
//| ...
71+
//|
72+
NORETURN void mp_raise_espidf_MemoryError(void) {
73+
nlr_raise(mp_obj_new_exception(&mp_type_espidf_MemoryError));
74+
}
75+
76+
void espidf_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
77+
mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;
78+
bool is_subclass = kind & PRINT_EXC_SUBCLASS;
79+
if (!is_subclass && (k == PRINT_EXC)) {
80+
mp_print_str(print, qstr_str(MP_OBJ_QSTR_VALUE(MP_QSTR_espidf)));
81+
mp_print_str(print, ".");
82+
}
83+
mp_obj_exception_print(print, o_in, kind);
84+
}
85+
86+
const mp_obj_type_t mp_type_espidf_MemoryError = {
87+
{ &mp_type_type },
88+
.name = MP_QSTR_MemoryError,
89+
.print = espidf_exception_print,
90+
.make_new = mp_obj_exception_make_new,
91+
.attr = mp_obj_exception_attr,
92+
.parent = &mp_type_MemoryError,
93+
};
94+
6695
STATIC const mp_rom_map_elem_t espidf_module_globals_table[] = {
6796
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espidf) },
6897

6998
{ MP_ROM_QSTR(MP_QSTR_heap_caps_get_total_size), MP_ROM_PTR(&espidf_heap_caps_get_total_size_obj)},
7099
{ MP_ROM_QSTR(MP_QSTR_heap_caps_get_free_size), MP_ROM_PTR(&espidf_heap_caps_get_free_size_obj)},
71100
{ MP_ROM_QSTR(MP_QSTR_heap_caps_get_largest_free_block), MP_ROM_PTR(&espidf_heap_caps_get_largest_free_block_obj)},
101+
102+
{ MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_espidf_MemoryError) },
72103
};
73104

74105
STATIC MP_DEFINE_CONST_DICT(espidf_module_globals, espidf_module_globals_table);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ESP32S2_BINDINGS_ESPIDF___INIT___H
28+
#define MICROPY_INCLUDED_ESP32S2_BINDINGS_ESPIDF___INIT___H
29+
30+
extern const mp_obj_type_t mp_type_espidf_MemoryError;
31+
32+
NORETURN void mp_raise_espidf_MemoryError(void);
33+
34+
#endif // MICROPY_INCLUDED_ESP32S2_BINDINGS_ESPIDF___INIT___H

ports/esp32s2/common-hal/socketpool/Socket.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
#include "shared-bindings/socketpool/Socket.h"
2828

29+
#include "py/mperrno.h"
30+
#include "py/runtime.h"
31+
2932
void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t* self, mp_uint_t timeout_ms) {
3033
self->timeout_ms = timeout_ms;
3134
}
@@ -40,14 +43,26 @@ bool common_hal_socketpool_socket_connect(socketpool_socket_obj_t* self, const c
4043
tls_config = &self->ssl_context->ssl_config;
4144
}
4245
int result = esp_tls_conn_new_sync(host, hostlen, port, tls_config, self->tcp);
43-
return result >= 0;
46+
self->connected = result >= 0;
47+
if (result < 0) {
48+
int esp_tls_code;
49+
esp_tls_get_and_clear_last_error(self->tcp->error_handle, &esp_tls_code, NULL);
50+
51+
// mp_raise_espidf_MemoryError
52+
mp_raise_OSError_msg_varg(translate("Unhandled ESP TLS error %d"), esp_tls_code);
53+
}
54+
return self->connected;
55+
}
56+
57+
bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t* self) {
58+
return self->connected;
4459
}
4560

4661
mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t* self, const uint8_t* buf, mp_uint_t len) {
4762
size_t sent = esp_tls_conn_write(self->tcp, buf, len);
4863

4964
if (sent < 0) {
50-
// raise an error
65+
mp_raise_OSError(MP_ENOTCONN);
5166
}
5267
return sent;
5368
}
@@ -57,14 +72,18 @@ mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t* self,
5772

5873
if (received == 0) {
5974
// socket closed
75+
common_hal_socketpool_socket_close(self);
6076
}
6177
if (received < 0) {
62-
// raise an error
78+
mp_raise_BrokenPipeError();
6379
}
6480
return received;
6581
}
6682

6783
void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) {
84+
if (self->connected) {
85+
self->connected = false;
86+
}
6887
if (self->tcp != NULL) {
6988
int status = esp_tls_conn_destroy(self->tcp);
7089

@@ -74,3 +93,7 @@ void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) {
7493
self->tcp = NULL;
7594
}
7695
}
96+
97+
bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t* self) {
98+
return self->tcp == NULL;
99+
}

ports/esp32s2/common-hal/socketpool/Socket.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
typedef struct {
3838
mp_obj_base_t base;
3939
int num;
40+
bool connected;
4041
esp_tls_t* tcp;
4142
ssl_sslcontext_obj_t* ssl_context;
4243
socketpool_socketpool_obj_t* pool;

ports/esp32s2/common-hal/socketpool/SocketPool.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,19 @@
2727
#include "shared-bindings/socketpool/SocketPool.h"
2828

2929
#include "py/runtime.h"
30+
#include "shared-bindings/wifi/__init__.h"
3031

3132
#include "esp-idf/components/lwip/lwip/src/include/lwip/netdb.h"
3233

34+
#include "bindings/espidf/__init__.h"
35+
36+
37+
void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t* self, mp_obj_t radio) {
38+
if (radio != MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj)) {
39+
mp_raise_ValueError(translate("SocketPool can only be used with wifi.radio."));
40+
}
41+
}
42+
3343
socketpool_socket_obj_t* common_hal_socketpool_socket(socketpool_socketpool_obj_t* self,
3444
socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type) {
3545

@@ -52,12 +62,21 @@ socketpool_socket_obj_t* common_hal_socketpool_socket(socketpool_socketpool_obj_
5262
socket_type = SOCK_RAW;
5363
}
5464

65+
if (socket_type == SOCK_DGRAM || socket_type == SOCK_RAW ||
66+
addr_family == AF_INET6 || ipproto == IPPROTO_IPV6) {
67+
mp_raise_NotImplementedError(translate("Only IPv4 SOCK_STREAM sockets supported."));
68+
}
69+
5570
int socknum = -1;
5671
esp_tls_t* tcp_handle = NULL;
5772
if (socket_type == SOCK_DGRAM || socket_type == SOCK_RAW) {
58-
socknum = lwip_socket(addr_family, socket_type, ipproto);
73+
// socknum = lwip_socket(addr_family, socket_type, ipproto);
5974
} else {
6075
tcp_handle = esp_tls_init();
76+
77+
if (tcp_handle == NULL) {
78+
mp_raise_espidf_MemoryError();
79+
}
6180
}
6281
if (socknum < 0 && tcp_handle == NULL) {
6382
mp_raise_RuntimeError(translate("Out of sockets"));

py/modbuiltins.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,9 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
726726
{ MP_ROM_QSTR(MP_QSTR_NameError), MP_ROM_PTR(&mp_type_NameError) },
727727
{ MP_ROM_QSTR(MP_QSTR_NotImplementedError), MP_ROM_PTR(&mp_type_NotImplementedError) },
728728
{ MP_ROM_QSTR(MP_QSTR_OSError), MP_ROM_PTR(&mp_type_OSError) },
729+
{ MP_ROM_QSTR(MP_QSTR_TimeoutError), MP_ROM_PTR(&mp_type_TimeoutError) },
730+
{ MP_ROM_QSTR(MP_QSTR_ConnectionError), MP_ROM_PTR(&mp_type_ConnectionError) },
731+
{ MP_ROM_QSTR(MP_QSTR_BrokenPipeError), MP_ROM_PTR(&mp_type_BrokenPipeError) },
729732
{ MP_ROM_QSTR(MP_QSTR_OverflowError), MP_ROM_PTR(&mp_type_OverflowError) },
730733
{ MP_ROM_QSTR(MP_QSTR_RuntimeError), MP_ROM_PTR(&mp_type_RuntimeError) },
731734
#if MICROPY_PY_ASYNC_AWAIT

py/obj.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,8 @@ extern const mp_obj_type_t mp_type_NameError;
604604
extern const mp_obj_type_t mp_type_NotImplementedError;
605605
extern const mp_obj_type_t mp_type_OSError;
606606
extern const mp_obj_type_t mp_type_TimeoutError;
607+
extern const mp_obj_type_t mp_type_ConnectionError;
608+
extern const mp_obj_type_t mp_type_BrokenPipeError;
607609
extern const mp_obj_type_t mp_type_OverflowError;
608610
extern const mp_obj_type_t mp_type_RuntimeError;
609611
extern const mp_obj_type_t mp_type_StopAsyncIteration;

py/objexcept.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,15 +282,17 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
282282
MP_DEFINE_EXCEPTION(UnboundLocalError, NameError)
283283
*/
284284
MP_DEFINE_EXCEPTION(OSError, Exception)
285-
MP_DEFINE_EXCEPTION(TimeoutError, OSError)
286-
/*
287-
MP_DEFINE_EXCEPTION(BlockingIOError, OSError)
288-
MP_DEFINE_EXCEPTION(ChildProcessError, OSError)
285+
MP_DEFINE_EXCEPTION(TimeoutError, OSError)
289286
MP_DEFINE_EXCEPTION(ConnectionError, OSError)
290287
MP_DEFINE_EXCEPTION(BrokenPipeError, ConnectionError)
288+
/*
291289
MP_DEFINE_EXCEPTION(ConnectionAbortedError, ConnectionError)
292290
MP_DEFINE_EXCEPTION(ConnectionRefusedError, ConnectionError)
293291
MP_DEFINE_EXCEPTION(ConnectionResetError, ConnectionError)
292+
*/
293+
/*
294+
MP_DEFINE_EXCEPTION(BlockingIOError, OSError)
295+
MP_DEFINE_EXCEPTION(ChildProcessError, OSError)
294296
MP_DEFINE_EXCEPTION(InterruptedError, OSError)
295297
MP_DEFINE_EXCEPTION(IsADirectoryError, OSError)
296298
MP_DEFINE_EXCEPTION(NotADirectoryError, OSError)

py/runtime.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,6 +1602,10 @@ NORETURN void mp_raise_OSError_msg_varg(const compressed_string_t *fmt, ...) {
16021602
va_end(argptr);
16031603
}
16041604

1605+
NORETURN void mp_raise_BrokenPipeError(void) {
1606+
nlr_raise(mp_obj_new_exception_arg1(&mp_type_BrokenPipeError, MP_OBJ_NEW_SMALL_INT(MP_EPIPE)));
1607+
}
1608+
16051609
NORETURN void mp_raise_NotImplementedError(const compressed_string_t *msg) {
16061610
mp_raise_msg(&mp_type_NotImplementedError, msg);
16071611
}

0 commit comments

Comments
 (0)