mirror of https://github.com/ARMmbed/mbed-os.git
Matched changes NetworkSocketAPI
Responded to feedback from mbed-client implementation to introduce a full feature set that should support most of the use cases for the API.pull/2216/head^2
parent
9f668f1a8f
commit
4c7992cb24
|
@ -109,33 +109,7 @@ static bool resolve(unsigned char *resp, char *ipaddress)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t query(UDPSocket *socket, const SocketAddress &addr, const char *hostname, char *ipaddress)
|
||||||
int32_t dnsQuery(NetworkInterface *iface, const char *host, char *ip)
|
|
||||||
{
|
|
||||||
if (isIP(host)) {
|
|
||||||
strcpy(ip, host);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UDPSocket sock(iface);
|
|
||||||
int32_t err;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < DNS_COUNT; i++) {
|
|
||||||
err = sock.open(DNS_IPS[0], 53);
|
|
||||||
if (err < 0) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = dnsQuery(&sock, host, ip);
|
|
||||||
sock.close();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
sock.close();
|
|
||||||
return NS_ERROR_DNS_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t dnsQuery(UDPSocket *socket, const char *hostname, char *ipaddress)
|
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
if (hostname == NULL) {
|
if (hostname == NULL) {
|
||||||
|
@ -184,7 +158,7 @@ int32_t dnsQuery(UDPSocket *socket, const char *hostname, char *ipaddress)
|
||||||
packet[c++] = 1;
|
packet[c++] = 1;
|
||||||
|
|
||||||
|
|
||||||
if (socket->send(packet, packetlen) < 0) {
|
if (socket->sendto(addr, packet, packetlen) < 0) {
|
||||||
delete packet;
|
delete packet;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -194,21 +168,49 @@ int32_t dnsQuery(UDPSocket *socket, const char *hostname, char *ipaddress)
|
||||||
|
|
||||||
// Receive the answer from DNS
|
// Receive the answer from DNS
|
||||||
int response_length = 0;
|
int response_length = 0;
|
||||||
response_length = socket->recv(packet, 1024);
|
response_length = socket->recvfrom(NULL, packet, 1024);
|
||||||
|
|
||||||
if (response_length > 0 ) {
|
if (response_length > 0 ) {
|
||||||
if (!resolve(packet, ipaddress)) {
|
if (!resolve(packet, ipaddress)) {
|
||||||
delete packet;
|
delete packet;
|
||||||
return NS_ERROR_DNS_FAILURE;
|
return NSAPI_ERROR_DNS_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanup and return
|
// cleanup and return
|
||||||
delete packet;
|
delete packet;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete packet;
|
delete packet;
|
||||||
return NS_ERROR_DNS_FAILURE;
|
return NSAPI_ERROR_DNS_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t dnsQuery(NetworkInterface *iface, const char *host, char *ip)
|
||||||
|
{
|
||||||
|
if (isIP(host)) {
|
||||||
|
strcpy(ip, host);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UDPSocket sock(iface);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < DNS_COUNT; i++) {
|
||||||
|
return query(&sock, SocketAddress(DNS_IPS[0], 53), host, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NSAPI_ERROR_DNS_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t dnsQuery(UDPSocket *socket, const char *host, char *ip)
|
||||||
|
{
|
||||||
|
if (isIP(host)) {
|
||||||
|
strcpy(ip, host);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < DNS_COUNT; i++) {
|
||||||
|
return query(socket, SocketAddress(DNS_IPS[0], 53), host, ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NSAPI_ERROR_DNS_FAILURE;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* EthernetInterface Base Class
|
/* Socket
|
||||||
* Copyright (c) 2015 ARM Limited
|
* Copyright (c) 2015 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -26,14 +26,14 @@ class EthernetInterface : public NetworkInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Start the interface
|
/** Start the interface
|
||||||
* @return 0 on success
|
* @return 0 on success, negative on failure
|
||||||
*/
|
*/
|
||||||
virtual int32_t connect() = 0;
|
virtual int connect() = 0;
|
||||||
|
|
||||||
/** Stop the interface
|
/** Stop the interface
|
||||||
* @return 0 on success
|
* @return 0 on success, negative on failure
|
||||||
*/
|
*/
|
||||||
virtual int32_t disconnect() = 0;
|
virtual int disconnect() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MESH_INTERFACE_H
|
||||||
|
#define MESH_INTERFACE_H
|
||||||
|
|
||||||
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
|
/** MeshInterface class
|
||||||
|
* Common interface that is shared between ethernet hardware
|
||||||
|
*/
|
||||||
|
class MeshInterface : public NetworkInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Start the interface
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
virtual int connect() = 0;
|
||||||
|
|
||||||
|
/** Stop the interface
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
virtual int disconnect() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,4 @@
|
||||||
/* NetworkInterface Base Class
|
/* Socket
|
||||||
* Copyright (c) 2015 ARM Limited
|
* Copyright (c) 2015 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -14,16 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "NetworkInterface.h"
|
|
||||||
#include "DnsQuery.h"
|
#include "DnsQuery.h"
|
||||||
|
#include "mbed.h"
|
||||||
|
|
||||||
|
int NetworkInterface::gethostbyname(const char *name, char *dest)
|
||||||
bool NetworkInterface::isConnected()
|
|
||||||
{
|
{
|
||||||
return getIPAddress() != 0;
|
return dnsQuery(this, name, dest);
|
||||||
}
|
|
||||||
|
|
||||||
int32_t NetworkInterface::getHostByName(const char *name, char *ip)
|
|
||||||
{
|
|
||||||
return dnsQuery(this, name, ip);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* NetworkInterface Base Class
|
/* Socket
|
||||||
* Copyright (c) 2015 ARM Limited
|
* Copyright (c) 2015 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -17,29 +17,37 @@
|
||||||
#ifndef NETWORK_INTERFACE_H
|
#ifndef NETWORK_INTERFACE_H
|
||||||
#define NETWORK_INTERFACE_H
|
#define NETWORK_INTERFACE_H
|
||||||
|
|
||||||
#include "SocketInterface.h"
|
#include "mbed.h"
|
||||||
#include "stdint.h"
|
#include "SocketAddress.h"
|
||||||
|
|
||||||
/** Maximum storage needed for IP address and MAC addresses
|
/** Enum of standardized error codes
|
||||||
*/
|
|
||||||
#define NS_IP_SIZE 16
|
|
||||||
#define NS_MAC_SIZE 18
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @enum ns_error_t
|
* @enum ns_error_t
|
||||||
* @brief enum of standardized error codes
|
|
||||||
*/
|
*/
|
||||||
enum ns_error_t {
|
enum nsapi_error_t {
|
||||||
NS_ERROR_WOULD_BLOCK = -3000, /*!< no data is not available but call is non-blocking */
|
NSAPI_ERROR_WOULD_BLOCK = -3001, /*!< no data is not available but call is non-blocking */
|
||||||
NS_ERROR_TIMEOUT = -3001, /*!< operation took longer than allowed */
|
NSAPI_ERROR_UNSUPPORTED = -3002, /*!< unsupported configuration */
|
||||||
NS_ERROR_NO_CONNECTION = -3002, /*!< not connected to a network */
|
NSAPI_ERROR_NO_CONNECTION = -3003, /*!< not connected to a network */
|
||||||
NS_ERROR_NO_SOCKET = -3003, /*!< socket not available for use */
|
NSAPI_ERROR_NO_SOCKET = -3004, /*!< socket not available for use */
|
||||||
NS_ERROR_NO_ADDRESS = -3004, /*!< IP address is not known */
|
NSAPI_ERROR_NO_ADDRESS = -3005, /*!< IP address is not known */
|
||||||
NS_ERROR_NO_MEMORY = -3005, /*!< memory resource not available */
|
NSAPI_ERROR_NO_MEMORY = -3006, /*!< memory resource not available */
|
||||||
NS_ERROR_DNS_FAILURE = -3006, /*!< DNS failed to complete successfully */
|
NSAPI_ERROR_DNS_FAILURE = -3007, /*!< DNS failed to complete successfully */
|
||||||
NS_ERROR_DHCP_FAILURE = -3007, /*!< DHCP failed to complete successfully */
|
NSAPI_ERROR_DHCP_FAILURE = -3008, /*!< DHCP failed to complete successfully */
|
||||||
NS_ERROR_AUTH_FAILURE = -3008, /*!< connection to access point faield */
|
NSAPI_ERROR_AUTH_FAILURE = -3009, /*!< connection to access point faield */
|
||||||
NS_ERROR_DEVICE_ERROR = -3009 /*!< failure interfacing with the network procesor */
|
NSAPI_ERROR_DEVICE_ERROR = -3010, /*!< failure interfacing with the network procesor */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Enum of available options
|
||||||
|
* @enum ns_opt_t
|
||||||
|
*/
|
||||||
|
enum ns_opt_t {
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Enum of socket protocols
|
||||||
|
* @enum protocol_t
|
||||||
|
*/
|
||||||
|
enum nsapi_protocol_t {
|
||||||
|
NSAPI_TCP, /*!< Socket is of TCP type */
|
||||||
|
NSAPI_UDP, /*!< Socket is of UDP type */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** NetworkInterface class
|
/** NetworkInterface class
|
||||||
|
@ -51,42 +59,175 @@ class NetworkInterface
|
||||||
public:
|
public:
|
||||||
virtual ~NetworkInterface() {};
|
virtual ~NetworkInterface() {};
|
||||||
|
|
||||||
/** Get the IP address
|
/** Get the internally stored IP address
|
||||||
* @return IP address of the interface or 0 if not yet connected
|
* @return IP address of the interface or null if not yet connected
|
||||||
*/
|
*/
|
||||||
virtual const char *getIPAddress() = 0;
|
virtual const char *get_ip_address() = 0;
|
||||||
|
|
||||||
/** Get the current MAC address
|
/** Get the internally stored MAC address
|
||||||
* @return String MAC address of the interface
|
* @return MAC address of the interface
|
||||||
*/
|
*/
|
||||||
virtual const char *getMACAddress() = 0;
|
virtual const char *get_mac_address() = 0;
|
||||||
|
|
||||||
/** Get the current status of the interface
|
/** Get the current status of the interface
|
||||||
* @return true if connected
|
* @return true if connected
|
||||||
*/
|
*/
|
||||||
virtual bool isConnected();
|
virtual bool is_connected() {
|
||||||
|
return get_ip_address() != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/** Looks up the specified host's IP address
|
/** Looks up the specified host's IP address
|
||||||
* @param name URL of host
|
* @param name Hostname to lookup
|
||||||
* @param ip Buffer to hold IP address, must be at least SOCK_IP_SIZE
|
* @param dest Destination for IP address, must have space for SocketAddress::IP_SIZE
|
||||||
* @return 0 on success
|
* @return 0 on success, negative on failure
|
||||||
*/
|
*/
|
||||||
virtual int32_t getHostByName(const char *name, char *ip);
|
virtual int gethostbyname(const char *name, char *dest);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Socket;
|
friend class Socket;
|
||||||
|
friend class UDPSocket;
|
||||||
|
friend class TCPSocket;
|
||||||
|
friend class TCPServer;
|
||||||
|
|
||||||
/** Internally create a socket
|
/** Create a socket
|
||||||
* @param proto The type of socket to open, NS_TCP or NS_UDP
|
* @param proto The type of socket to open, TCP or UDP
|
||||||
* @return The allocated socket
|
* @return The alocated socket or null on failure
|
||||||
*/
|
*/
|
||||||
virtual SocketInterface *createSocket(ns_protocol_t proto) = 0;
|
virtual void *socket_create(nsapi_protocol_t proto) = 0;
|
||||||
|
|
||||||
/** Internally destroy a socket
|
/** Destroy a socket
|
||||||
* @param socket An allocated SocketInterface
|
* @param socket Previously allocated socket
|
||||||
* @returns 0 on success
|
|
||||||
*/
|
*/
|
||||||
virtual void destroySocket(SocketInterface *socket) = 0;
|
virtual void socket_destroy(void *handle) = 0;
|
||||||
|
|
||||||
|
/** Set socket options
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param optname Option ID
|
||||||
|
* @param optval Option value
|
||||||
|
* @param optlen Length of the option value
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
virtual int socket_set_option(void *handle, int optname, const void *optval, unsigned int optlen) = 0;
|
||||||
|
|
||||||
|
/** Get socket options
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param optname Option ID
|
||||||
|
* @param optval Buffer pointer where to write the option value
|
||||||
|
* @param optlen Length of the option value
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
virtual int socket_get_option(void *handle, int optname, void *optval, unsigned int *optlen) = 0;
|
||||||
|
|
||||||
|
/** Bind a server socket to a specific port
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param port The port to listen for incoming connections on
|
||||||
|
* @return 0 on success, negative on failure.
|
||||||
|
*/
|
||||||
|
virtual int socket_bind(void *handle, int port) = 0;
|
||||||
|
|
||||||
|
/** Start listening for incoming connections
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param backlog Number of pending connections that can be queued up at any
|
||||||
|
* one time [Default: 1]
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
virtual int socket_listen(void *handle, int backlog) = 0;
|
||||||
|
|
||||||
|
/** Connects this TCP socket to the server
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param address SocketAddress to connect to
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
virtual int socket_connect(void *handle, const SocketAddress &address) = 0;
|
||||||
|
|
||||||
|
/** Check if the socket is connected
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @return true if connected, false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool socket_is_connected(void *handle) = 0;
|
||||||
|
|
||||||
|
/** Accept a new connection.
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param socket A TCPSocket instance that will handle the incoming connection.
|
||||||
|
* @return 0 on success, negative on failure.
|
||||||
|
* @note This call is not-blocking, if this call would block, must
|
||||||
|
* immediately return NSAPI_ERROR_WOULD_WAIT
|
||||||
|
*/
|
||||||
|
virtual int socket_accept(void *handle, void **connection) = 0;
|
||||||
|
|
||||||
|
/** Send data to the remote host
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param data The buffer to send to the host
|
||||||
|
* @param size The length of the buffer to send
|
||||||
|
* @return Number of written bytes on success, negative on failure
|
||||||
|
* @note This call is not-blocking, if this call would block, must
|
||||||
|
* immediately return NSAPI_ERROR_WOULD_WAIT
|
||||||
|
*/
|
||||||
|
virtual int socket_send(void *handle, const void *data, unsigned size) = 0;
|
||||||
|
|
||||||
|
/** Receive data from the remote host
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param data The buffer in which to store the data received from the host
|
||||||
|
* @param size The maximum length of the buffer
|
||||||
|
* @return Number of received bytes on success, negative on failure
|
||||||
|
* @note This call is not-blocking, if this call would block, must
|
||||||
|
* immediately return NSAPI_ERROR_WOULD_WAIT
|
||||||
|
*/
|
||||||
|
virtual int socket_recv(void *handle, void *data, unsigned size) = 0;
|
||||||
|
|
||||||
|
/** Send a packet to a remote endpoint
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param address The remote SocketAddress
|
||||||
|
* @param data The packet to be sent
|
||||||
|
* @param size The length of the packet to be sent
|
||||||
|
* @return the number of written bytes on success, negative on failure
|
||||||
|
* @note This call is not-blocking, if this call would block, must
|
||||||
|
* immediately return NSAPI_ERROR_WOULD_WAIT
|
||||||
|
*/
|
||||||
|
virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size) = 0;
|
||||||
|
|
||||||
|
/** Receive a packet from a remote endpoint
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param address Destination for the remote SocketAddress or null
|
||||||
|
* @param buffer The buffer for storing the incoming packet data
|
||||||
|
* If a packet is too long to fit in the supplied buffer,
|
||||||
|
* excess bytes are discarded
|
||||||
|
* @param size The length of the buffer
|
||||||
|
* @return the number of received bytes on success, negative on failure
|
||||||
|
* @note This call is not-blocking, if this call would block, must
|
||||||
|
* immediately return NSAPI_ERROR_WOULD_WAIT
|
||||||
|
*/
|
||||||
|
virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size) = 0;
|
||||||
|
|
||||||
|
/** Close the socket
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param shutdown free the left-over data in message queues
|
||||||
|
*/
|
||||||
|
virtual int socket_close(void *handle, bool shutdown) = 0;
|
||||||
|
|
||||||
|
/** Register a callback on when a new connection is ready
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param callback Function to call when accept will succeed, may be called in
|
||||||
|
* interrupt context.
|
||||||
|
* @param id Argument to pass to callback
|
||||||
|
*/
|
||||||
|
virtual void socket_attach_accept(void *handle, void (*callback)(void *), void *id) = 0;
|
||||||
|
|
||||||
|
/** Register a callback on when send is ready
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param callback Function to call when accept will succeed, may be called in
|
||||||
|
* interrupt context.
|
||||||
|
* @param id Argument to pass to callback
|
||||||
|
*/
|
||||||
|
virtual void socket_attach_send(void *handle, void (*callback)(void *), void *id) = 0;
|
||||||
|
|
||||||
|
/** Register a callback on when recv is ready
|
||||||
|
* @param handle Socket handle
|
||||||
|
* @param callback Function to call when accept will succeed, may be called in
|
||||||
|
* interrupt context.
|
||||||
|
* @param id Argument to pass to callback
|
||||||
|
*/
|
||||||
|
virtual void socket_attach_recv(void *handle, void (*callback)(void *), void *id) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
124
Socket.cpp
124
Socket.cpp
|
@ -15,116 +15,68 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
Socket::Socket(NetworkInterface *iface, ns_protocol_t proto)
|
Socket::Socket(NetworkInterface *iface, nsapi_protocol_t proto)
|
||||||
: _iface(iface)
|
: _iface(iface)
|
||||||
, _proto(proto)
|
, _blocking(true)
|
||||||
, _socket(0)
|
, _timeout(0)
|
||||||
{
|
{
|
||||||
memset(_ip_address, 0, NS_IP_SIZE);
|
_socket = _iface->socket_create(proto);
|
||||||
_port = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket::~Socket()
|
Socket::~Socket()
|
||||||
{
|
{
|
||||||
if (_socket) {
|
if (_socket) {
|
||||||
close();
|
close(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Socket::set_blocking(bool blocking)
|
||||||
int32_t Socket::open(const char *address, uint16_t port)
|
|
||||||
{
|
{
|
||||||
int32_t err;
|
_blocking = blocking;
|
||||||
|
|
||||||
err = close();
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _iface->getHostByName(address, _ip_address);
|
|
||||||
_port = port;
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
_socket = _iface->createSocket(_proto);
|
|
||||||
if (!_socket) {
|
|
||||||
return NS_ERROR_NO_SOCKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _socket->open(_ip_address, _port);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
_iface->destroySocket(_socket);
|
|
||||||
_socket = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Socket::close()
|
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) {
|
if (!_socket) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketInterface *socket = _socket;
|
|
||||||
_socket = 0;
|
|
||||||
|
|
||||||
int32_t err = socket->close();
|
int err = _iface->socket_close(_socket, shutdown);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
_iface->destroySocket(socket);
|
void *socket = _socket;
|
||||||
|
_socket = 0;
|
||||||
|
_iface->socket_destroy(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Socket::send(const void *data, uint32_t size)
|
void Socket::thunk(void *p)
|
||||||
{
|
{
|
||||||
if (!_socket) {
|
FunctionPointer *fptr = (FunctionPointer *)p;
|
||||||
return NS_ERROR_NO_CONNECTION;
|
(*fptr)();
|
||||||
}
|
|
||||||
return _socket->send(data, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Socket::recv(void *data, uint32_t size, bool blocking)
|
|
||||||
{
|
|
||||||
while (true) {
|
|
||||||
if (!_socket) {
|
|
||||||
return NS_ERROR_NO_CONNECTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t recv = _socket->recv(data, size);
|
|
||||||
|
|
||||||
if (recv != NS_ERROR_WOULD_BLOCK || !blocking) {
|
|
||||||
return recv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *Socket::getIPAddress() const
|
|
||||||
{
|
|
||||||
if (_ip_address[0]) {
|
|
||||||
return _ip_address;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t Socket::getPort() const
|
|
||||||
{
|
|
||||||
return _port;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Socket::isConnected()
|
|
||||||
{
|
|
||||||
if (!_socket) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _socket->isConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
82
Socket.h
82
Socket.h
|
@ -17,69 +17,57 @@
|
||||||
#ifndef SOCKET_H
|
#ifndef SOCKET_H
|
||||||
#define SOCKET_H
|
#define SOCKET_H
|
||||||
|
|
||||||
|
#include "SocketAddress.h"
|
||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
/** Abstract socket class
|
/** Abstract socket class
|
||||||
* API for handling general sockets. Supports IP address operations
|
|
||||||
* and sending/recieving data.
|
|
||||||
*/
|
*/
|
||||||
class Socket
|
class Socket {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
~Socket();
|
/** Socket lifetime
|
||||||
|
|
||||||
/** Open a connection to the underlying address
|
|
||||||
* @param address URL or IP address to connect to
|
|
||||||
* @param port Port to connect to
|
|
||||||
* @return 0 on success
|
|
||||||
*/
|
*/
|
||||||
int32_t open(const char *address, uint16_t port);
|
virtual ~Socket();
|
||||||
|
|
||||||
/** Close an open connection
|
/** Set blocking or non-blocking mode of the socket
|
||||||
* @return 0 on success
|
* @param blocking true for blocking mode, false for non-blocking mode.
|
||||||
*/
|
*/
|
||||||
int32_t close();
|
void set_blocking(bool blocking);
|
||||||
|
|
||||||
/** Send data over the socket
|
/** Set timeout on a socket operation if blocking behaviour is enabled
|
||||||
* @param data Buffer of data to send
|
* @param timeout timeout in ms
|
||||||
* @param size Size of data to send
|
|
||||||
* @return Number of bytes sent or a negative value on failure
|
|
||||||
*/
|
*/
|
||||||
int32_t send(const void *data, uint32_t size);
|
void set_timeout(unsigned int timeout);
|
||||||
|
|
||||||
/** Recieve data over the socket
|
/* Set socket options
|
||||||
* @param data Buffer to store recieved data
|
* @param optname Option ID
|
||||||
* @param size Size of provided buffer
|
* @param optval Option value
|
||||||
* @param blocking If true wait for data, otherwise return NS_ERROR_WOULD_BLOCK
|
* @param optlen Length of the option value
|
||||||
* @return Number of bytes recieved or a negative value on failure
|
* @return 0 on success, negative on failure
|
||||||
*/
|
*/
|
||||||
int32_t recv(void *data, uint32_t size, bool blocking = true);
|
int set_option(int optname, const void *optval, unsigned optlen);
|
||||||
|
|
||||||
/** Gets the IP address
|
/* Get socket options
|
||||||
* @return IP address to connect to
|
* @param optname Option ID
|
||||||
|
* @param optval Buffer pointer where to write the option value
|
||||||
|
* @param optlen Length of the option value
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
*/
|
*/
|
||||||
const char *getIPAddress() const;
|
int get_option(int optname, void *optval, unsigned *optlen);
|
||||||
|
|
||||||
/** Gets the port
|
/** Close the socket
|
||||||
* @return Port to connect to
|
* @param shutdown free the left-over data in message queues
|
||||||
*/
|
*/
|
||||||
uint16_t getPort() const;
|
int close(bool shutdown=true);
|
||||||
|
|
||||||
/** Returns status of socket
|
|
||||||
* @return true if connected
|
|
||||||
*/
|
|
||||||
bool isConnected();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Socket(NetworkInterface *iface, ns_protocol_t proto);
|
Socket(NetworkInterface *iface, nsapi_protocol_t proto);
|
||||||
|
|
||||||
|
static void thunk(void *);
|
||||||
|
|
||||||
private:
|
|
||||||
NetworkInterface *_iface;
|
NetworkInterface *_iface;
|
||||||
ns_protocol_t _proto;
|
void *_socket;
|
||||||
SocketInterface *_socket;
|
bool _blocking;
|
||||||
|
unsigned _timeout;
|
||||||
char _ip_address[NS_IP_SIZE];
|
|
||||||
uint16_t _port;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* 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 "NetworkInterface.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "mbed.h"
|
||||||
|
|
||||||
|
SocketAddress::SocketAddress(NetworkInterface *iface, const char *host, uint16_t port)
|
||||||
|
{
|
||||||
|
int err = iface->gethostbyname(host, _ip_address);
|
||||||
|
set_port(port);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
_ip_address[0] = '\0';
|
||||||
|
_port = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (!_ip_address[0]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return _ip_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t SocketAddress::get_port() const
|
||||||
|
{
|
||||||
|
return _port;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOCKET_ADDRESS_H
|
||||||
|
#define SOCKET_ADDRESS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/** Maximum size of IP address
|
||||||
|
*/
|
||||||
|
#define NSAPI_IP_SIZE 16
|
||||||
|
|
||||||
|
/** Maximum size of MAC address
|
||||||
|
*/
|
||||||
|
#define NSAPI_MAC_SIZE 18
|
||||||
|
|
||||||
|
// Predeclared classes
|
||||||
|
class NetworkInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A general socket address composed of the IP address and port
|
||||||
|
*/
|
||||||
|
class SocketAddress {
|
||||||
|
public:
|
||||||
|
/** SocketAddress construction using DNS resolution
|
||||||
|
* @param iface NetworkInterface to use for DNS resolution
|
||||||
|
* @param addr Null-terminated hostname that will be resolved
|
||||||
|
* @param port 16-bit port
|
||||||
|
* @note on failure, IP address and port will be set to null
|
||||||
|
*/
|
||||||
|
SocketAddress(NetworkInterface *iface, const char *addr, uint16_t port = 0);
|
||||||
|
|
||||||
|
/** SocketAddress construction
|
||||||
|
* @param addr Null-terminated IP address
|
||||||
|
* @param port 16-bit port
|
||||||
|
* @note on failure, IP address and port will be set to null
|
||||||
|
*/
|
||||||
|
SocketAddress(const char *addr = 0, uint16_t port = 0);
|
||||||
|
|
||||||
|
/** SocketAddress construction
|
||||||
|
* @param addr SocketAddress to copy
|
||||||
|
*/
|
||||||
|
SocketAddress(const SocketAddress &addr);
|
||||||
|
|
||||||
|
/** Set the IP address
|
||||||
|
* @param addr Null-terminated string representing the IP address
|
||||||
|
*/
|
||||||
|
void set_ip_address(const char *addr);
|
||||||
|
|
||||||
|
/** Set the port
|
||||||
|
* @param port 16-bit port
|
||||||
|
*/
|
||||||
|
void set_port(uint16_t port);
|
||||||
|
|
||||||
|
/** Get the IP address
|
||||||
|
* @return The string representation of the IP Address
|
||||||
|
*/
|
||||||
|
const char *get_ip_address() const;
|
||||||
|
|
||||||
|
/** Get the port
|
||||||
|
* @return The 16-bit port
|
||||||
|
*/
|
||||||
|
uint16_t get_port(void) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
char _ip_address[NSAPI_IP_SIZE];
|
||||||
|
uint16_t _port;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,83 +0,0 @@
|
||||||
/* SocketInterface Base Class
|
|
||||||
* 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 SOCKET_INTERFACE_H
|
|
||||||
#define SOCKET_INTERFACE_H
|
|
||||||
|
|
||||||
#include "stdint.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @enum ns_protocol_t
|
|
||||||
* @brief enum of socket protocols
|
|
||||||
*/
|
|
||||||
enum ns_protocol_t {
|
|
||||||
NS_TCP, /*!< Socket is of TCP type */
|
|
||||||
NS_UDP, /*!< Socket is of UDP type */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** SocketInterface class
|
|
||||||
* Common interface for implementation specific sockets created through
|
|
||||||
* network interfaces. This class is used internally by the
|
|
||||||
* TCPSocket and UDPSocket classes
|
|
||||||
*/
|
|
||||||
class SocketInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~SocketInterface() {}
|
|
||||||
|
|
||||||
/** Open a connection to the underlying address
|
|
||||||
* @param ip IP address to connect to
|
|
||||||
* @param port Port to connect to
|
|
||||||
* @return 0 on success
|
|
||||||
*/
|
|
||||||
virtual int32_t open(const char *ip, uint16_t port) = 0;
|
|
||||||
|
|
||||||
/** Close an open connection
|
|
||||||
* @return 0 on success
|
|
||||||
*/
|
|
||||||
virtual int32_t close() = 0;
|
|
||||||
|
|
||||||
/** Send data
|
|
||||||
* @param data Buffer of data to send
|
|
||||||
* @param size Size of data to send
|
|
||||||
* @return Number of bytes received or a negative value on success
|
|
||||||
*/
|
|
||||||
virtual int32_t send(const void *data, uint32_t size) = 0;
|
|
||||||
|
|
||||||
/** Receive data
|
|
||||||
* @note
|
|
||||||
* This call should return immediately with a value of
|
|
||||||
* NS_ERROR_WOULD_BOCK if no data is available.
|
|
||||||
*
|
|
||||||
* @param data A buffer to store the data in
|
|
||||||
* @param size Size of buffer
|
|
||||||
* @return Number of bytes received or a negative value on failure
|
|
||||||
*/
|
|
||||||
virtual int32_t recv(void *data, uint32_t size) = 0;
|
|
||||||
|
|
||||||
/** Status of the socket
|
|
||||||
* @return True if connected
|
|
||||||
*/
|
|
||||||
virtual bool isConnected() {
|
|
||||||
// By default return true if socket was created successfully
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* 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"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
TCPServer::TCPServer(NetworkInterface *iface)
|
||||||
|
: Socket(iface, NSAPI_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)
|
||||||
|
{
|
||||||
|
mbed::Timer timer;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
void *socket = connection->_socket;
|
||||||
|
connection->_socket = 0;
|
||||||
|
_iface->socket_destroy(socket);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!_socket) {
|
||||||
|
return NSAPI_ERROR_NO_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = _iface->socket_accept(_socket, &socket);
|
||||||
|
|
||||||
|
if (err > 0) {
|
||||||
|
connection->_socket = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != NSAPI_ERROR_WOULD_BLOCK || !_blocking ||
|
||||||
|
(_timeout && timer.read_ms() > _timeout)) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TCPServer::attach_accept(FunctionPointer callback)
|
||||||
|
{
|
||||||
|
_accept_cb = callback;
|
||||||
|
|
||||||
|
if (_socket && _accept_cb) {
|
||||||
|
return _iface->socket_attach_accept(_socket, Socket::thunk, &_accept_cb);
|
||||||
|
} else if (_socket) {
|
||||||
|
return _iface->socket_attach_accept(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPServer::~TCPServer()
|
||||||
|
{
|
||||||
|
if (_socket && _accept_cb) {
|
||||||
|
_iface->socket_attach_accept(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TCPSERVER_H
|
||||||
|
#define TCPSERVER_H
|
||||||
|
|
||||||
|
#include "Socket.h"
|
||||||
|
#include "TCPSocket.h"
|
||||||
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
|
/** TCP Server.
|
||||||
|
*/
|
||||||
|
class TCPServer : public Socket {
|
||||||
|
public:
|
||||||
|
/** TCP Server lifetime
|
||||||
|
*/
|
||||||
|
TCPServer(NetworkInterface *iface);
|
||||||
|
virtual ~TCPServer();
|
||||||
|
|
||||||
|
/** Bind a socket to a specific port
|
||||||
|
* @param port The port to listen for incoming connections on
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
int bind(uint16_t port);
|
||||||
|
|
||||||
|
/** Start listening for incoming connections
|
||||||
|
* @param backlog Number of pending connections that can be queued up at any
|
||||||
|
* one time [Default: 1]
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
int listen(int backlog=1);
|
||||||
|
|
||||||
|
/** Accept a new connection.
|
||||||
|
* @param socket A TCPSocket instance that will handle the incoming connection.
|
||||||
|
* @return 0 on success, negative on failure.
|
||||||
|
*/
|
||||||
|
int accept(TCPSocket *connection);
|
||||||
|
|
||||||
|
/** Register a callback on when a new connection is ready
|
||||||
|
* @param callback Function to call when accept will succeed, may be called in
|
||||||
|
* interrupt context.
|
||||||
|
*/
|
||||||
|
void attach_accept(FunctionPointer callback);
|
||||||
|
|
||||||
|
template <typename T, typename M>
|
||||||
|
void attach_accept(T *tptr, M mptr) {
|
||||||
|
attach_accept(FunctionPointer(tptr, mptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionPointer _accept_cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* 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"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
TCPSocket::TCPSocket(NetworkInterface *iface)
|
||||||
|
: Socket(iface, NSAPI_TCP)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int TCPSocket::connect(const 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, 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)
|
||||||
|
{
|
||||||
|
mbed::Timer timer;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!_socket) {
|
||||||
|
return NSAPI_ERROR_NO_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sent = _iface->socket_send(_socket, data, size);
|
||||||
|
if (sent != NSAPI_ERROR_WOULD_BLOCK || !_blocking ||
|
||||||
|
(_timeout && timer.read_ms() > _timeout)) {
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TCPSocket::recv(void *data, unsigned size)
|
||||||
|
{
|
||||||
|
mbed::Timer timer;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!_socket) {
|
||||||
|
return NSAPI_ERROR_NO_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recv = _iface->socket_recv(_socket, data, size);
|
||||||
|
if (recv != NSAPI_ERROR_WOULD_BLOCK || !_blocking ||
|
||||||
|
(_timeout && timer.read_ms() > _timeout)) {
|
||||||
|
return recv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TCPSocket::attach_send(FunctionPointer callback)
|
||||||
|
{
|
||||||
|
_send_cb = callback;
|
||||||
|
|
||||||
|
if (_socket && _send_cb) {
|
||||||
|
return _iface->socket_attach_send(_socket, Socket::thunk, &_send_cb);
|
||||||
|
} else if (_socket) {
|
||||||
|
return _iface->socket_attach_send(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TCPSocket::attach_recv(FunctionPointer callback)
|
||||||
|
{
|
||||||
|
_recv_cb = callback;
|
||||||
|
|
||||||
|
if (_socket && _recv_cb) {
|
||||||
|
return _iface->socket_attach_recv(_socket, Socket::thunk, &_recv_cb);
|
||||||
|
} else if (_socket) {
|
||||||
|
return _iface->socket_attach_recv(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPSocket::~TCPSocket()
|
||||||
|
{
|
||||||
|
if (_socket && _send_cb) {
|
||||||
|
_iface->socket_attach_send(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_socket && _recv_cb) {
|
||||||
|
_iface->socket_attach_recv(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
85
TCPSocket.h
85
TCPSocket.h
|
@ -1,4 +1,4 @@
|
||||||
/* TCPSocket
|
/* Socket
|
||||||
* Copyright (c) 2015 ARM Limited
|
* Copyright (c) 2015 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -14,26 +14,81 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TCP_SOCKET_H
|
#ifndef TCPSOCKET_H
|
||||||
#define TCP_SOCKET_H
|
#define TCPSOCKET_H
|
||||||
|
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
/** TCPSocket class
|
/** TCP socket connection
|
||||||
* API for handling TCP sockets. The implementation is determined
|
|
||||||
* by the interface passed during construction.
|
|
||||||
*/
|
*/
|
||||||
class TCPSocket : public Socket
|
class TCPSocket : public Socket {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/** Create a socket using the specified network interface
|
/** TCP socket lifetime
|
||||||
* No network operations are performed until the socket is actually used
|
|
||||||
* @param iface The network interface to use
|
|
||||||
* @param url Optional URL to connect to, copied internally
|
|
||||||
* @param port Optional port to connect to
|
|
||||||
*/
|
*/
|
||||||
TCPSocket(NetworkInterface *iface)
|
TCPSocket(NetworkInterface *iface);
|
||||||
: Socket(iface, NS_TCP) {}
|
virtual ~TCPSocket();
|
||||||
|
|
||||||
|
/** Connects this TCP socket to the server
|
||||||
|
* @param host The host to connect to. It can either be an IP Address
|
||||||
|
* or a hostname that will be resolved with DNS
|
||||||
|
* @param port The host's port to connect to
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
int connect(const char *host, uint16_t port);
|
||||||
|
|
||||||
|
/** Connects this TCP socket to the server
|
||||||
|
* @param address SocketAddress to connect to
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
int connect(const SocketAddress &address);
|
||||||
|
|
||||||
|
/** Check if the socket is connected
|
||||||
|
* @return true if connected, false otherwise
|
||||||
|
*/
|
||||||
|
bool is_connected();
|
||||||
|
|
||||||
|
/** Send data to the remote host
|
||||||
|
* @param data The buffer to send to the host
|
||||||
|
* @param size The length of the buffer to send
|
||||||
|
* @return Number of written bytes on success, negative on failure
|
||||||
|
*/
|
||||||
|
int send(const void *data, unsigned size);
|
||||||
|
|
||||||
|
/** Receive data from the remote host
|
||||||
|
* @param data The buffer in which to store the data received from the host
|
||||||
|
* @param size The maximum length of the buffer
|
||||||
|
* @return Number of received bytes on success, negative on failure
|
||||||
|
*/
|
||||||
|
int recv(void *data, unsigned size);
|
||||||
|
|
||||||
|
/** Register a callback on when send is ready
|
||||||
|
* @param callback Function to call when send will succeed, may be called in
|
||||||
|
* interrupt context.
|
||||||
|
*/
|
||||||
|
void attach_send(FunctionPointer callback);
|
||||||
|
|
||||||
|
template <typename T, typename M>
|
||||||
|
void attach_send(T *tptr, M mptr) {
|
||||||
|
attach_send(FunctionPointer(tptr, mptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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(FunctionPointer callback);
|
||||||
|
|
||||||
|
template <typename T, typename M>
|
||||||
|
void attach_recv(T *tptr, M mptr) {
|
||||||
|
attach_recv(FunctionPointer(tptr, mptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class TCPServer;
|
||||||
|
|
||||||
|
FunctionPointer _send_cb;
|
||||||
|
FunctionPointer _recv_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* 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"
|
||||||
|
#include "Timer.h"
|
||||||
|
|
||||||
|
UDPSocket::UDPSocket(NetworkInterface *iface)
|
||||||
|
: Socket(iface, NSAPI_UDP)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDPSocket::bind(uint16_t port)
|
||||||
|
{
|
||||||
|
if (!_socket) {
|
||||||
|
return NSAPI_ERROR_NO_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _iface->socket_bind(_socket, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDPSocket::sendto(const SocketAddress &address, const void *data, unsigned size)
|
||||||
|
{
|
||||||
|
mbed::Timer timer;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!_socket) {
|
||||||
|
return NSAPI_ERROR_NO_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sent = _iface->socket_sendto(_socket, address, data, size);
|
||||||
|
if (sent != NSAPI_ERROR_WOULD_BLOCK || !_blocking ||
|
||||||
|
(_timeout && timer.read_ms() > _timeout)) {
|
||||||
|
return sent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int UDPSocket::recvfrom(SocketAddress *address, void *buffer, unsigned size)
|
||||||
|
{
|
||||||
|
mbed::Timer timer;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!_socket) {
|
||||||
|
return NSAPI_ERROR_NO_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recv = _iface->socket_recvfrom(_socket, address, buffer, size);
|
||||||
|
if (recv != NSAPI_ERROR_WOULD_BLOCK || !_blocking ||
|
||||||
|
(_timeout && timer.read_ms() > _timeout)) {
|
||||||
|
return recv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UDPSocket::attach_send(FunctionPointer callback)
|
||||||
|
{
|
||||||
|
_send_cb = callback;
|
||||||
|
if (_socket && _send_cb) {
|
||||||
|
return _iface->socket_attach_send(_socket, Socket::thunk, &_send_cb);
|
||||||
|
} else if (_socket) {
|
||||||
|
return _iface->socket_attach_send(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDPSocket::attach_recv(FunctionPointer callback)
|
||||||
|
{
|
||||||
|
_recv_cb = callback;
|
||||||
|
if (_socket && _recv_cb) {
|
||||||
|
return _iface->socket_attach_recv(_socket, Socket::thunk, &_recv_cb);
|
||||||
|
} else if (_socket) {
|
||||||
|
return _iface->socket_attach_recv(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UDPSocket::~UDPSocket()
|
||||||
|
{
|
||||||
|
if (_socket && _send_cb) {
|
||||||
|
_iface->socket_attach_send(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_socket && _recv_cb) {
|
||||||
|
_iface->socket_attach_recv(_socket, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
74
UDPSocket.h
74
UDPSocket.h
|
@ -1,4 +1,4 @@
|
||||||
/* UDPSocket
|
/* Socket
|
||||||
* Copyright (c) 2015 ARM Limited
|
* Copyright (c) 2015 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -14,26 +14,70 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UDP_SOCKET_H
|
#ifndef UDPSOCKET_H
|
||||||
#define UDP_SOCKET_H
|
#define UDPSOCKET_H
|
||||||
|
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
/** UDPSocket class
|
/** UDP Socket
|
||||||
* API for handling UDP sockets. The implementation is determined
|
|
||||||
* by the interface passed during construction.
|
|
||||||
*/
|
*/
|
||||||
class UDPSocket : public Socket
|
class UDPSocket : public Socket {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
/** Create a socket using the specified network interface
|
/** UDPSocket lifetime
|
||||||
* No network operations are performed until the socket is actually used
|
|
||||||
* @param iface The network interface to use
|
|
||||||
* @param ip Optional URL to connect to, copied internally
|
|
||||||
* @param port Optional port to connect to
|
|
||||||
*/
|
*/
|
||||||
UDPSocket(NetworkInterface *iface)
|
UDPSocket(NetworkInterface *iface);
|
||||||
: Socket(iface, NS_UDP) {}
|
virtual ~UDPSocket();
|
||||||
|
|
||||||
|
/** Bind a UDP Server Socket to a specific port
|
||||||
|
* @param port The port to listen for incoming connections on
|
||||||
|
* @return 0 on success, negative on failure.
|
||||||
|
*/
|
||||||
|
int bind(uint16_t port);
|
||||||
|
|
||||||
|
/** Send a packet to a remote endpoint
|
||||||
|
* @param address The remote SocketAddress
|
||||||
|
* @param data The packet to be sent
|
||||||
|
* @param size The length of the packet to be sent
|
||||||
|
* @return The number of written bytes on success, negative on failure
|
||||||
|
*/
|
||||||
|
int sendto(const SocketAddress &address, const void *data, unsigned size);
|
||||||
|
|
||||||
|
/** Receive a packet from a remote endpoint
|
||||||
|
* @param address Destination for the remote SocketAddress or null
|
||||||
|
* @param buffer The buffer for storing the incoming packet data
|
||||||
|
* If a packet is too long to fit in the supplied buffer,
|
||||||
|
* excess bytes are discarded
|
||||||
|
* @param size The length of the buffer
|
||||||
|
* @return The number of received bytes on success, negative on failure
|
||||||
|
*/
|
||||||
|
int recvfrom(SocketAddress *address, void *buffer, unsigned size);
|
||||||
|
|
||||||
|
/** Register a callback on when send is ready
|
||||||
|
* @param callback Function to call when send will succeed, may be called in
|
||||||
|
* interrupt context.
|
||||||
|
*/
|
||||||
|
void attach_send(FunctionPointer callback);
|
||||||
|
|
||||||
|
template <typename T, typename M>
|
||||||
|
void attach_send(T *tptr, M mptr) {
|
||||||
|
attach_send(FunctionPointer(tptr, mptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 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(FunctionPointer callback);
|
||||||
|
|
||||||
|
template <typename T, typename M>
|
||||||
|
void attach_recv(T *tptr, M mptr) {
|
||||||
|
attach_recv(FunctionPointer(tptr, mptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FunctionPointer _send_cb;
|
||||||
|
FunctionPointer _recv_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* WiFiInterface Base Class
|
/* Socket
|
||||||
* Copyright (c) 2015 ARM Limited
|
* Copyright (c) 2015 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -21,14 +21,13 @@
|
||||||
|
|
||||||
/** Enum for WiFi encryption types
|
/** Enum for WiFi encryption types
|
||||||
*/
|
*/
|
||||||
enum ns_security_t {
|
enum nsapi_security_t {
|
||||||
NS_SECURITY_NONE = 0, /*!< open access point */
|
NSAPI_SECURITY_NONE = 0, /*!< open access point */
|
||||||
NS_SECURITY_WEP, /*!< phrase conforms to WEP */
|
NSAPI_SECURITY_WEP, /*!< phrase conforms to WEP */
|
||||||
NS_SECURITY_WPA, /*!< phrase conforms to WPA */
|
NSAPI_SECURITY_WPA, /*!< phrase conforms to WPA */
|
||||||
NS_SECURITY_WPA2, /*!< phrase conforms to WPA2 */
|
NSAPI_SECURITY_WPA2, /*!< phrase conforms to WPA2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** WiFiInterface class
|
/** WiFiInterface class
|
||||||
* Common interface that is shared between WiFi devices
|
* Common interface that is shared between WiFi devices
|
||||||
*/
|
*/
|
||||||
|
@ -36,17 +35,17 @@ class WiFiInterface : public NetworkInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/** Start the interface
|
/** Start the interface
|
||||||
* @param ssid Name of the network to connect to
|
* @param ssid Name of the network to connect to
|
||||||
* @param pass Security passphrase to connect to the network
|
* @param pass Security passphrase to connect to the network
|
||||||
* @param security Type of encryption to connect with
|
* @param security Type of encryption for connection
|
||||||
* @return 0 on success
|
* @return 0 on success, negative on failure
|
||||||
*/
|
*/
|
||||||
virtual int32_t connect(const char *ssid, const char *pass, ns_security_t security = NS_SECURITY_NONE) = 0;
|
virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE) = 0;
|
||||||
|
|
||||||
/** Stop the interface
|
/** Stop the interface
|
||||||
* @return 0 on success
|
* @return 0 on success, negative on failure
|
||||||
*/
|
*/
|
||||||
virtual int32_t disconnect() = 0;
|
virtual int disconnect() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue