diff --git a/cc3200/ftp/ftp.c b/cc3200/ftp/ftp.c index 3dc0923ce2..d812f563af 100644 --- a/cc3200/ftp/ftp.c +++ b/cc3200/ftp/ftp.c @@ -40,6 +40,7 @@ #include "ftp.h" #include "simplelink.h" #include "modwlan.h" +#include "modusocket.h" #include "debug.h" #include "serverstask.h" #include "ff.h" @@ -50,7 +51,6 @@ #include "updater.h" #include "timeutils.h" - /****************************************************************************** DEFINE PRIVATE CONSTANTS ******************************************************************************/ @@ -429,6 +429,9 @@ static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) { _sd = *sd; if (_sd > 0) { + // add the new socket to the network administration + modusocket_socket_add(_sd, false); + // Enable non-blocking mode nonBlockingOption.NonblockingEnabled = 1; ASSERT (sl_SetSockOpt(_sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption)) == SL_SOC_OK); @@ -464,6 +467,9 @@ static ftp_result_t ftp_wait_for_connection (_i16 l_sd, _i16 *n_sd) { return E_FTP_RESULT_FAILED; } + // add the new socket to the network administration + modusocket_socket_add(_sd, false); + // client connected, so go on return E_FTP_RESULT_OK; } diff --git a/cc3200/mods/modnetwork.c b/cc3200/mods/modnetwork.c index f7dfd139f8..dd91427f41 100644 --- a/cc3200/mods/modnetwork.c +++ b/cc3200/mods/modnetwork.c @@ -25,48 +25,23 @@ * THE SOFTWARE. */ -#include -#include -#include +#include #include "py/mpstate.h" #include MICROPY_HAL_H #include "modnetwork.h" #include "mpexception.h" #include "serverstask.h" +#include "simplelink.h" + /// \module network - network configuration /// /// This module provides network drivers and routing configuration. void mod_network_init0(void) { - mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0); } -void mod_network_register_nic(mp_obj_t nic) { - for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { - if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) { - // nic already registered - return; - } - } - // nic not registered so add to list - mp_obj_list_append(&MP_STATE_PORT(mod_network_nic_list), nic); -} - -mp_obj_t mod_network_find_nic(void) { - for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { - mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; - return nic; - } - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); -} - -STATIC mp_obj_t network_route(void) { - return &MP_STATE_PORT(mod_network_nic_list); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route); - #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) STATIC mp_obj_t network_server_start(void) { servers_start(); @@ -97,7 +72,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_server_login_obj, network_server_login) STATIC const mp_map_elem_t mp_module_network_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) }, { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&mod_network_nic_type_wlan }, - { MP_OBJ_NEW_QSTR(MP_QSTR_route), (mp_obj_t)&network_route_obj }, #if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP) { MP_OBJ_NEW_QSTR(MP_QSTR_start_server), (mp_obj_t)&network_server_start_obj }, diff --git a/cc3200/mods/modnetwork.h b/cc3200/mods/modnetwork.h index 1b7811c93f..891513bc13 100644 --- a/cc3200/mods/modnetwork.h +++ b/cc3200/mods/modnetwork.h @@ -37,7 +37,7 @@ typedef struct _mod_network_nic_type_t { mp_obj_type_t base; // API for non-socket operations - int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out, uint8_t family); + int (*gethostbyname)(const char *name, mp_uint_t len, uint8_t *ip_out, uint8_t family); // API for socket operations; return -1 on error int (*socket)(struct _mod_network_socket_obj_t *s, int *_errno); @@ -57,7 +57,6 @@ typedef struct _mod_network_nic_type_t { typedef struct _mod_network_socket_obj_t { mp_obj_base_t base; - mp_obj_t nic; mod_network_nic_type_t *nic_type; union { struct { @@ -74,7 +73,5 @@ typedef struct _mod_network_socket_obj_t { extern const mod_network_nic_type_t mod_network_nic_type_wlan; void mod_network_init0(void); -void mod_network_register_nic(mp_obj_t nic); -mp_obj_t mod_network_find_nic(void); #endif // MODNETWORK_H_ diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c index 0d9564a48b..68a3252c98 100644 --- a/cc3200/mods/modusocket.c +++ b/cc3200/mods/modusocket.c @@ -34,62 +34,135 @@ #include "py/runtime.h" #include "netutils.h" #include "modnetwork.h" +#include "modusocket.h" #include "mpexception.h" +/****************************************************************************** + DEFINE PRIVATE CONSTANTS + ******************************************************************************/ +#define MOD_NETWORK_MAX_SOCKETS 10 + +/****************************************************************************** + DEFINE PRIVATE TYPES + ******************************************************************************/ +typedef struct { + int16_t sd; + bool user; +} modusocket_sock_t; + +/****************************************************************************** + DEFINE PRIVATE DATA + ******************************************************************************/ +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}}; + +/****************************************************************************** + DEFINE PUBLIC FUNCTIONS + ******************************************************************************/ +__attribute__ ((section (".boot"))) +void modusocket_pre_init (void) { + // create the wlan lock + ASSERT(OSI_OK == sl_LockObjCreate(&modusocket_LockObj, "SockLock")); + sl_LockObjUnlock (&modusocket_LockObj); +} + +void modusocket_socket_add (int16_t sd, bool user) { + sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd < 0) { + modusocket_sockets[i].sd = sd; + modusocket_sockets[i].user = user; + break; + } + } + sl_LockObjUnlock (&modusocket_LockObj); +} + +void modusocket_socket_delete (int16_t sd) { + sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd == sd) { + modusocket_sockets[i].sd = -1; + break; + } + } + sl_LockObjUnlock (&modusocket_LockObj); +} + +void modusocket_enter_sleep (void) { + fd_set socketset; + int16_t maxfd = 0; + + sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + int16_t sd; + if ((sd = modusocket_sockets[i].sd) >= 0) { + FD_SET(sd, &socketset); + maxfd = (maxfd > sd) ? maxfd : sd; + } + } + + // wait for any of the sockets to become ready... + sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL); + sl_LockObjUnlock (&modusocket_LockObj); +} + +void modusocket_close_all_user_sockets (void) { + sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER); + for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) { + if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) { + sl_Close(modusocket_sockets[i].sd); + modusocket_sockets[i].sd = -1; + } + } + sl_LockObjUnlock (&modusocket_LockObj); +} + /******************************************************************************/ // socket class STATIC const mp_obj_type_t socket_type; -STATIC void socket_select_nic(mod_network_socket_obj_t *self) { - // select a nic - self->nic = mod_network_find_nic(); - self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic); - - // call the nic to open the socket - int _errno; - if (self->nic_type->socket(self, &_errno) != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); - } -} - // 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); - // create socket object (not bound to any NIC yet) + // 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->nic = MP_OBJ_NULL; - s->nic_type = NULL; + s->nic_type = (mod_network_nic_type_t *)&mod_network_nic_type_wlan; s->u_param.domain = AF_INET; s->u_param.type = SOCK_STREAM; s->u_param.proto = IPPROTO_TCP; s->u_param.fileno = -1; - if (n_args >= 1) { + if (n_args > 0) { s->u_param.domain = mp_obj_get_int(args[0]); - if (n_args >= 2) { + if (n_args > 1) { s->u_param.type = mp_obj_get_int(args[1]); - if (n_args >= 3) { + if (n_args > 2) { s->u_param.proto = mp_obj_get_int(args[2]); - if (n_args == 4) { + if (n_args > 3) { s->u_param.fileno = mp_obj_get_int(args[3]); } } } } - socket_select_nic(s); + // create the socket + int _errno; + if (s->nic_type->socket(s, &_errno) != 0) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); + } + modusocket_socket_add(s->sd, true); return s; } // method socket.close() STATIC mp_obj_t socket_close(mp_obj_t self_in) { mod_network_socket_obj_t *self = self_in; - if (self->nic != MP_OBJ_NULL) { - self->nic_type->close(self); - } + self->nic_type->close(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close); @@ -107,7 +180,6 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { if (self->nic_type->bind(self, ip, port, &_errno) != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); @@ -116,16 +188,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) { mod_network_socket_obj_t *self = self_in; - if (self->nic == MP_OBJ_NULL) { - // not connected - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN))); - } - int _errno; if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); @@ -135,11 +201,10 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mod_network_socket_obj_t *self = self_in; // create new socket object - // starts with empty NIC so that finaliser doesn't run close() method if accept() fails + // starts with empty nic so that the finaliser doesn't run close() method if accept() fails mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); socket2->base.type = (mp_obj_t)&socket_type; - socket2->nic = MP_OBJ_NULL; - socket2->nic_type = NULL; + socket2->nic_type = MP_OBJ_NULL; // accept incoming connection uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; @@ -149,15 +214,16 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } - // new socket has valid state, so set the NIC to the same as parent - socket2->nic = self->nic; + // new socket has valid state, so set the nic to the same as parent socket2->nic_type = self->nic_type; + // add the socket to the list + modusocket_socket_add(socket2->sd, true); + // make the return value mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL); client->items[0] = socket2; client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE); - return client; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); @@ -175,7 +241,6 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { if (self->nic_type->connect(self, ip, port, &_errno) != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); @@ -183,10 +248,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); // method socket.send(bytes) STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { mod_network_socket_obj_t *self = self_in; - if (self->nic == MP_OBJ_NULL) { - // not connected - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF))); - } mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); int _errno; @@ -201,10 +262,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); // method socket.recv(bufsize) STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = self_in; - if (self->nic == MP_OBJ_NULL) { - // not connected - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN))); - } mp_int_t len = mp_obj_get_int(len_in); vstr_t vstr; vstr_init_len(&vstr, len); @@ -234,13 +291,12 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ 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 sendto + // call the nic to sendto int _errno; mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); if (ret == -1) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } - return mp_obj_new_int(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); @@ -248,10 +304,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); // method socket.recvfrom(bufsize) STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { mod_network_socket_obj_t *self = self_in; - if (self->nic == MP_OBJ_NULL) { - // not connected - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN))); - } vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(len_in)); byte ip[4]; @@ -299,7 +351,6 @@ STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) { if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); } - return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); @@ -310,10 +361,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_s // otherwise, timeout is in seconds STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { mod_network_socket_obj_t *self = self_in; - if (self->nic == MP_OBJ_NULL) { - // not connected - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN))); - } mp_uint_t timeout; if (timeout_in == mp_const_none) { timeout = -1; @@ -384,28 +431,19 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); - // find a NIC that can do a name lookup - for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { - mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; - mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); - if (nic_type->gethostbyname != NULL) { - // Only IPv4 is supported - uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; - int32_t result = nic_type->gethostbyname(nic, host, hlen, out_ip, AF_INET); - 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); - tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET); - tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM); - tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); - tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); - tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE); - return mp_obj_new_list(1, (mp_obj_t*)&tuple); - } + // ipv4 only + uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; + int32_t result = mod_network_nic_type_wlan.gethostbyname(host, hlen, out_ip, AF_INET); + if (result != 0) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(result))); } - - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET); + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM); + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); + tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); + tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE); + return mp_obj_new_list(1, (mp_obj_t*)&tuple); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo); diff --git a/cc3200/mods/modusocket.h b/cc3200/mods/modusocket.h new file mode 100644 index 0000000000..c2c055325e --- /dev/null +++ b/cc3200/mods/modusocket.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef MODUSOCKET_H_ +#define MODUSOCKET_H_ + +extern void modusocket_pre_init (void); +extern void modusocket_socket_add (int16_t sd, bool user); +extern void modusocket_socket_delete (int16_t sd); +extern void modusocket_enter_sleep (void); +extern void modusocket_close_all_user_sockets (void); + +#endif /* MODUSOCKET_H_ */ diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c index b05c046a99..cdcd375e66 100644 --- a/cc3200/mods/modwlan.c +++ b/cc3200/mods/modwlan.c @@ -36,6 +36,7 @@ #include "py/runtime.h" #include "netutils.h" #include "modnetwork.h" +#include "modusocket.h" #include "modwlan.h" #include "pybioctl.h" #include "debug.h" @@ -229,6 +230,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) { { CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION); CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED); + // TODO reset the servers } break; case SL_WLAN_STA_CONNECTED_EVENT: @@ -243,6 +245,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) { break; case SL_WLAN_STA_DISCONNECTED_EVENT: wlan_obj.staconnected = false; + // TODO reset the servers break; case SL_WLAN_P2P_DEV_FOUND_EVENT: // TODO @@ -718,8 +721,6 @@ STATIC mp_obj_t wlan_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k } wlan_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_wlan; - // register with the network module - mod_network_register_nic(&wlan_obj); return &wlan_obj; } @@ -1065,7 +1066,7 @@ STATIC const mp_cb_methods_t wlan_cb_methods = { /******************************************************************************/ // Micro Python bindings; WLAN socket -STATIC int wlan_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { +STATIC int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) { uint32_t ip; int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family); @@ -1090,14 +1091,11 @@ STATIC int wlan_socket_socket(struct _mod_network_socket_obj_t *s, int *_errno) // save the socket descriptor s->sd = sd; - // make it blocking by default - int32_t optval = 0; - sl_SetSockOpt(sd, SOL_SOCKET, SO_NONBLOCKING, &optval, (SlSocklen_t)sizeof(optval)); - return 0; } STATIC void wlan_socket_close(mod_network_socket_obj_t *s) { + modusocket_socket_delete(s->sd); s->closed = true; sl_Close(s->sd); } @@ -1152,12 +1150,6 @@ STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t } STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) { - if (s->closed) { - sl_Close (s->sd); - *_errno = EBADF; - return -1; - } - mp_int_t bytes = 0; if (len > 0) { bytes = sl_Send(s->sd, (const void *)buf, len, 0); @@ -1173,7 +1165,7 @@ STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uin STATIC 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) { - // socket is closed, but the CC3200 may have some data remaining in its buffer, so check + // 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); @@ -1182,8 +1174,8 @@ STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t le tv.tv_usec = 2; int nfds = sl_Select(s->sd + 1, &rfds, NULL, NULL, &tv); if (nfds == -1 || !FD_ISSET(s->sd, &rfds)) { - // no data waiting, so close socket and return 0 data - sl_Close(s->sd); + // no data waiting, so close the socket and return 0 data + wlan_socket_close(s); return 0; } } diff --git a/cc3200/mods/pybsleep.c b/cc3200/mods/pybsleep.c index 7e62418f4f..4226e6d1ce 100644 --- a/cc3200/mods/pybsleep.c +++ b/cc3200/mods/pybsleep.c @@ -52,6 +52,7 @@ #include "mpcallback.h" #include "mperror.h" #include "sleeprestore.h" +#include "serverstask.h" /****************************************************************************** DECLARE PRIVATE CONSTANTS @@ -429,7 +430,7 @@ STATIC void PRCMInterruptHandler (void) { pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO; break; case PRCM_LPDS_TIMER: - // disable the timer as a wake-up source + // disable the timer as wake-up source pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_LPDS; MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER); mpcallback_handler(pybsleep_data.timer_lpds_wake_cb); @@ -593,6 +594,7 @@ STATIC mp_obj_t pyb_sleep_suspend (mp_obj_t self_in) { // do we need network wake-up? if (pybsleep_data.wlan_lpds_wake_cb) { MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ); + server_sleep_sockets(); } else { MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ); diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h index 5bf6477ea4..fd60f04327 100644 --- a/cc3200/mpconfigport.h +++ b/cc3200/mpconfigport.h @@ -139,7 +139,6 @@ extern const struct _mp_obj_module_t mp_module_ubinascii; const char *readline_hist[8]; \ mp_obj_t mp_const_user_interrupt; \ mp_obj_t pyb_config_main; \ - mp_obj_list_t mod_network_nic_list; \ mp_obj_list_t pybsleep_obj_list; \ mp_obj_list_t mpcallback_obj_list; \ mp_obj_list_t pyb_timer_channel_obj_list; \ diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 459d171302..7b730c5367 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -50,6 +50,7 @@ #include "mperror.h" #include "simplelink.h" #include "modnetwork.h" +#include "modusocket.h" #include "modwlan.h" #include "serverstask.h" #include "telnet.h" @@ -255,6 +256,9 @@ soft_reset_exit: // flush the serial flash buffer sflash_disk_flush(); + // clean-up the user socket space + modusocket_close_all_user_sockets(); + #if MICROPY_HW_HAS_SDCARD pybsd_deinit(); #endif @@ -283,9 +287,12 @@ STATIC void mptask_pre_init (void) { // this one allocates memory for the nvic vault pybsleep_pre_init(); - // this one allocates mameory for the WLAN semaphore + // this one allocates memory for the WLAN semaphore wlan_pre_init(); + // this one allocates memory for the Socket semaphore + modusocket_pre_init(); + #if MICROPY_HW_HAS_SDCARD pybsd_init0(); #endif diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h index ee07fb5ed3..c3fdf71f36 100644 --- a/cc3200/qstrdefsport.h +++ b/cc3200/qstrdefsport.h @@ -233,7 +233,6 @@ Q(IPPROTO_RAW) // for network class Q(network) -Q(route) Q(start_server) Q(stop_server) Q(server_running) diff --git a/cc3200/serverstask.c b/cc3200/serverstask.c index 550f0c0719..80f22987fe 100644 --- a/cc3200/serverstask.c +++ b/cc3200/serverstask.c @@ -36,6 +36,7 @@ #include "telnet.h" #include "ftp.h" #include "pybwdt.h" +#include "modusocket.h" /****************************************************************************** @@ -58,6 +59,7 @@ typedef struct { DECLARE PRIVATE DATA ******************************************************************************/ static servers_Data_t servers_data = {.enabled = false, .do_disable = false, .do_enable = false}; +static volatile bool sleep_sockets = false; /****************************************************************************** DECLARE PRIVATE FUNCTIONS @@ -108,11 +110,17 @@ void TASK_Servers (void *pvParameters) { ftp_run(); } + // set the alive flag for the wdt + pybwdt_srv_alive(); + + if (sleep_sockets) { + sleep_sockets = false; + modusocket_enter_sleep(); + } + // move to the next cycle cycle = cycle ? false : true; HAL_Delay(SERVERS_CYCLE_TIME_MS); - // set the alive flag for the wdt - pybwdt_srv_alive(); } } @@ -133,8 +141,14 @@ bool servers_are_enabled (void) { return servers_data.enabled; } +void server_sleep_sockets (void) { + sleep_sockets = true; + HAL_Delay (SERVERS_CYCLE_TIME_MS + 1); +} + void servers_close_socket (int16_t *sd) { if (*sd > 0) { + modusocket_socket_delete(*sd); sl_Close(*sd); *sd = -1; } diff --git a/cc3200/serverstask.h b/cc3200/serverstask.h index 04b1367ff2..6607283136 100644 --- a/cc3200/serverstask.h +++ b/cc3200/serverstask.h @@ -59,5 +59,6 @@ extern void servers_stop (void); extern bool servers_are_enabled (void); extern void servers_close_socket (int16_t *sd); extern void servers_set_login (char *user, char *pass); +extern void server_sleep_sockets (void); #endif /* SERVERSTASK_H_ */ diff --git a/cc3200/telnet/telnet.c b/cc3200/telnet/telnet.c index a910437df4..0edc00cdb1 100644 --- a/cc3200/telnet/telnet.c +++ b/cc3200/telnet/telnet.c @@ -32,6 +32,7 @@ #include "telnet.h" #include "simplelink.h" #include "modwlan.h" +#include "modusocket.h" #include "debug.h" #include "mpexception.h" #include "serverstask.h" @@ -322,6 +323,9 @@ static bool telnet_create_socket (void) { // Open a socket for telnet ASSERT ((telnet_data.sd = sl_Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0); if (telnet_data.sd > 0) { + // add the socket to the network administration + modusocket_socket_add(telnet_data.sd, false); + // Enable non-blocking mode nonBlockingOption.NonblockingEnabled = 1; ASSERT (sl_SetSockOpt(telnet_data.sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption)) == SL_SOC_OK); @@ -352,15 +356,18 @@ static void telnet_wait_for_connection (void) { return; } else { - // close the listening socket, we don't need it anymore - sl_Close(telnet_data.sd); - if (telnet_data.n_sd <= 0) { // error telnet_reset(); return; } + // close the listening socket, we don't need it anymore + servers_close_socket(&telnet_data.sd); + + // add the new socket to the network administration + modusocket_socket_add(telnet_data.n_sd, false); + // client connected, so go on telnet_data.rxWindex = 0; telnet_data.rxRindex = 0;