From 9a65fa304c151f796ecfd040b0744ed7cdc88537 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 11 Jun 2015 20:26:24 +0200 Subject: [PATCH] cc3200: Add modussl, ssl sockets subclassed from normal sockets. Stream methods were added to normal sockets as in the unix port. --- cc3200/application.mk | 1 + cc3200/mods/modnetwork.h | 13 +++- cc3200/mods/moduhashlib.h | 32 -------- cc3200/mods/modusocket.c | 107 +++++++++++++++++---------- cc3200/mods/modusocket.h | 3 + cc3200/mods/modussl.c | 149 ++++++++++++++++++++++++++++++++++++++ cc3200/mods/modwlan.c | 61 +++++++--------- cc3200/mods/modwlan.h | 2 +- cc3200/mpconfigport.h | 3 + cc3200/qstrdefsport.h | 15 ++++ 10 files changed, 276 insertions(+), 110 deletions(-) delete mode 100644 cc3200/mods/moduhashlib.h create mode 100644 cc3200/mods/modussl.c diff --git a/cc3200/application.mk b/cc3200/application.mk index 0ac98bf5f2..cfb90d6ffa 100644 --- a/cc3200/application.mk +++ b/cc3200/application.mk @@ -92,6 +92,7 @@ APP_MODS_SRC_C = $(addprefix mods/,\ modpyb.c \ moduos.c \ modusocket.c \ + modussl.c \ modutime.c \ modwlan.c \ pybadc.c \ diff --git a/cc3200/mods/modnetwork.h b/cc3200/mods/modnetwork.h index af9bdb6ef6..59034847b9 100644 --- a/cc3200/mods/modnetwork.h +++ b/cc3200/mods/modnetwork.h @@ -40,8 +40,7 @@ typedef struct _mod_network_nic_type_t { mp_obj_type_t base; } mod_network_nic_type_t; -typedef struct _mod_network_socket_obj_t { - mp_obj_base_t base; +typedef struct _mod_network_socket_base_t { union { struct { uint8_t domain; @@ -51,8 +50,14 @@ typedef struct _mod_network_socket_obj_t { } u_param; int16_t sd; }; - bool closed; - bool has_timeout; + bool has_timeout; + bool cert_req; + bool closed; +} mod_network_socket_base_t; + +typedef struct _mod_network_socket_obj_t { + mp_obj_base_t base; + mod_network_socket_base_t sock_base; } mod_network_socket_obj_t; /****************************************************************************** diff --git a/cc3200/mods/moduhashlib.h b/cc3200/mods/moduhashlib.h deleted file mode 100644 index d89d9f001c..0000000000 --- a/cc3200/mods/moduhashlib.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014 Paul Sokolovsky - * Copyright (c) 2015 Daniel Campora - * - * 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. - */ -#ifndef MODUHASHLIB_H_ -#define MODUHASHLIB_H_ - -extern const mp_obj_module_t mp_module_uhashlib; - -#endif // MODUHASHLIB_H_ diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c index 57822e0ebc..e4211003cc 100644 --- a/cc3200/mods/modusocket.c +++ b/cc3200/mods/modusocket.c @@ -29,9 +29,12 @@ #include #include "simplelink.h" -#include "py/mpstate.h" +#include "py/mpconfig.h" #include MICROPY_HAL_H +#include "py/obj.h" +#include "py/objstr.h" #include "py/runtime.h" +#include "py/stream.h" #include "netutils.h" #include "modnetwork.h" #include "modwlan.h" @@ -54,6 +57,7 @@ typedef struct { /****************************************************************************** DEFINE PRIVATE DATA ******************************************************************************/ +STATIC const mp_obj_type_t socket_type; STATIC OsiLockObj_t modusocket_LockObj; STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}}; @@ -121,8 +125,6 @@ void modusocket_close_all_user_sockets (void) { /******************************************************************************/ // socket class -STATIC const mp_obj_type_t socket_type; - // constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None) STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 4, false); @@ -130,18 +132,22 @@ STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_ // create socket object mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t); s->base.type = (mp_obj_t)&socket_type; - s->u_param.domain = AF_INET; - s->u_param.type = SOCK_STREAM; - s->u_param.proto = IPPROTO_TCP; - s->u_param.fileno = -1; + s->sock_base.u_param.domain = AF_INET; + s->sock_base.u_param.type = SOCK_STREAM; + s->sock_base.u_param.proto = IPPROTO_TCP; + s->sock_base.u_param.fileno = -1; + s->sock_base.has_timeout = false; + s->sock_base.cert_req = false; + s->sock_base.closed = false; + if (n_args > 0) { - s->u_param.domain = mp_obj_get_int(args[0]); + s->sock_base.u_param.domain = mp_obj_get_int(args[0]); if (n_args > 1) { - s->u_param.type = mp_obj_get_int(args[1]); + s->sock_base.u_param.type = mp_obj_get_int(args[1]); if (n_args > 2) { - s->u_param.proto = mp_obj_get_int(args[2]); + s->sock_base.u_param.proto = mp_obj_get_int(args[2]); if (n_args > 3) { - s->u_param.fileno = mp_obj_get_int(args[3]); + s->sock_base.u_param.fileno = mp_obj_get_int(args[3]); } } } @@ -153,8 +159,6 @@ STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_ nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } - s->has_timeout = false; - modusocket_socket_add(s->sd, true); return s; } @@ -201,9 +205,10 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { // create new socket object mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); - socket2->base.type = (mp_obj_t)&socket_type; + // the new socket inherits all properties from its parent + memcpy (socket2, self, sizeof(mod_network_socket_obj_t)); - // accept incoming connection + // accept the incoming connection uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; mp_uint_t port; int _errno; @@ -212,7 +217,7 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { } // add the socket to the list - modusocket_socket_add(socket2->sd, true); + modusocket_socket_add(socket2->sock_base.sd, true); // make the return value mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); @@ -230,9 +235,12 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE); - // call the NIC to connect the socket + // connect the socket int _errno; if (wlan_socket_connect(self, ip, port, &_errno) != 0) { + if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) { + return mp_const_none; + } nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } return mp_const_none; @@ -246,7 +254,7 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); int _errno; mp_uint_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno); - if (ret == -1) { + if (ret < 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } return mp_obj_new_int_from_uint(ret); @@ -261,8 +269,8 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { vstr_init_len(&vstr, len); int _errno; mp_uint_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno); - if (ret == -1) { - if (_errno == EAGAIN && self->has_timeout) { + if (ret < 0) { + if (_errno == EAGAIN && self->sock_base.has_timeout) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out")); } nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); @@ -291,7 +299,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ // call the nic to sendto int _errno; mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); - if (ret == -1) { + if (ret < 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } return mp_obj_new_int(ret); @@ -307,8 +315,8 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { mp_uint_t port; int _errno; mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); - if (ret == -1) { - if (_errno == EAGAIN && self->has_timeout) { + if (ret < 0) { + if (_errno == EAGAIN && self->sock_base.has_timeout) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out")); } nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); @@ -386,29 +394,48 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); STATIC const mp_map_elem_t socket_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj }, + + // stream methods + { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_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 }, }; -STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); +MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); -mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { +STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { + mod_network_socket_obj_t *self = self_in; + return wlan_socket_recv(self, buf, size, errcode); +} + +STATIC mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { + mod_network_socket_obj_t *self = self_in; + return wlan_socket_send(self, buf, size, errcode); +} + +STATIC mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { mod_network_socket_obj_t *self = self_in; return wlan_socket_ioctl(self, request, arg, errcode); } -STATIC const mp_stream_p_t socket_stream_p = { +const mp_stream_p_t socket_stream_p = { + .read = socket_read, + .write = socket_write, .ioctl = socket_ioctl, .is_text = false, }; @@ -434,7 +461,7 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { // ipv4 only uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET); - if (result != 0) { + if (result < 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(result))); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); diff --git a/cc3200/mods/modusocket.h b/cc3200/mods/modusocket.h index c2c055325e..851f8e5be7 100644 --- a/cc3200/mods/modusocket.h +++ b/cc3200/mods/modusocket.h @@ -27,6 +27,9 @@ #ifndef MODUSOCKET_H_ #define MODUSOCKET_H_ +extern const mp_obj_dict_t socket_locals_dict; +extern const mp_stream_p_t socket_stream_p; + extern void modusocket_pre_init (void); extern void modusocket_socket_add (int16_t sd, bool user); extern void modusocket_socket_delete (int16_t sd); diff --git a/cc3200/mods/modussl.c b/cc3200/mods/modussl.c new file mode 100644 index 0000000000..be7219284f --- /dev/null +++ b/cc3200/mods/modussl.c @@ -0,0 +1,149 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2015 Daniel Campora + * + * 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 "simplelink.h" +#include "py/mpconfig.h" +#include MICROPY_HAL_H +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "modnetwork.h" +#include "modusocket.h" +#include "mpexception.h" + +/****************************************************************************** + DEFINE CONSTANTS + ******************************************************************************/ +#define SSL_CERT_NONE (0) +#define SSL_CERT_OPTIONAL (1) +#define SSL_CERT_REQUIRED (2) + +/****************************************************************************** + DEFINE TYPES + ******************************************************************************/ +typedef struct _mp_obj_ssl_socket_t { + mp_obj_base_t base; + mod_network_socket_base_t sock_base; + mp_obj_t o_sock; +} mp_obj_ssl_socket_t; + +/****************************************************************************** + DECLARE PRIVATE DATA + ******************************************************************************/ +STATIC const mp_obj_type_t ssl_socket_type; + +/******************************************************************************/ +// Micro Python bindings; SSL class + +// ssl socket inherits from normal socket, so we take its +// locals and stream methods +STATIC const mp_obj_type_t ssl_socket_type = { + { &mp_type_type }, + .name = MP_QSTR_ussl, + .getiter = NULL, + .iternext = NULL, + .stream_p = &socket_stream_p, + .locals_dict = (mp_obj_t)&socket_locals_dict, +}; + +STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + STATIC const mp_arg_t allowed_args[] = { + { MP_QSTR_sock, MP_ARG_REQUIRED | MP_ARG_OBJ, }, + { MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_false} }, + { MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} }, + { MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + // parse arguments + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // chech if ca validation is required + if (args[4].u_int != SSL_CERT_NONE && args[5].u_obj == mp_const_none) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + } + + // server side param is irrelevant for us (at least for the moment) + + // retrieve the file paths (with an 6 byte offset because to strip the '/flash' prefix) + const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]); + const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]); + const char *cafile = (args[5].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ? + NULL : &(mp_obj_str_get_str(args[5].u_obj)[6]); + + _i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd; + _i16 _errno; + if (keyfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, keyfile, strlen(keyfile))) < 0) { + goto socket_error; + } + if (certfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, certfile, strlen(certfile))) < 0) { + goto socket_error; + } + if (cafile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME, cafile, strlen(cafile))) < 0) { + goto socket_error; + } + + // create the ssl socket + mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t); + // ssl socket inherits all properties from the original socket + memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t)); + ssl_sock->base.type = &ssl_socket_type; + ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false; + ssl_sock->o_sock = args[0].u_obj; + + return ssl_sock; + +socket_error: + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket); + +STATIC const mp_map_elem_t mp_module_ussl_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ussl) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_wrap_socket), (mp_obj_t)&mod_ssl_wrap_socket_obj }, + + // class exceptions + { MP_OBJ_NEW_QSTR(MP_QSTR_SSLError), (mp_obj_t)&mp_type_OSError }, + + // class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_CERT_NONE), MP_OBJ_NEW_SMALL_INT(SSL_CERT_NONE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CERT_OPTIONAL), MP_OBJ_NEW_SMALL_INT(SSL_CERT_OPTIONAL) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CERT_REQUIRED), MP_OBJ_NEW_SMALL_INT(SSL_CERT_REQUIRED) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_ussl_globals, mp_module_ussl_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_ussl_globals, +}; + diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c index 0f89266bee..4861660dd2 100644 --- a/cc3200/mods/modwlan.c +++ b/cc3200/mods/modwlan.c @@ -1134,32 +1134,30 @@ int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) { // open the socket - int16_t sd = sl_Socket(s->u_param.domain, s->u_param.type, s->u_param.proto); + int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto); // save the socket descriptor - s->sd = sd; + s->sock_base.sd = sd; if (sd < 0) { *_errno = sd; return -1; } - // mark the socket not closed - s->closed = false; - return 0; } void wlan_socket_close(mod_network_socket_obj_t *s) { // this is to prevent the finalizer to close a socket that failed when being created - if (s->sd >= 0) { - modusocket_socket_delete(s->sd); - sl_Close(s->sd); + if (s->sock_base.sd >= 0) { + modusocket_socket_delete(s->sock_base.sd); + // TODO check return value and raise an exception if applicable + sl_Close(s->sock_base.sd); } - s->closed = true; + s->sock_base.closed = true; } int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) - int ret = sl_Bind(s->sd, &addr, sizeof(addr)); + int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr)); if (ret != 0) { *_errno = ret; return -1; @@ -1168,7 +1166,7 @@ int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int } int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) { - int ret = sl_Listen(s->sd, backlog); + int ret = sl_Listen(s->sock_base.sd, backlog); if (ret != 0) { *_errno = ret; return -1; @@ -1182,17 +1180,14 @@ int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2 sockaddr addr; socklen_t addr_len = sizeof(addr); - sd = sl_Accept(s->sd, &addr, &addr_len); + sd = sl_Accept(s->sock_base.sd, &addr, &addr_len); // save the socket descriptor - s2->sd = sd; + s2->sock_base.sd = sd; if (sd < 0) { *_errno = sd; return -1; } - // mark the socket not closed - s2->closed = false; - // return ip and port UNPACK_SOCKADDR(addr, ip, *port); @@ -1201,7 +1196,7 @@ int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2 int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) - int ret = sl_Connect(s->sd, &addr, sizeof(addr)); + int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr)); if (ret != 0) { *_errno = ret; return -1; @@ -1212,7 +1207,7 @@ int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, i int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) { mp_int_t bytes = 0; if (len > 0) { - bytes = sl_Send(s->sd, (const void *)buf, len, 0); + bytes = sl_Send(s->sock_base.sd, (const void *)buf, len, 0); } if (bytes <= 0) { *_errno = bytes; @@ -1224,16 +1219,16 @@ int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) { // check if the socket is open - if (s->closed) { + if (s->sock_base.closed) { // socket is closed, but the there might be data remaining in the buffer, so check fd_set rfds; FD_ZERO(&rfds); - FD_SET(s->sd, &rfds); + FD_SET(s->sock_base.sd, &rfds); timeval tv; tv.tv_sec = 0; tv.tv_usec = 2; - int nfds = sl_Select(s->sd + 1, &rfds, NULL, NULL, &tv); - if (nfds == -1 || !FD_ISSET(s->sd, &rfds)) { + int nfds = sl_Select(s->sock_base.sd + 1, &rfds, NULL, NULL, &tv); + if (nfds == -1 || !FD_ISSET(s->sock_base.sd, &rfds)) { // no data waiting, so close the socket and return 0 data wlan_socket_close(s); return 0; @@ -1244,7 +1239,7 @@ int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int len = MIN(len, WLAN_MAX_RX_SIZE); // do the recv - int ret = sl_Recv(s->sd, buf, len, 0); + int ret = sl_Recv(s->sock_base.sd, buf, len, 0); if (ret < 0) { *_errno = ret; return -1; @@ -1255,7 +1250,7 @@ int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { MAKE_SOCKADDR(addr, ip, port) - int ret = sl_SendTo(s->sd, (byte*)buf, len, 0, (sockaddr*)&addr, sizeof(addr)); + int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (sockaddr*)&addr, sizeof(addr)); if (ret < 0) { *_errno = ret; return -1; @@ -1266,7 +1261,7 @@ int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { sockaddr addr; socklen_t addr_len = sizeof(addr); - mp_int_t ret = sl_RecvFrom(s->sd, buf, len, 0, &addr, &addr_len); + mp_int_t ret = sl_RecvFrom(s->sock_base.sd, buf, len, 0, &addr, &addr_len); if (ret < 0) { *_errno = ret; return -1; @@ -1275,8 +1270,8 @@ int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, return ret; } -int wlan_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { - int ret = sl_SetSockOpt(socket->sd, level, opt, optval, optlen); +int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { + int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen); if (ret < 0) { *_errno = ret; return -1; @@ -1296,14 +1291,14 @@ int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int // set blocking mode option.NonblockingEnabled = 0; } - ret = sl_SetSockOpt(s->sd, SOL_SOCKET, SO_NONBLOCKING, &option, sizeof(option)); + ret = sl_SetSockOpt(s->sock_base.sd, SOL_SOCKET, SO_NONBLOCKING, &option, sizeof(option)); has_timeout = false; } else { // set timeout struct SlTimeval_t timeVal; timeVal.tv_sec = timeout_s; // seconds timeVal.tv_usec = 0; // microseconds. 10000 microseconds resolution - ret = sl_SetSockOpt(s->sd, SOL_SOCKET, SO_RCVTIMEO, &timeVal, sizeof(timeVal)); + ret = sl_SetSockOpt(s->sock_base.sd, SOL_SOCKET, SO_RCVTIMEO, &timeVal, sizeof(timeVal)); has_timeout = true; } @@ -1312,7 +1307,7 @@ int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int return -1; } - s->has_timeout = has_timeout; + s->sock_base.has_timeout = has_timeout; return 0; } @@ -1321,7 +1316,7 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t if (request == MP_IOCTL_POLL) { mp_uint_t flags = arg; ret = 0; - int32_t sd = s->sd; + int32_t sd = s->sock_base.sd; // init fds fd_set rfds, wfds, xfds; @@ -1335,7 +1330,7 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t // A socked that just closed is available for reading. A call to // recv() returns 0 which is consistent with BSD. - if (s->closed) { + if (s->sock_base.closed) { ret |= MP_IOCTL_POLL_RD; } } @@ -1346,7 +1341,7 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t FD_SET(sd, &xfds); } - // call simplelink select with minimum timeout + // call simplelink's select with minimum timeout SlTimeval_t tv; tv.tv_sec = 0; tv.tv_usec = 1; diff --git a/cc3200/mods/modwlan.h b/cc3200/mods/modwlan.h index a811afdd78..c17a6e0b38 100644 --- a/cc3200/mods/modwlan.h +++ b/cc3200/mods/modwlan.h @@ -75,7 +75,7 @@ extern int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uin extern int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno); extern int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); extern int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); -extern int wlan_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); +extern int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); extern int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno); extern int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno); diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h index cb26683960..7f51261c46 100644 --- a/cc3200/mpconfigport.h +++ b/cc3200/mpconfigport.h @@ -108,6 +108,7 @@ extern const struct _mp_obj_module_t mp_module_usocket; extern const struct _mp_obj_module_t mp_module_network; extern const struct _mp_obj_module_t mp_module_uhashlib; extern const struct _mp_obj_module_t mp_module_ubinascii; +extern const struct _mp_obj_module_t mp_module_ussl; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ @@ -118,6 +119,7 @@ extern const struct _mp_obj_module_t mp_module_ubinascii; { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_ubinascii), (mp_obj_t)&mp_module_ubinascii }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_ussl), (mp_obj_t)&mp_module_ussl }, \ #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ { MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \ @@ -129,6 +131,7 @@ extern const struct _mp_obj_module_t mp_module_ubinascii; { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_hashlib), (mp_obj_t)&mp_module_uhashlib }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_ssl), (mp_obj_t)&mp_module_ussl }, \ // extra constants #define MICROPY_PORT_CONSTANTS \ diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h index 13a85a4fc7..3d37a0f4fc 100644 --- a/cc3200/qstrdefsport.h +++ b/cc3200/qstrdefsport.h @@ -237,6 +237,21 @@ Q(IPPROTO_TCP) Q(IPPROTO_UDP) Q(IPPROTO_RAW) +// for ssl class +Q(ssl) +Q(ussl) +Q(wrap_socket) +Q(sock) +Q(keyfile) +Q(certfile) +Q(server_side) +Q(cert_reqs) +Q(ca_certs) +Q(SSLError) +Q(CERT_NONE) +Q(CERT_OPTIONAL) +Q(CERT_REQUIRED) + // for network class Q(network) Q(server_running)