From e32d1e17bb7c17b5474c4be696e5428ece973301 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 13 Jul 2016 01:35:59 +0300 Subject: extmod/modussl: Rename to modussl_axtls.c, to allow impl using other SSL libs. --- extmod/modussl.c | 225 ------------------------------------------------- extmod/modussl_axtls.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+), 225 deletions(-) delete mode 100644 extmod/modussl.c create mode 100644 extmod/modussl_axtls.c (limited to 'extmod') diff --git a/extmod/modussl.c b/extmod/modussl.c deleted file mode 100644 index 4a3e297e1..000000000 --- a/extmod/modussl.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/stream.h" - -#if MICROPY_PY_USSL - -#include "ssl.h" - -typedef struct _mp_obj_ssl_socket_t { - mp_obj_base_t base; - mp_obj_t sock; - SSL_CTX *ssl_ctx; - SSL *ssl_sock; - byte *buf; - uint32_t bytes_left; -} mp_obj_ssl_socket_t; - -STATIC const mp_obj_type_t ussl_socket_type; - -STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, bool server_side) { - mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t); - o->base.type = &ussl_socket_type; - o->buf = NULL; - o->bytes_left = 0; - o->sock = sock; - - uint32_t options = SSL_SERVER_VERIFY_LATER; - if ((o->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL))); - } - - if (server_side) { - o->ssl_sock = ssl_server_new(o->ssl_ctx, (long)sock); - } else { - o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0); - - int res; - /* check the return status */ - if ((res = ssl_handshake_status(o->ssl_sock)) != SSL_OK) { - printf("ssl_handshake_status: %d\n", res); - ssl_display_error(res); - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EIO))); - } - } - - return o; -} - -STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "<_SSLSocket %p>", self->ssl_sock); -} - -STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { - mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); - - while (o->bytes_left == 0) { - mp_int_t r = ssl_read(o->ssl_sock, &o->buf); - if (r == SSL_OK) { - // SSL_OK from ssl_read() means "everything is ok, but there's - // not user data yet. So, we just keep reading. - continue; - } - if (r < 0) { - if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) { - // EOF - return 0; - } - *errcode = r; - return MP_STREAM_ERROR; - } - o->bytes_left = r; - } - - if (size > o->bytes_left) { - size = o->bytes_left; - } - memcpy(buf, o->buf, size); - o->buf += size; - o->bytes_left -= size; - return size; -} - -STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { - mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); - mp_int_t r = ssl_write(o->ssl_sock, buf, size); - if (r < 0) { - *errcode = r; - return MP_STREAM_ERROR; - } - return r; -} - -STATIC mp_obj_t socket_close(mp_obj_t self_in) { - mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); - ssl_free(self->ssl_sock); - ssl_ctx_free(self->ssl_ctx); - - mp_obj_t dest[2]; - mp_load_method(self->sock, MP_QSTR_close, dest); - return mp_call_method_n_kw(0, 0, dest); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); - -STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table); - -STATIC const mp_stream_p_t ussl_socket_stream_p = { - .read = socket_read, - .write = socket_write, -}; - -STATIC const mp_obj_type_t ussl_socket_type = { - { &mp_type_type }, - // Save on qstr's, reuse same as for module - .name = MP_QSTR_ussl, - .print = socket_print, - .getiter = NULL, - .iternext = NULL, - .protocol = &ussl_socket_stream_p, - .locals_dict = (void*)&ussl_socket_locals_dict, -}; - -STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - // TODO: Implement more args - static const mp_arg_t allowed_args[] = { - { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - }; - - // TODO: Check that sock implements stream protocol - mp_obj_t sock = pos_args[0]; - - struct { - mp_arg_val_t server_side; - } args; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, - MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); - - return MP_OBJ_FROM_PTR(socket_new(sock, args.server_side.u_bool)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket); - -STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) }, - { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table); - -const mp_obj_module_t mp_module_ussl = { - .base = { &mp_type_module }, - .name = MP_QSTR_ussl, - .globals = (mp_obj_dict_t*)&mp_module_ssl_globals, -}; - - -// These functions might be split to stream_posix.c. They are referenced by -// axtls os_port.h . -ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len); -ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len); - -int mp_stream_errno; - -ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len) { - struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj; - const mp_stream_p_t *stream_p = o->type->protocol; - mp_uint_t out_sz = stream_p->write(o, buf, len, &mp_stream_errno); - if (out_sz == MP_STREAM_ERROR) { - return -1; - } else { - return out_sz; - } -} - -ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len) { - struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj; - const mp_stream_p_t *stream_p = o->type->protocol; - mp_uint_t out_sz = stream_p->read(o, buf, len, &mp_stream_errno); - if (out_sz == MP_STREAM_ERROR) { - return -1; - } else { - return out_sz; - } -} - -#endif // MICROPY_PY_USSL diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c new file mode 100644 index 000000000..4a3e297e1 --- /dev/null +++ b/extmod/modussl_axtls.c @@ -0,0 +1,225 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Paul Sokolovsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/stream.h" + +#if MICROPY_PY_USSL + +#include "ssl.h" + +typedef struct _mp_obj_ssl_socket_t { + mp_obj_base_t base; + mp_obj_t sock; + SSL_CTX *ssl_ctx; + SSL *ssl_sock; + byte *buf; + uint32_t bytes_left; +} mp_obj_ssl_socket_t; + +STATIC const mp_obj_type_t ussl_socket_type; + +STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, bool server_side) { + mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t); + o->base.type = &ussl_socket_type; + o->buf = NULL; + o->bytes_left = 0; + o->sock = sock; + + uint32_t options = SSL_SERVER_VERIFY_LATER; + if ((o->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL))); + } + + if (server_side) { + o->ssl_sock = ssl_server_new(o->ssl_ctx, (long)sock); + } else { + o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0); + + int res; + /* check the return status */ + if ((res = ssl_handshake_status(o->ssl_sock)) != SSL_OK) { + printf("ssl_handshake_status: %d\n", res); + ssl_display_error(res); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EIO))); + } + } + + return o; +} + +STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)kind; + mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "<_SSLSocket %p>", self->ssl_sock); +} + +STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { + mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); + + while (o->bytes_left == 0) { + mp_int_t r = ssl_read(o->ssl_sock, &o->buf); + if (r == SSL_OK) { + // SSL_OK from ssl_read() means "everything is ok, but there's + // not user data yet. So, we just keep reading. + continue; + } + if (r < 0) { + if (r == SSL_CLOSE_NOTIFY || r == SSL_ERROR_CONN_LOST) { + // EOF + return 0; + } + *errcode = r; + return MP_STREAM_ERROR; + } + o->bytes_left = r; + } + + if (size > o->bytes_left) { + size = o->bytes_left; + } + memcpy(buf, o->buf, size); + o->buf += size; + o->bytes_left -= size; + return size; +} + +STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { + mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in); + mp_int_t r = ssl_write(o->ssl_sock, buf, size); + if (r < 0) { + *errcode = r; + return MP_STREAM_ERROR; + } + return r; +} + +STATIC mp_obj_t socket_close(mp_obj_t self_in) { + mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); + ssl_free(self->ssl_sock); + ssl_ctx_free(self->ssl_ctx); + + mp_obj_t dest[2]; + mp_load_method(self->sock, MP_QSTR_close, dest); + return mp_call_method_n_kw(0, 0, dest); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); + +STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table); + +STATIC const mp_stream_p_t ussl_socket_stream_p = { + .read = socket_read, + .write = socket_write, +}; + +STATIC const mp_obj_type_t ussl_socket_type = { + { &mp_type_type }, + // Save on qstr's, reuse same as for module + .name = MP_QSTR_ussl, + .print = socket_print, + .getiter = NULL, + .iternext = NULL, + .protocol = &ussl_socket_stream_p, + .locals_dict = (void*)&ussl_socket_locals_dict, +}; + +STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + // TODO: Implement more args + static const mp_arg_t allowed_args[] = { + { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + + // TODO: Check that sock implements stream protocol + mp_obj_t sock = pos_args[0]; + + struct { + mp_arg_val_t server_side; + } args; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); + + return MP_OBJ_FROM_PTR(socket_new(sock, args.server_side.u_bool)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket); + +STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) }, + { MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table); + +const mp_obj_module_t mp_module_ussl = { + .base = { &mp_type_module }, + .name = MP_QSTR_ussl, + .globals = (mp_obj_dict_t*)&mp_module_ssl_globals, +}; + + +// These functions might be split to stream_posix.c. They are referenced by +// axtls os_port.h . +ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len); +ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len); + +int mp_stream_errno; + +ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len) { + struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->write(o, buf, len, &mp_stream_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len) { + struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj; + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->read(o, buf, len, &mp_stream_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +#endif // MICROPY_PY_USSL -- cgit v1.2.3 From 20283aec107d60f4339268f56fdf451d8867b49a Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Wed, 13 Jul 2016 01:49:38 +0300 Subject: extmod/modussl_axtls: Further changes to allow alternative SSL modules. Make variable MICROPY_SSL_AXTLS=1 should be defined to activate modussl_axtls and link with -laxtls. --- extmod/modussl_axtls.c | 2 +- py/py.mk | 5 ++++- unix/mpconfigport.h | 2 +- unix/mpconfigport.mk | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) (limited to 'extmod') diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 4a3e297e1..9e30ce6f8 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -32,7 +32,7 @@ #include "py/runtime.h" #include "py/stream.h" -#if MICROPY_PY_USSL +#if MICROPY_PY_USSL && MICROPY_SSL_AXTLS #include "ssl.h" diff --git a/py/py.mk b/py/py.mk index bc0fa4238..1a3bfb942 100644 --- a/py/py.mk +++ b/py/py.mk @@ -20,9 +20,12 @@ INC += -I../lib INC += -I../lib/netutils ifeq ($(MICROPY_PY_USSL),1) -CFLAGS_MOD += -DMICROPY_PY_USSL=1 -I../lib/axtls/ssl -I../lib/axtls/crypto -I../lib/axtls/config +CFLAGS_MOD += -DMICROPY_PY_USSL=1 +ifeq ($(MICROPY_SSL_AXTLS),1) +CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I../lib/axtls/ssl -I../lib/axtls/crypto -I../lib/axtls/config LDFLAGS_MOD += -L../lib/axtls/_stage -laxtls endif +endif #ifeq ($(MICROPY_PY_LWIP),1) #CFLAGS_MOD += -DMICROPY_PY_LWIP=1 -I../lib/lwip/src/include -I../lib/lwip/src/include/ipv4 -I../extmod/lwip-include diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index 06c4edc1e..30441c9fd 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -111,7 +111,7 @@ #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UHASHLIB (1) -#if MICROPY_PY_USSL +#if MICROPY_PY_USSL && MICROPY_SSL_AXTLS #define MICROPY_PY_UHASHLIB_SHA1 (1) #endif #define MICROPY_PY_UBINASCII (1) diff --git a/unix/mpconfigport.mk b/unix/mpconfigport.mk index 9f826661a..f7912141a 100644 --- a/unix/mpconfigport.mk +++ b/unix/mpconfigport.mk @@ -28,6 +28,7 @@ MICROPY_PY_FFI = 1 # ussl module requires axtls MICROPY_PY_USSL = 1 +MICROPY_SSL_AXTLS = 1 # jni module requires JVM/JNI MICROPY_PY_JNI = 0 -- cgit v1.2.3 From 780114e398ccaf7909b0b94120e986410f156c87 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 15 Jul 2016 01:05:06 +0300 Subject: extmod/modussl_axtls: Add dummy setblocking() method. Accepts only value of True. --- extmod/modussl_axtls.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'extmod') diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 9e30ce6f8..a965f4f7c 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -122,6 +122,16 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in return r; } +STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { + // Currently supports only blocking mode + (void)self_in; + if (!mp_obj_is_true(flag_in)) { + mp_not_implemented(""); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); + STATIC mp_obj_t socket_close(mp_obj_t self_in) { mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); ssl_free(self->ssl_sock); @@ -139,6 +149,7 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) }, }; -- cgit v1.2.3 From 0a6f599cf2e3930cf0ad49305d0dad03c3891788 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 16 Jul 2016 03:46:42 +0300 Subject: extmod/vfs_fat: Implement rmdir() method. Shares the code with remove() method due to the same underlying f_unlink() FatFs operation. --- extmod/vfs_fat.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'extmod') diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index df5cbb0d6..a691ee062 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -90,6 +90,14 @@ STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove); +STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) { + // TODO: Currently just redirects to fat_vfs_remove(), which are + // backed by the same underlying FatFs function. Should at least + // check that path is actually a dir. + return fat_vfs_remove(vfs_in, path_in); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir); + STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) { (void)vfs_in; const char *old_path = mp_obj_str_get_str(path_in); @@ -247,6 +255,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&fat_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) }, -- cgit v1.2.3 From a53e0e59f303eddbeda96a04df272837308c2f33 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 23 Jul 2016 00:38:56 +0300 Subject: extmod/modussl_axtls: Use mp_stream_close() method. --- extmod/modussl_axtls.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'extmod') diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index a965f4f7c..2ef122fa6 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -136,10 +136,7 @@ STATIC mp_obj_t socket_close(mp_obj_t self_in) { mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); ssl_free(self->ssl_sock); ssl_ctx_free(self->ssl_ctx); - - mp_obj_t dest[2]; - mp_load_method(self->sock, MP_QSTR_close, dest); - return mp_call_method_n_kw(0, 0, dest); + return mp_stream_close(self->sock); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); -- cgit v1.2.3 From 2dd21d9a68ef90bd42fa355a744dde89031611c1 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 23 Jul 2016 00:52:35 +0300 Subject: extmod/modwebrepl: Use mp_stream_close() method. --- extmod/modwebrepl.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'extmod') diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 4f7b924e0..67734bd66 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -77,12 +77,6 @@ STATIC char denied_prompt[] = "\r\nAccess denied\r\n"; STATIC char webrepl_passwd[10]; -static inline void close_meth(mp_obj_t stream) { - mp_obj_t dest[2]; - mp_load_method(stream, MP_QSTR_close, dest); - mp_call_method_n_kw(0, 0, dest); -} - STATIC void write_webrepl(mp_obj_t websock, const void *buf, size_t len) { const mp_stream_p_t *sock_stream = mp_get_stream_raise(websock, MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); int err; @@ -256,7 +250,7 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int } if (self->data_to_recv == 0) { - close_meth(self->cur_file); + mp_stream_close(self->cur_file); self->hdr_to_recv = sizeof(struct webrepl_file); DEBUG_printf("webrepl: Finished writing file\n"); write_webrepl_resp(self->sock, 0); -- cgit v1.2.3 From 25df419c6703396e7e817bf6c8bb443f6c941e5d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 24 Jul 2016 00:29:32 +0300 Subject: extmod/modbtree: Check __bt_open() return value for error. --- extmod/modbtree.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'extmod') diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 0a0c5271c..6613c06c8 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -331,6 +331,9 @@ STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); DB *db = __bt_open(fname, /*flags*/O_CREAT | O_RDWR, /*mode*/0770, /*openinfo*/NULL, /*dflags*/0); + if (db == NULL) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno))); + } return MP_OBJ_FROM_PTR(btree_new(db)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_btree_open_obj, 1, mod_btree_open); -- cgit v1.2.3 From 4f1b0292dbc5920457673a31cadfd894239cc1b9 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 30 Jul 2016 00:25:06 +0300 Subject: py/stream: Add adapter methods with POSIX-compatible signatures. Previoussly such read() and write() methods were used by modussl_axtls, move to py/stream for reuse. --- extmod/modussl_axtls.c | 30 -------------------------- py/stream.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ py/stream.h | 6 ++++++ 3 files changed, 64 insertions(+), 30 deletions(-) (limited to 'extmod') diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index 2ef122fa6..ce86263c2 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -200,34 +200,4 @@ const mp_obj_module_t mp_module_ussl = { .globals = (mp_obj_dict_t*)&mp_module_ssl_globals, }; - -// These functions might be split to stream_posix.c. They are referenced by -// axtls os_port.h . -ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len); -ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len); - -int mp_stream_errno; - -ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len) { - struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj; - const mp_stream_p_t *stream_p = o->type->protocol; - mp_uint_t out_sz = stream_p->write(o, buf, len, &mp_stream_errno); - if (out_sz == MP_STREAM_ERROR) { - return -1; - } else { - return out_sz; - } -} - -ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len) { - struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj; - const mp_stream_p_t *stream_p = o->type->protocol; - mp_uint_t out_sz = stream_p->read(o, buf, len, &mp_stream_errno); - if (out_sz == MP_STREAM_ERROR) { - return -1; - } else { - return out_sz; - } -} - #endif // MICROPY_PY_USSL diff --git a/py/stream.c b/py/stream.c index 0511ef32c..d426973e8 100644 --- a/py/stream.c +++ b/py/stream.c @@ -510,3 +510,61 @@ STATIC mp_obj_t stream_ioctl(size_t n_args, const mp_obj_t *args) { return mp_obj_new_int(res); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj, 2, 3, stream_ioctl); + +/* + * POSIX-like functions + * + * These functions have POSIX-compatible signature (except for "void *stream" + * first argument instead of "int fd"). They are useful to port existing + * POSIX-compatible software to work with MicroPython streams. + */ + + +// errno-like variable. If any of the functions below returned with error +// status, this variable will contain error no. +int mp_stream_errno; + +ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) { + mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->write(stream, buf, len, &mp_stream_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) { + mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t out_sz = stream_p->read(stream, buf, len, &mp_stream_errno); + if (out_sz == MP_STREAM_ERROR) { + return -1; + } else { + return out_sz; + } +} + +off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) { + const mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); + const mp_stream_p_t *stream_p = o->type->protocol; + struct mp_stream_seek_t seek_s; + seek_s.offset = offset; + seek_s.whence = whence; + mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &mp_stream_errno); + if (res == MP_STREAM_ERROR) { + return -1; + } + return seek_s.offset; +} + +int mp_stream_posix_fsync(mp_obj_t stream) { + mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); + const mp_stream_p_t *stream_p = o->type->protocol; + mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_FLUSH, 0, &mp_stream_errno); + if (res == MP_STREAM_ERROR) { + return -1; + } + return res; +} diff --git a/py/stream.h b/py/stream.h index d1074986a..8dd689887 100644 --- a/py/stream.h +++ b/py/stream.h @@ -84,6 +84,12 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf, mp_uint_t size, int *errcode, void mp_stream_write_adaptor(void *self, const char *buf, size_t len); +// Functions with POSIX-compatible signatures +ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len); +ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len); +off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence); +int mp_stream_posix_fsync(mp_obj_t stream); + #if MICROPY_STREAMS_NON_BLOCK #define mp_is_nonblocking_error(errno) ((errno) == EAGAIN || (errno) == EWOULDBLOCK) #else -- cgit v1.2.3 From 99061d1dcb92dcff87b8a32be3e308a37fe4c13a Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 31 Jul 2016 00:40:35 +0300 Subject: extmod/modbtree: Switch to accepting stream object instead of filename. Requires "embedded" BerkeleyDB BTree implementation. --- extmod/modbtree.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'extmod') diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 6613c06c8..4c58d17d3 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -31,6 +31,7 @@ #include "py/nlr.h" #include "py/runtime.h" +#include "py/stream.h" #if MICROPY_PY_BTREE @@ -314,15 +315,20 @@ STATIC const mp_obj_type_t btree_type = { .locals_dict = (void*)&btree_locals_dict, }; +STATIC FILEVTABLE btree_stream_fvtable = { + mp_stream_posix_read, + mp_stream_posix_write, + mp_stream_posix_lseek, + mp_stream_posix_fsync +}; + STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; - const char *fname = NULL; - if (pos_args[0] != mp_const_none) { - fname = mp_obj_str_get_str(pos_args[0]); - } + // Make sure we got a stream object + mp_get_stream_raise(pos_args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); struct { mp_arg_val_t server_side; @@ -330,7 +336,7 @@ STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); - DB *db = __bt_open(fname, /*flags*/O_CREAT | O_RDWR, /*mode*/0770, /*openinfo*/NULL, /*dflags*/0); + DB *db = __bt_open(pos_args[0], &btree_stream_fvtable, /*openinfo*/NULL, /*dflags*/0); if (db == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno))); } -- cgit v1.2.3 From 3eb532e97463b7f9b9ffe6f617a035284ef3e37b Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 2 Aug 2016 00:21:05 +0300 Subject: extmod/modbtree: Implement __contains__ operation. --- extmod/modbtree.c | 20 ++++++++++++++++++++ tests/extmod/btree1.py | 3 +++ tests/extmod/btree1.py.exp | 2 ++ 3 files changed, 25 insertions(+) (limited to 'extmod') diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 4c58d17d3..3fec52fa5 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -31,6 +31,7 @@ #include "py/nlr.h" #include "py/runtime.h" +#include "py/runtime0.h" #include "py/stream.h" #if MICROPY_PY_BTREE @@ -292,6 +293,24 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } +STATIC mp_obj_t btree_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { + mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in); + switch (op) { + case MP_BINARY_OP_IN: { + mp_uint_t v; + DBT key, val; + key.data = (void*)mp_obj_str_get_data(rhs_in, &v); + key.size = v; + int res = __bt_get(self->db, &key, &val, 0); + CHECK_ERROR(res); + return mp_obj_new_bool(res != RET_SPECIAL); + } + default: + // op not supported + return MP_OBJ_NULL; + } +} + STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&btree_close_obj) }, { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&btree_get_obj) }, @@ -311,6 +330,7 @@ STATIC const mp_obj_type_t btree_type = { .print = btree_print, .getiter = btree_getiter, .iternext = btree_iternext, + .binary_op = btree_binary_op, .subscr = btree_subscr, .locals_dict = (void*)&btree_locals_dict, }; diff --git a/tests/extmod/btree1.py b/tests/extmod/btree1.py index 54c3dc794..c96cce92d 100644 --- a/tests/extmod/btree1.py +++ b/tests/extmod/btree1.py @@ -62,5 +62,8 @@ print(list(db.values())) for k in db: print(k) +print("foo1", "foo1" in db) +print("foo2", "foo2" in db) + db.close() f.close() diff --git a/tests/extmod/btree1.py.exp b/tests/extmod/btree1.py.exp index a266d7acf..2983a0987 100644 --- a/tests/extmod/btree1.py.exp +++ b/tests/extmod/btree1.py.exp @@ -30,3 +30,5 @@ KeyError b'bar1' b'foo1' b'foo3' +foo1 True +foo2 False -- cgit v1.2.3 From c16612ee87e2f3c58ef26031dc04b689da772c51 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 5 Aug 2016 22:53:10 +0300 Subject: extmod/modwebrepl: Factor out "GET" iteration to write_file_chunk(). --- extmod/modwebrepl.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'extmod') diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 67734bd66..32edb6e6b 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -111,6 +111,22 @@ STATIC mp_obj_t webrepl_make_new(const mp_obj_type_t *type, size_t n_args, size_ return o; } +STATIC int write_file_chunk(mp_obj_webrepl_t *self) { + const mp_stream_p_t *file_stream = + mp_get_stream_raise(self->cur_file, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); + byte readbuf[2 + 256]; + int err; + mp_uint_t out_sz = file_stream->read(self->cur_file, readbuf + 2, sizeof(readbuf) - 2, &err); + if (out_sz == MP_STREAM_ERROR) { + return out_sz; + } + readbuf[0] = out_sz; + readbuf[1] = out_sz >> 8; + DEBUG_printf("webrepl: Sending %d bytes of file\n", out_sz); + write_webrepl(self->sock, readbuf, 2 + out_sz); + return out_sz; +} + STATIC void handle_op(mp_obj_webrepl_t *self) { mp_obj_t open_args[2] = { mp_obj_new_str(self->hdr.fname, strlen(self->hdr.fname), false), @@ -122,8 +138,6 @@ STATIC void handle_op(mp_obj_webrepl_t *self) { } self->cur_file = mp_builtin_open(2, open_args, (mp_map_t*)&mp_const_empty_map); - const mp_stream_p_t *file_stream = - mp_get_stream_raise(self->cur_file, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); #if 0 struct mp_stream_seek_t seek = { .offset = self->hdr.offset, .whence = 0 }; @@ -137,17 +151,11 @@ STATIC void handle_op(mp_obj_webrepl_t *self) { if (self->hdr.type == PUT_FILE) { self->data_to_recv = self->hdr.size; } else if (self->hdr.type == GET_FILE) { - byte readbuf[2 + 256]; - int err; // TODO: It's not ideal that we block connection while sending file // and don't process any input. while (1) { - mp_uint_t out_sz = file_stream->read(self->cur_file, readbuf + 2, sizeof(readbuf) - 2, &err); + mp_uint_t out_sz = write_file_chunk(self); assert(out_sz != MP_STREAM_ERROR); - readbuf[0] = out_sz; - readbuf[1] = out_sz >> 8; - DEBUG_printf("webrepl: Sending %d bytes of file\n", out_sz); - write_webrepl(self->sock, readbuf, 2 + out_sz); if (out_sz == 0) { break; } -- cgit v1.2.3 From ed500e49878292c87cd68b8fcfd842f70201eb2d Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Fri, 5 Aug 2016 22:57:50 +0300 Subject: extmod/modwebrepl: Make GET_FILE operation non-blocking. In the sense that while GET_FILE transfers its data, REPL still works. This is done by requiring client to send 1-byte block before WebREPL server transfers next block of data. --- extmod/modwebrepl.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'extmod') diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 32edb6e6b..6820bbab4 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -151,18 +151,7 @@ STATIC void handle_op(mp_obj_webrepl_t *self) { if (self->hdr.type == PUT_FILE) { self->data_to_recv = self->hdr.size; } else if (self->hdr.type == GET_FILE) { - // TODO: It's not ideal that we block connection while sending file - // and don't process any input. - while (1) { - mp_uint_t out_sz = write_file_chunk(self); - assert(out_sz != MP_STREAM_ERROR); - if (out_sz == 0) { - break; - } - } - - write_webrepl_resp(self->sock, 0); - self->hdr_to_recv = sizeof(struct webrepl_file); + self->data_to_recv = 1; } } @@ -250,17 +239,27 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int buf_sz += sz; } - DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz); - int err; - mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err); - if (err != 0 || res != buf_sz) { - assert(0); + if (self->hdr.type == PUT_FILE) { + DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz); + int err; + mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err); + if (err != 0 || res != buf_sz) { + assert(0); + } + } else if (self->hdr.type == GET_FILE) { + assert(buf_sz == 1); + assert(self->data_to_recv == 0); + assert(filebuf[0] == 0); + mp_uint_t out_sz = write_file_chunk(self); + if (out_sz != 0) { + self->data_to_recv = 1; + } } if (self->data_to_recv == 0) { mp_stream_close(self->cur_file); self->hdr_to_recv = sizeof(struct webrepl_file); - DEBUG_printf("webrepl: Finished writing file\n"); + DEBUG_printf("webrepl: Finished file operation %d\n", self->hdr.type); write_webrepl_resp(self->sock, 0); } -- cgit v1.2.3 From d79342d33e4cf7232763a7154fb8bf9273cb4b32 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 6 Aug 2016 00:10:22 +0300 Subject: extmod/modbtree: open(): Add option kwargs. Namely: flags, cachesize, pagesize, minkeypage. --- extmod/modbtree.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'extmod') diff --git a/extmod/modbtree.c b/extmod/modbtree.c index 3fec52fa5..f21e7e442 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -344,19 +344,30 @@ STATIC FILEVTABLE btree_stream_fvtable = { STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { - { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_cachesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_pagesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_minkeypage, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; // Make sure we got a stream object mp_get_stream_raise(pos_args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); struct { - mp_arg_val_t server_side; + mp_arg_val_t flags; + mp_arg_val_t cachesize; + mp_arg_val_t pagesize; + mp_arg_val_t minkeypage; } args; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); + BTREEINFO openinfo = {0}; + openinfo.flags = args.flags.u_int; + openinfo.cachesize = args.cachesize.u_int; + openinfo.psize = args.pagesize.u_int; + openinfo.minkeypage = args.minkeypage.u_int; - DB *db = __bt_open(pos_args[0], &btree_stream_fvtable, /*openinfo*/NULL, /*dflags*/0); + DB *db = __bt_open(pos_args[0], &btree_stream_fvtable, &openinfo, /*dflags*/0); if (db == NULL) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno))); } -- cgit v1.2.3 From a931c4eeecda56139e2aabb71799bc58fd3ae287 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 6 Aug 2016 15:13:26 +0300 Subject: extmod/modwebsocket: Add readline method. This goes bit against websocket nature (message-based communication), as it ignores boundaries bertween messages, but may be very practical to do simple things with websockets. --- extmod/modwebsocket.c | 1 + 1 file changed, 1 insertion(+) (limited to 'extmod') diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c index 6354633af..c7c698c99 100644 --- a/extmod/modwebsocket.c +++ b/extmod/modwebsocket.c @@ -283,6 +283,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(websocket_close_obj, websocket_close); STATIC const mp_map_elem_t websocket_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&mp_stream_ioctl_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&websocket_close_obj }, -- cgit v1.2.3 From e0d49b7e1bea90e742e6db81ec91903fd8755c3c Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 6 Aug 2016 15:53:16 +0300 Subject: extmod/modwebsocket: Make compatible with non-default object models. --- extmod/modwebsocket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'extmod') diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c index c7c698c99..a4d5ae274 100644 --- a/extmod/modwebsocket.c +++ b/extmod/modwebsocket.c @@ -73,11 +73,11 @@ STATIC mp_obj_t websocket_make_new(const mp_obj_type_t *type, size_t n_args, siz if (n_args > 1 && args[1] == mp_const_true) { o->opts |= BLOCKING_WRITE; } - return o; + return MP_OBJ_FROM_PTR(o); } STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { - mp_obj_websocket_t *self = self_in; + mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in); const mp_stream_p_t *stream_p = mp_get_stream_raise(self->sock, MP_STREAM_OP_READ); while (1) { if (self->to_recv != 0) { @@ -219,7 +219,7 @@ no_payload: } STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { - mp_obj_websocket_t *self = self_in; + mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in); assert(size < 0x10000); byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)}; int hdr_sz; -- cgit v1.2.3 From cbef0dba2eef29757237dfe4bca3d21e6a81a0ba Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sat, 6 Aug 2016 16:18:03 +0300 Subject: extmod/modwebsocket: Use mp_rom_map_elem_t and friends. --- extmod/modwebsocket.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'extmod') diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c index a4d5ae274..f46dac177 100644 --- a/extmod/modwebsocket.c +++ b/extmod/modwebsocket.c @@ -280,13 +280,13 @@ STATIC mp_obj_t websocket_close(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(websocket_close_obj, websocket_close); -STATIC const mp_map_elem_t websocket_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&mp_stream_ioctl_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&websocket_close_obj }, +STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&websocket_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table); @@ -301,12 +301,12 @@ STATIC const mp_obj_type_t websocket_type = { .name = MP_QSTR_websocket, .make_new = websocket_make_new, .protocol = &websocket_stream_p, - .locals_dict = (mp_obj_t)&websocket_locals_dict, + .locals_dict = (void*)&websocket_locals_dict, }; -STATIC const mp_map_elem_t websocket_module_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_websocket) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_websocket), (mp_obj_t)&websocket_type }, +STATIC const mp_rom_map_elem_t websocket_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_websocket) }, + { MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&websocket_type) }, }; STATIC MP_DEFINE_CONST_DICT(websocket_module_globals, websocket_module_globals_table); -- cgit v1.2.3 From e15fb33e109983ced35f14c674e0aa1d47dbc357 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Sun, 7 Aug 2016 00:01:25 +0300 Subject: extmod/modwebrepl: Add GET_VER operation to query MicroPython version. --- extmod/modwebrepl.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'extmod') diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 6820bbab4..4e3780fa4 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -38,6 +38,7 @@ #include "py/mphal.h" #endif #include "extmod/modwebsocket.h" +#include "genhdr/mpversion.h" #if MICROPY_PY_WEBREPL @@ -57,7 +58,7 @@ struct webrepl_file { char fname[64]; } __attribute__((packed)); -enum { PUT_FILE = 1, GET_FILE, LIST_DIR }; +enum { PUT_FILE = 1, GET_FILE, GET_VER }; enum { STATE_PASSWD, STATE_NORMAL }; typedef struct _mp_obj_webrepl_t { @@ -128,6 +129,20 @@ STATIC int write_file_chunk(mp_obj_webrepl_t *self) { } STATIC void handle_op(mp_obj_webrepl_t *self) { + + // Handle operations not requiring opened file + + switch (self->hdr.type) { + case GET_VER: { + static char ver[] = {MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO}; + write_webrepl(self->sock, ver, sizeof(ver)); + self->hdr_to_recv = sizeof(struct webrepl_file); + return; + } + } + + // Handle operations requiring opened file + mp_obj_t open_args[2] = { mp_obj_new_str(self->hdr.fname, strlen(self->hdr.fname), false), MP_OBJ_NEW_QSTR(MP_QSTR_rb) -- cgit v1.2.3