Base class for IP Based Networking Libraries
Dependencies: DnsQuery
Dependents: TempTower BSDInterfaceTests HelloBSDInterface ESP8266InterfaceTests ... more
For a complete getting started guide see the wiki...
Network Socket API
The Network Socket API provides a common interface for using sockets on network devices. The API provides a simple class-based interface that should be familiar to users experienced with other socket APIs. Additionally, the API provides a simple interface for implementing network devices, making it easy to connect hardware agnostic programs to new devices.
Network Interfaces
The NetworkInterface provides an abstract class for network devices that support sockets. Devices should provide a DeviceInterface class that inherits this interface and adds implementation specific methods for using the device. A NetworkInterface must be provided to a Socket constructor to open a socket on the interface. Currently two subclasses are defined for common devices, EthernetInterface
and WiFiInterface.
Sockets
The Socket class is used for managing network sockets. Once opened, the socket provides a pipe through which data can sent and recieved to a specific endpoint. The socket class can be instantiated as either a TCPSocket
or a UDPSocket
which defines the protocol used for the connection.
Revision 79:43a7e8c0d6cc, committed 2016-04-05
- Comitter:
- Christopher Haster
- Date:
- Tue Apr 05 10:40:34 2016 -0500
- Parent:
- 78:0914f9b9b24b
- Child:
- 80:9c6673c93082
- Commit message:
- Added rough implementation of the API shim
Changed in this revision
--- a/NetworkInterface.h Tue Apr 05 09:20:32 2016 -0500 +++ b/NetworkInterface.h Tue Apr 05 10:40:34 2016 -0500 @@ -17,6 +17,8 @@ #ifndef NETWORK_INTERFACE_H #define NETWORK_INTERFACE_H +#include "FunctionPointer.h" + /** * @enum ns_error_t * @brief enum of standardized error codes @@ -75,6 +77,11 @@ virtual SocketAddress gethostbyname(const char *name, uint16_t port=0); protected: + friend class Socket; + friend class UDPSocket; + friend class TCPSocket; + friend class TCPServer; + /** Enum of socket protocols /enum protocol_t */ @@ -194,21 +201,21 @@ \param callback Function to call when accept will succeed, may be called in interrupt context. */ - virtual void socket_attach_accept(void *handle, FuncPtr<void()> callback) = 0; + virtual void socket_attach_accept(void *handle, mbed::FuncPtr<void()> callback) = 0; /** Register a callback on when send is ready \param handle Socket handle \param callback Function to call when send will succeed, may be called in interrupt context. */ - virtual void socket_attach_send(void *handle, FuncPtr<void()> callback) = 0; + virtual void socket_attach_send(void *handle, mbed::FuncPtr<void()> callback) = 0; /** Register a callback on when recv is ready \param handle Socket handle \param callback Function to call when recv will succeed, may be called in interrupt context. */ - virtual void socket_attach_recv(void *handle, FuncPtr<void()> callback) = 0; + virtual void socket_attach_recv(void *handle, mbed::FuncPtr<void()> callback) = 0; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket.cpp Tue Apr 05 10:40:34 2016 -0500 @@ -0,0 +1,75 @@ +/* Socket + * 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. + */ + +#include "Socket.h" + +Socket::Socket(NetworkInterface *iface, NetworkInterface::protocol_t proto) + : _iface(iface) +{ + _socket = _iface->socket_create(proto); +} + +Socket::~Socket() +{ + if (_socket) { + close(false); + } +} + +void Socket::set_blocking(bool blocking) +{ + _blocking = blocking; +} + +void Socket::set_timeout(unsigned timeout) +{ + _timeout = timeout; +} + +int Socket::set_option(int optname, const void *optval, unsigned int optlen) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_set_option(_socket, optname, optval, optlen); +} + +int Socket::get_option(int optname, void *optval, unsigned int *optlen) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_get_option(_socket, optname, optval, optlen); +} + +int Socket::close(bool shutdown) +{ + if (!_socket) { + return 0; + } + + int err = _iface->socket_close(_socket, shutdown); + if (!err) { + void *socket = _socket; + _socket = 0; + _iface->socket_destroy(socket); + } + + return err; +} +
--- a/Socket.h Tue Apr 05 09:20:32 2016 -0500 +++ b/Socket.h Tue Apr 05 10:40:34 2016 -0500 @@ -17,6 +17,8 @@ #ifndef SOCKET_H #define SOCKET_H +#include "SocketAddress.h" +#include "NetworkInterface.h" /** Abstract socket class */ @@ -24,7 +26,6 @@ public: /** Socket lifetime */ - Socket(); ~Socket(); /** Set blocking or non-blocking mode of the socket @@ -57,6 +58,14 @@ \param shutdown free the left-over data in message queues */ int close(bool shutdown=true); + +protected: + Socket(NetworkInterface *iface, NetworkInterface::protocol_t proto); + + NetworkInterface *_iface; + void *_socket; + bool _blocking; + unsigned _timeout; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SocketAddress.cpp Tue Apr 05 10:40:34 2016 -0500 @@ -0,0 +1,51 @@ +/* Socket + * 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. + */ + +#include "SocketAddress.h" +#include <string.h> + +SocketAddress::SocketAddress(const char *addr, uint16_t port) +{ + set_ip_address(addr); + set_port(port); +} + +SocketAddress::SocketAddress(const SocketAddress &addr) +{ + set_ip_address(addr.get_ip_address()); + set_port(addr.get_port()); +} + +void SocketAddress::set_ip_address(const char *addr) +{ + strncpy(_ip_address, addr, sizeof _ip_address); + _ip_address[sizeof _ip_address - 1] = '\0'; +} + +void SocketAddress::set_port(uint16_t port) +{ + _port = port; +} + +const char *SocketAddress::get_ip_address() const +{ + return _ip_address; +} + +uint16_t SocketAddress::get_port() const +{ + return _port; +}
--- a/SocketAddress.h Tue Apr 05 09:20:32 2016 -0500 +++ b/SocketAddress.h Tue Apr 05 10:40:34 2016 -0500 @@ -17,21 +17,24 @@ #ifndef SOCKET_ADDRESS_H #define SOCKET_ADDRESS_H +#include <stdint.h> + /** * A general socket address composed of the IP address and port */ class SocketAddress { public: - /** SocketAddress lifetime + /** SocketAddress construction + /param addr Null-terminated string representing the IP address + /param port 16-bit port */ SocketAddress(const char *addr = 0, uint16_t port = 0); SocketAddress(const SocketAddress &); - ~SocketAddress(); /** Set the IP address - \param host Null-terminated string representing the IP address + \param addr Null-terminated string representing the IP address */ - void set_ip_address(const char *host); + void set_ip_address(const char *addr); /** Set the port \param port 16-bit port @@ -41,12 +44,16 @@ /** Get the IP address \return The string representation of the IP Address */ - const char *get_ip_address(); + const char *get_ip_address() const; /** Get the port \return The 16-bit port */ - int get_port(void); + uint16_t get_port(void) const; + +private: + char _ip_address[16]; + uint16_t _port; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TCPServer.cpp Tue Apr 05 10:40:34 2016 -0500 @@ -0,0 +1,58 @@ +/* Socket + * 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. + */ + +#include "TCPServer.h" + +TCPServer::TCPServer(NetworkInterface *iface) + : Socket(iface, NetworkInterface::TCP) +{ +} + +int TCPServer::bind(uint16_t port) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_bind(_socket, port); +} + +int TCPServer::listen(int backlog) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_listen(_socket, backlog); +} + +int TCPServer::accept(TCPSocket *connection) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + void *socket = connection->_socket; + connection->_socket = 0; + _iface->socket_destroy(socket); + + int err = _iface->socket_accept(_socket, &socket); + if (!err) { + connection->_socket = socket; + } + + return err; +}
--- a/TCPServer.h Tue Apr 05 09:20:32 2016 -0500 +++ b/TCPServer.h Tue Apr 05 10:40:34 2016 -0500 @@ -34,7 +34,7 @@ \param port The port to listen for incoming connections on \return 0 on success, negative on failure */ - int bind(int port); + int bind(uint16_t port); /** Start listening for incoming connections \param backlog Number of pending connections that can be queued up at any @@ -53,7 +53,7 @@ \param callback Function to call when accept will succeed, may be called in interrupt context. */ - void attach_accept(FuncPtr<void()> callback); + void attach_accept(mbed::FuncPtr<void()> callback); }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TCPSocket.cpp Tue Apr 05 10:40:34 2016 -0500 @@ -0,0 +1,64 @@ +/* Socket + * 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. + */ + +#include "TCPSocket.h" + +TCPSocket::TCPSocket(NetworkInterface *iface) + : Socket(iface, NetworkInterface::TCP) +{ +} + +int TCPSocket::connect(SocketAddress addr) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_connect(_socket, addr); +} + +int TCPSocket::connect(const char *host, uint16_t port) +{ + SocketAddress addr = _iface->gethostbyname(host, port); + if (!addr.get_ip_address()) { + return NSAPI_ERROR_DNS_FAILURE; + } + + return connect(addr); +} + +bool TCPSocket::is_connected() +{ + return _socket && _iface->socket_is_connected(_socket); +} + +int TCPSocket::send(const void *data, unsigned size) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_send(_socket, data, size); +} + +int TCPSocket::recv(void *data, unsigned size) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_recv(_socket, data, size); +}
--- a/TCPSocket.h Tue Apr 05 09:20:32 2016 -0500 +++ b/TCPSocket.h Tue Apr 05 10:40:34 2016 -0500 @@ -36,7 +36,7 @@ \param port The host's port to connect to \return 0 on success, negative on failure */ - int connect(const char* host, const int port); + int connect(const char *host, uint16_t port); /** Connects this TCP socket to the server \param address SocketAddress to connect to @@ -67,13 +67,16 @@ \param callback Function to call when send will succeed, may be called in interrupt context. */ - void attach_send(FuncPtr<void()> callback); + void attach_send(mbed::FuncPtr<void()> callback); /** Register a callback on when recv is ready \param callback Function to call when recv will succeed, may be called in interrupt context. */ - void attach_recv(FuncPtr<void()> callback); + void attach_recv(mbed::FuncPtr<void()> callback); + +private: + friend class TCPServer; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UDPSocket.cpp Tue Apr 05 10:40:34 2016 -0500 @@ -0,0 +1,50 @@ +/* Socket + * 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. + */ + +#include "UDPSocket.h" + +UDPSocket::UDPSocket(NetworkInterface *iface) + : Socket(iface, NetworkInterface::UDP) +{ +} + +int UDPSocket::bind(uint16_t port) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_bind(_socket, port); +} + +int UDPSocket::sendto(SocketAddress address, const void *data, unsigned size) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_sendto(_socket, address, data, size); +} + +int UDPSocket::recvfrom(SocketAddress *address, void *buffer, unsigned size) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + + return _iface->socket_recvfrom(_socket, address, buffer, size); +} +
--- a/UDPSocket.h Tue Apr 05 09:20:32 2016 -0500 +++ b/UDPSocket.h Tue Apr 05 10:40:34 2016 -0500 @@ -34,7 +34,7 @@ \param port The port to listen for incoming connections on \return 0 on success, negative on failure. */ - int bind(int port); + int bind(uint16_t port); /** Send a packet to a remote endpoint \param address The remote SocketAddress @@ -58,13 +58,13 @@ \param callback Function to call when send will succeed, may be called in interrupt context. */ - void attach_send(FuncPtr<void()> callback); + void attach_send(mbed::FuncPtr<void()> callback); /** Register a callback on when recv is ready \param callback Function to call when recv will succeed, may be called in interrupt context. */ - void attach_recv(FuncPtr<void()> callback); + void attach_recv(mbed::FuncPtr<void()> callback); }; #endif