From 90cd978785d0ac7d38115b09aecee797ff4c8a2c Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Thu, 26 May 2016 23:54:05 -0500 Subject: [PATCH] Separate interface from stack in NSAPI This patch consists of: -Add NetworkInterface to wrap objects bound to a stack and update socket code to handle this in addition to NetworkStacks -Update MeshInterface to inherit from NetworkInterface -Update NanostackInterface so it only inherits from NetworkStack -Add MeshInterfaceNanostack and update LoWPANNDInterface and ThreadInterface to inherit from this --- EthernetInterface.h => EthInterface.h | 12 +++--- MeshInterface.h | 4 +- NetworkInterface.h | 41 +++++++++++++++++++++ NetworkStack.h | 4 +- SocketAddress.cpp | 53 ++++++++++++++++----------- SocketAddress.h | 15 ++++++++ TCPServer.cpp | 11 ++++++ TCPServer.h | 21 +++++++++++ TCPSocket.cpp | 13 +++++++ TCPSocket.h | 21 +++++++++++ UDPSocket.cpp | 11 ++++++ UDPSocket.h | 21 +++++++++++ WiFiInterface.h | 4 +- 13 files changed, 198 insertions(+), 33 deletions(-) rename EthernetInterface.h => EthInterface.h (87%) create mode 100644 NetworkInterface.h diff --git a/EthernetInterface.h b/EthInterface.h similarity index 87% rename from EthernetInterface.h rename to EthInterface.h index c0214c688b..e16a71b128 100644 --- a/EthernetInterface.h +++ b/EthInterface.h @@ -1,4 +1,4 @@ -/* EthernetInterface +/* EthInterface * Copyright (c) 2015 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,16 +14,16 @@ * limitations under the License. */ -#ifndef ETHERNET_INTERFACE_H -#define ETHERNET_INTERFACE_H +#ifndef ETH_INTERFACE_H +#define ETH_INTERFACE_H -#include "NetworkStack.h" +#include "NetworkInterface.h" -/** EthernetInterface class +/** EthInterface class * * Common interface that is shared between ethernet hardware. */ -class EthernetInterface +class EthInterface : public NetworkInterface { public: /** Start the interface diff --git a/MeshInterface.h b/MeshInterface.h index 811b3f7352..54d3654b45 100644 --- a/MeshInterface.h +++ b/MeshInterface.h @@ -17,13 +17,13 @@ #ifndef MESH_INTERFACE_H #define MESH_INTERFACE_H -#include "NetworkStack.h" +#include "NetworkInterface.h" /** MeshInterface class * * Common interface that is shared between mesh hardware */ -class MeshInterface +class MeshInterface : public NetworkInterface { public: /** Start the interface diff --git a/NetworkInterface.h b/NetworkInterface.h new file mode 100644 index 0000000000..af97ee7ffd --- /dev/null +++ b/NetworkInterface.h @@ -0,0 +1,41 @@ +/* NetworkStack + * Copyright (c) 2015 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETWORK_INTERFACE_H +#define NETWORK_INTERFACE_H + +#include "mbed.h" +#include "SocketAddress.h" + +class NetworkInterface { +public: + virtual ~NetworkInterface() {}; + NetworkInterface() {} + + /** Get the internally stored IP address + /return IP address of the interface or null if not yet connected + */ + virtual const char *get_ip_address() = 0; +protected: + friend class Socket; + friend class UDPSocket; + friend class TCPSocket; + friend class TCPServer; + friend class SocketAddress; + virtual NetworkStack * get_stack(void) = 0; +}; + +#endif diff --git a/NetworkStack.h b/NetworkStack.h index 8667c9d9f0..2c5b0f9c5a 100644 --- a/NetworkStack.h +++ b/NetworkStack.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef NETWORK_INTERFACE_H -#define NETWORK_INTERFACE_H +#ifndef NETWORK_STACK_H +#define NETWORK_STACK_H #include "mbed.h" #include "SocketAddress.h" diff --git a/SocketAddress.cpp b/SocketAddress.cpp index ec6a15fb82..31d560f2db 100644 --- a/SocketAddress.cpp +++ b/SocketAddress.cpp @@ -15,6 +15,7 @@ */ #include "SocketAddress.h" +#include "NetworkInterface.h" #include "NetworkStack.h" #include #include "mbed.h" @@ -144,28 +145,12 @@ static void ipv6_to_address(char *addr, const uint8_t *bytes) SocketAddress::SocketAddress(NetworkStack *iface, const char *host, uint16_t port) { - memset(&_ip_address, 0, sizeof _ip_address); + _SocketAddress(iface, host, port); +} - // Check for valid IP addresses - if (host && ipv4_is_valid(host)) { - _ip_version = NSAPI_IPv4; - ipv4_from_address(_ip_bytes, host); - set_port(port); - } else if (host && ipv6_is_valid(host)) { - _ip_version = NSAPI_IPv6; - ipv6_from_address(_ip_bytes, host); - set_port(port); - } else { - // DNS lookup - int err = iface->gethostbyname(this, host); - if (!err) { - set_port(port); - } else { - _ip_version = NSAPI_IPv4; - memset(_ip_bytes, 0, NSAPI_IPv4_BYTES); - set_port(0); - } - } +SocketAddress::SocketAddress(NetworkInterface *iface, const char *host, uint16_t port) +{ + _SocketAddress(iface->get_stack(), host, port); } SocketAddress::SocketAddress(const char *addr, uint16_t port) @@ -273,3 +258,29 @@ SocketAddress::operator bool() const return false; } + +void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port) +{ + memset(&_ip_address, 0, sizeof _ip_address); + + // Check for valid IP addresses + if (host && ipv4_is_valid(host)) { + _ip_version = NSAPI_IPv4; + ipv4_from_address(_ip_bytes, host); + set_port(port); + } else if (host && ipv6_is_valid(host)) { + _ip_version = NSAPI_IPv6; + ipv6_from_address(_ip_bytes, host); + set_port(port); + } else { + // DNS lookup + int err = iface->gethostbyname(this, host); + if (!err) { + set_port(port); + } else { + _ip_version = NSAPI_IPv4; + memset(_ip_bytes, 0, NSAPI_IPv4_BYTES); + set_port(0); + } + } +} diff --git a/SocketAddress.h b/SocketAddress.h index 64f2991e0b..f87653e987 100644 --- a/SocketAddress.h +++ b/SocketAddress.h @@ -65,6 +65,7 @@ enum nsapi_version_t { // Predeclared classes class NetworkStack; +class NetworkInterface; /** SocketAddress class @@ -86,6 +87,19 @@ public: */ SocketAddress(NetworkStack *iface, const char *host, uint16_t port = 0); + /** Create a SocketAddress from a hostname and port + * + * The hostname may be either a domain name or an IP address. If the + * hostname is an IP address, no network transactions will be performed. + * + * On failure, the IP address and port will be set to zero + * + * @param iface Network interface to use for DNS resolution + * @param host Hostname to resolve + * @param port Optional 16-bit port + */ + SocketAddress(NetworkInterface *iface, const char *host, uint16_t port = 0); + /** Create a SocketAddress from an IP address and port * * @param host Null-terminated representation of the IP address @@ -157,6 +171,7 @@ public: operator bool() const; private: + void _SocketAddress(NetworkStack *iface, const char *host, uint16_t port); char _ip_address[NSAPI_IP_SIZE]; uint8_t _ip_bytes[NSAPI_IP_BYTES]; nsapi_version_t _ip_version; diff --git a/TCPServer.cpp b/TCPServer.cpp index 3edae6093e..cf75096e3b 100644 --- a/TCPServer.cpp +++ b/TCPServer.cpp @@ -28,6 +28,12 @@ TCPServer::TCPServer(NetworkStack *iface) open(iface); } +TCPServer::TCPServer(NetworkInterface *iface) + : _pending(0), _accept_sem(0) +{ + open(iface->get_stack()); +} + TCPServer::~TCPServer() { close(); @@ -38,6 +44,11 @@ int TCPServer::open(NetworkStack *iface) return Socket::open(iface, NSAPI_TCP); } +int TCPServer::open(NetworkInterface *iface) +{ + return TCPServer::open(iface->get_stack()); +} + int TCPServer::listen(int backlog) { _lock.lock(); diff --git a/TCPServer.h b/TCPServer.h index 6c32286216..f5a7e2c87a 100644 --- a/TCPServer.h +++ b/TCPServer.h @@ -19,6 +19,7 @@ #include "Socket.h" #include "TCPSocket.h" +#include "NetworkInterface.h" #include "NetworkStack.h" #include "Semaphore.h" @@ -46,6 +47,15 @@ public: */ TCPServer(NetworkStack *iface); + /** Create a socket on a network interface + * + * Creates and opens a socket on the network stack of the given + * network interface. + * + * @param iface Network interface as target for socket + */ + TCPServer(NetworkInterface *iface); + /** Opens a socket * * Creates a network socket on the specified network stack. @@ -56,6 +66,17 @@ public: */ virtual int open(NetworkStack *iface); + /** Opens a socket + * + * Creates a network socket on the network stack of the given + * network interface. Not needed if stack is passed to the + * socket's constructor. + * + * @param iface Network interface as target for socket + * @return 0 on success, negative error code on failure + */ + virtual int open(NetworkInterface *iface); + /** Listen for connections on a TCP socket * * Marks the socket as a passive socket that can be used to accept diff --git a/TCPSocket.cpp b/TCPSocket.cpp index 286683e75a..59566d1921 100644 --- a/TCPSocket.cpp +++ b/TCPSocket.cpp @@ -29,6 +29,13 @@ TCPSocket::TCPSocket(NetworkStack *iface) open(iface); } +TCPSocket::TCPSocket(NetworkInterface *iface) + : _pending(0), _read_sem(0), _write_sem(0) +{ + // TCPSocket::open is thread safe + open(iface->get_stack()); +} + TCPSocket::~TCPSocket() { close(); @@ -40,6 +47,12 @@ int TCPSocket::open(NetworkStack *iface) return Socket::open(iface, NSAPI_TCP); } +int TCPSocket::open(NetworkInterface *iface) +{ + // Socket::open is thread safe + return TCPSocket::open(iface->get_stack()); +} + int TCPSocket::connect(const SocketAddress &addr) { _lock.lock(); diff --git a/TCPSocket.h b/TCPSocket.h index 4f19b60a0b..d4e6a1f845 100644 --- a/TCPSocket.h +++ b/TCPSocket.h @@ -18,6 +18,7 @@ #define TCPSOCKET_H #include "Socket.h" +#include "NetworkInterface.h" #include "NetworkStack.h" #include "Semaphore.h" @@ -45,6 +46,15 @@ public: */ TCPSocket(NetworkStack *iface); + /** Create a socket on a network interface + * + * Creates and opens a socket on the network stack of the given + * network interface. + * + * @param iface Network interface as target for socket + */ + TCPSocket(NetworkInterface *iface); + /** Opens a socket * * Creates a network socket on the specified network stack. @@ -55,6 +65,17 @@ public: */ virtual int open(NetworkStack *iface); + /** Opens a socket + * + * Creates a network socket on the network stack of the given + * network interface. Not needed if stack is passed to the + * socket's constructor. + * + * @param iface Network interface as target for socket + * @return 0 on success, negative error code on failure + */ + virtual int open(NetworkInterface *iface); + /** Connects TCP socket to a remote host * * Initiates a connection to a remote server specified by either diff --git a/UDPSocket.cpp b/UDPSocket.cpp index 361e3c83ae..d6e13b4226 100644 --- a/UDPSocket.cpp +++ b/UDPSocket.cpp @@ -28,6 +28,12 @@ UDPSocket::UDPSocket(NetworkStack *iface) open(iface); } +UDPSocket::UDPSocket(NetworkInterface *iface) + : _pending(0), _read_sem(0), _write_sem(0) +{ + open(iface->get_stack()); +} + UDPSocket::~UDPSocket() { close(); @@ -38,6 +44,11 @@ int UDPSocket::open(NetworkStack *iface) return Socket::open(iface, NSAPI_UDP); } +int UDPSocket::open(NetworkInterface *iface) +{ + return UDPSocket::open(iface->get_stack()); +} + int UDPSocket::sendto(const char *host, uint16_t port, const void *data, unsigned size) { SocketAddress addr(_iface, host, port); diff --git a/UDPSocket.h b/UDPSocket.h index 7e3439678e..3575f18cf5 100644 --- a/UDPSocket.h +++ b/UDPSocket.h @@ -18,6 +18,7 @@ #define UDPSOCKET_H #include "Socket.h" +#include "NetworkInterface.h" #include "NetworkStack.h" #include "Semaphore.h" @@ -45,6 +46,15 @@ public: */ UDPSocket(NetworkStack *iface); + /** Create a socket on a network interface + * + * Creates and opens a socket on the network stack of the given + * network interface. + * + * @param iface Network interface as target for socket + */ + UDPSocket(NetworkInterface *iface); + /** Opens a socket * * Creates a network socket on the specified network stack. @@ -55,6 +65,17 @@ public: */ virtual int open(NetworkStack *iface); + /** Opens a socket + * + * Creates a network socket on the network stack of the given + * network interface. Not needed if stack is passed to the + * socket's constructor. + * + * @param iface Network interface as target for socket + * @return 0 on success, negative error code on failure + */ + virtual int open(NetworkInterface *iface); + /** Send a packet over a UDP socket * * Sends data to the specified address specified by either a domain name diff --git a/WiFiInterface.h b/WiFiInterface.h index 09f5340d32..f99b411b01 100644 --- a/WiFiInterface.h +++ b/WiFiInterface.h @@ -17,7 +17,7 @@ #ifndef WIFI_INTERFACE_H #define WIFI_INTERFACE_H -#include "NetworkStack.h" +#include "NetworkInterface.h" /** Enum of WiFi encryption types * @@ -37,7 +37,7 @@ enum nsapi_security_t { * * Common interface that is shared between WiFi devices */ -class WiFiInterface +class WiFiInterface: public NetworkInterface { public: /** Start the interface