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;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
static int32_t query(UDPSocket *socket, const SocketAddress &addr, const char *hostname, char *ipaddress)
|
||||
{
|
||||
int len = 0;
|
||||
if (hostname == NULL) {
|
||||
|
@ -184,7 +158,7 @@ int32_t dnsQuery(UDPSocket *socket, const char *hostname, char *ipaddress)
|
|||
packet[c++] = 1;
|
||||
|
||||
|
||||
if (socket->send(packet, packetlen) < 0) {
|
||||
if (socket->sendto(addr, packet, packetlen) < 0) {
|
||||
delete packet;
|
||||
return false;
|
||||
}
|
||||
|
@ -194,12 +168,12 @@ int32_t dnsQuery(UDPSocket *socket, const char *hostname, char *ipaddress)
|
|||
|
||||
// Receive the answer from DNS
|
||||
int response_length = 0;
|
||||
response_length = socket->recv(packet, 1024);
|
||||
response_length = socket->recvfrom(NULL, packet, 1024);
|
||||
|
||||
if (response_length > 0 ) {
|
||||
if (!resolve(packet, ipaddress)) {
|
||||
delete packet;
|
||||
return NS_ERROR_DNS_FAILURE;
|
||||
return NSAPI_ERROR_DNS_FAILURE;
|
||||
}
|
||||
|
||||
// cleanup and return
|
||||
|
@ -208,7 +182,35 @@ int32_t dnsQuery(UDPSocket *socket, const char *hostname, char *ipaddress)
|
|||
}
|
||||
|
||||
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
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -26,14 +26,14 @@ class EthernetInterface : public NetworkInterface
|
|||
{
|
||||
public:
|
||||
/** 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
|
||||
* @return 0 on success
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
virtual int32_t disconnect() = 0;
|
||||
virtual int disconnect() = 0;
|
||||
};
|
||||
|
||||
#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
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -14,16 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "NetworkInterface.h"
|
||||
#include "DnsQuery.h"
|
||||
#include "mbed.h"
|
||||
|
||||
|
||||
bool NetworkInterface::isConnected()
|
||||
int NetworkInterface::gethostbyname(const char *name, char *dest)
|
||||
{
|
||||
return getIPAddress() != 0;
|
||||
}
|
||||
|
||||
int32_t NetworkInterface::getHostByName(const char *name, char *ip)
|
||||
{
|
||||
return dnsQuery(this, name, ip);
|
||||
return dnsQuery(this, name, dest);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* NetworkInterface Base Class
|
||||
/* Socket
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -17,29 +17,37 @@
|
|||
#ifndef NETWORK_INTERFACE_H
|
||||
#define NETWORK_INTERFACE_H
|
||||
|
||||
#include "SocketInterface.h"
|
||||
#include "stdint.h"
|
||||
#include "mbed.h"
|
||||
#include "SocketAddress.h"
|
||||
|
||||
/** Maximum storage needed for IP address and MAC addresses
|
||||
*/
|
||||
#define NS_IP_SIZE 16
|
||||
#define NS_MAC_SIZE 18
|
||||
|
||||
/**
|
||||
/** Enum of standardized error codes
|
||||
* @enum ns_error_t
|
||||
* @brief enum of standardized error codes
|
||||
*/
|
||||
enum ns_error_t {
|
||||
NS_ERROR_WOULD_BLOCK = -3000, /*!< no data is not available but call is non-blocking */
|
||||
NS_ERROR_TIMEOUT = -3001, /*!< operation took longer than allowed */
|
||||
NS_ERROR_NO_CONNECTION = -3002, /*!< not connected to a network */
|
||||
NS_ERROR_NO_SOCKET = -3003, /*!< socket not available for use */
|
||||
NS_ERROR_NO_ADDRESS = -3004, /*!< IP address is not known */
|
||||
NS_ERROR_NO_MEMORY = -3005, /*!< memory resource not available */
|
||||
NS_ERROR_DNS_FAILURE = -3006, /*!< DNS failed to complete successfully */
|
||||
NS_ERROR_DHCP_FAILURE = -3007, /*!< DHCP failed to complete successfully */
|
||||
NS_ERROR_AUTH_FAILURE = -3008, /*!< connection to access point faield */
|
||||
NS_ERROR_DEVICE_ERROR = -3009 /*!< failure interfacing with the network procesor */
|
||||
enum nsapi_error_t {
|
||||
NSAPI_ERROR_WOULD_BLOCK = -3001, /*!< no data is not available but call is non-blocking */
|
||||
NSAPI_ERROR_UNSUPPORTED = -3002, /*!< unsupported configuration */
|
||||
NSAPI_ERROR_NO_CONNECTION = -3003, /*!< not connected to a network */
|
||||
NSAPI_ERROR_NO_SOCKET = -3004, /*!< socket not available for use */
|
||||
NSAPI_ERROR_NO_ADDRESS = -3005, /*!< IP address is not known */
|
||||
NSAPI_ERROR_NO_MEMORY = -3006, /*!< memory resource not available */
|
||||
NSAPI_ERROR_DNS_FAILURE = -3007, /*!< DNS failed to complete successfully */
|
||||
NSAPI_ERROR_DHCP_FAILURE = -3008, /*!< DHCP failed to complete successfully */
|
||||
NSAPI_ERROR_AUTH_FAILURE = -3009, /*!< connection to access point faield */
|
||||
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
|
||||
|
@ -51,42 +59,175 @@ class NetworkInterface
|
|||
public:
|
||||
virtual ~NetworkInterface() {};
|
||||
|
||||
/** Get the IP address
|
||||
* @return IP address of the interface or 0 if not yet connected
|
||||
/** Get the internally stored IP address
|
||||
* @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
|
||||
* @return String MAC address of the interface
|
||||
/** Get the internally stored MAC address
|
||||
* @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
|
||||
* @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
|
||||
* @param name URL of host
|
||||
* @param ip Buffer to hold IP address, must be at least SOCK_IP_SIZE
|
||||
* @return 0 on success
|
||||
* @param name Hostname to lookup
|
||||
* @param dest Destination for IP address, must have space for SocketAddress::IP_SIZE
|
||||
* @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:
|
||||
friend class Socket;
|
||||
friend class UDPSocket;
|
||||
friend class TCPSocket;
|
||||
friend class TCPServer;
|
||||
|
||||
/** Internally create a socket
|
||||
* @param proto The type of socket to open, NS_TCP or NS_UDP
|
||||
* @return The allocated socket
|
||||
/** Create a socket
|
||||
* @param proto The type of socket to open, TCP or UDP
|
||||
* @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
|
||||
* @param socket An allocated SocketInterface
|
||||
* @returns 0 on success
|
||||
/** Destroy a socket
|
||||
* @param socket Previously allocated socket
|
||||
*/
|
||||
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
|
||||
|
|
124
Socket.cpp
124
Socket.cpp
|
@ -15,116 +15,68 @@
|
|||
*/
|
||||
|
||||
#include "Socket.h"
|
||||
#include <string.h>
|
||||
|
||||
Socket::Socket(NetworkInterface *iface, ns_protocol_t proto)
|
||||
Socket::Socket(NetworkInterface *iface, nsapi_protocol_t proto)
|
||||
: _iface(iface)
|
||||
, _proto(proto)
|
||||
, _socket(0)
|
||||
, _blocking(true)
|
||||
, _timeout(0)
|
||||
{
|
||||
memset(_ip_address, 0, NS_IP_SIZE);
|
||||
_port = 0;
|
||||
_socket = _iface->socket_create(proto);
|
||||
}
|
||||
|
||||
Socket::~Socket()
|
||||
{
|
||||
if (_socket) {
|
||||
close();
|
||||
close(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32_t Socket::open(const char *address, uint16_t port)
|
||||
void Socket::set_blocking(bool blocking)
|
||||
{
|
||||
int32_t err;
|
||||
|
||||
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;
|
||||
_blocking = blocking;
|
||||
}
|
||||
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SocketInterface *socket = _socket;
|
||||
_socket = 0;
|
||||
|
||||
int32_t err = socket->close();
|
||||
int err = _iface->socket_close(_socket, shutdown);
|
||||
if (!err) {
|
||||
_iface->destroySocket(socket);
|
||||
void *socket = _socket;
|
||||
_socket = 0;
|
||||
_iface->socket_destroy(socket);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t Socket::send(const void *data, uint32_t size)
|
||||
void Socket::thunk(void *p)
|
||||
{
|
||||
if (!_socket) {
|
||||
return NS_ERROR_NO_CONNECTION;
|
||||
}
|
||||
return _socket->send(data, size);
|
||||
FunctionPointer *fptr = (FunctionPointer *)p;
|
||||
(*fptr)();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
74
Socket.h
74
Socket.h
|
@ -17,69 +17,57 @@
|
|||
#ifndef SOCKET_H
|
||||
#define SOCKET_H
|
||||
|
||||
#include "SocketAddress.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
/** Abstract socket class
|
||||
* API for handling general sockets. Supports IP address operations
|
||||
* and sending/recieving data.
|
||||
*/
|
||||
class Socket
|
||||
{
|
||||
class Socket {
|
||||
public:
|
||||
~Socket();
|
||||
|
||||
/** 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
|
||||
/** Socket lifetime
|
||||
*/
|
||||
int32_t open(const char *address, uint16_t port);
|
||||
virtual ~Socket();
|
||||
|
||||
/** Close an open connection
|
||||
* @return 0 on success
|
||||
/** Set blocking or non-blocking mode of the socket
|
||||
* @param blocking true for blocking mode, false for non-blocking mode.
|
||||
*/
|
||||
int32_t close();
|
||||
void set_blocking(bool blocking);
|
||||
|
||||
/** Send data over the socket
|
||||
* @param data Buffer of data to send
|
||||
* @param size Size of data to send
|
||||
* @return Number of bytes sent or a negative value on failure
|
||||
/** Set timeout on a socket operation if blocking behaviour is enabled
|
||||
* @param timeout timeout in ms
|
||||
*/
|
||||
int32_t send(const void *data, uint32_t size);
|
||||
void set_timeout(unsigned int timeout);
|
||||
|
||||
/** Recieve data over the socket
|
||||
* @param data Buffer to store recieved data
|
||||
* @param size Size of provided buffer
|
||||
* @param blocking If true wait for data, otherwise return NS_ERROR_WOULD_BLOCK
|
||||
* @return Number of bytes recieved or a negative value on failure
|
||||
/* Set socket options
|
||||
* @param optname Option ID
|
||||
* @param optval Option value
|
||||
* @param optlen Length of the option value
|
||||
* @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
|
||||
* @return IP address to connect to
|
||||
/* Get socket options
|
||||
* @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
|
||||
* @return Port to connect to
|
||||
/** Close the socket
|
||||
* @param shutdown free the left-over data in message queues
|
||||
*/
|
||||
uint16_t getPort() const;
|
||||
|
||||
/** Returns status of socket
|
||||
* @return true if connected
|
||||
*/
|
||||
bool isConnected();
|
||||
int close(bool shutdown=true);
|
||||
|
||||
protected:
|
||||
Socket(NetworkInterface *iface, ns_protocol_t proto);
|
||||
Socket(NetworkInterface *iface, nsapi_protocol_t proto);
|
||||
|
||||
static void thunk(void *);
|
||||
|
||||
private:
|
||||
NetworkInterface *_iface;
|
||||
ns_protocol_t _proto;
|
||||
SocketInterface *_socket;
|
||||
|
||||
char _ip_address[NS_IP_SIZE];
|
||||
uint16_t _port;
|
||||
void *_socket;
|
||||
bool _blocking;
|
||||
unsigned _timeout;
|
||||
};
|
||||
|
||||
#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
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -14,26 +14,81 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TCP_SOCKET_H
|
||||
#define TCP_SOCKET_H
|
||||
#ifndef TCPSOCKET_H
|
||||
#define TCPSOCKET_H
|
||||
|
||||
#include "Socket.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
/** TCPSocket class
|
||||
* API for handling TCP sockets. The implementation is determined
|
||||
* by the interface passed during construction.
|
||||
/** TCP socket connection
|
||||
*/
|
||||
class TCPSocket : public Socket
|
||||
{
|
||||
class TCPSocket : public Socket {
|
||||
public:
|
||||
/** Create a socket using the specified network interface
|
||||
* 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
|
||||
/** TCP socket lifetime
|
||||
*/
|
||||
TCPSocket(NetworkInterface *iface)
|
||||
: Socket(iface, NS_TCP) {}
|
||||
TCPSocket(NetworkInterface *iface);
|
||||
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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -14,26 +14,70 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UDP_SOCKET_H
|
||||
#define UDP_SOCKET_H
|
||||
#ifndef UDPSOCKET_H
|
||||
#define UDPSOCKET_H
|
||||
|
||||
#include "Socket.h"
|
||||
#include "NetworkInterface.h"
|
||||
|
||||
/** UDPSocket class
|
||||
* API for handling UDP sockets. The implementation is determined
|
||||
* by the interface passed during construction.
|
||||
/** UDP Socket
|
||||
*/
|
||||
class UDPSocket : public Socket
|
||||
{
|
||||
class UDPSocket : public Socket {
|
||||
public:
|
||||
/** Create a socket using the specified network interface
|
||||
* 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 lifetime
|
||||
*/
|
||||
UDPSocket(NetworkInterface *iface)
|
||||
: Socket(iface, NS_UDP) {}
|
||||
UDPSocket(NetworkInterface *iface);
|
||||
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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* WiFiInterface Base Class
|
||||
/* Socket
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -21,14 +21,13 @@
|
|||
|
||||
/** Enum for WiFi encryption types
|
||||
*/
|
||||
enum ns_security_t {
|
||||
NS_SECURITY_NONE = 0, /*!< open access point */
|
||||
NS_SECURITY_WEP, /*!< phrase conforms to WEP */
|
||||
NS_SECURITY_WPA, /*!< phrase conforms to WPA */
|
||||
NS_SECURITY_WPA2, /*!< phrase conforms to WPA2 */
|
||||
enum nsapi_security_t {
|
||||
NSAPI_SECURITY_NONE = 0, /*!< open access point */
|
||||
NSAPI_SECURITY_WEP, /*!< phrase conforms to WEP */
|
||||
NSAPI_SECURITY_WPA, /*!< phrase conforms to WPA */
|
||||
NSAPI_SECURITY_WPA2, /*!< phrase conforms to WPA2 */
|
||||
};
|
||||
|
||||
|
||||
/** WiFiInterface class
|
||||
* Common interface that is shared between WiFi devices
|
||||
*/
|
||||
|
@ -36,17 +35,17 @@ class WiFiInterface : public NetworkInterface
|
|||
{
|
||||
public:
|
||||
/** Start the interface
|
||||
* @param ssid Name of the network to connect to
|
||||
* @param pass Security passphrase to connect to the network
|
||||
* @param security Type of encryption to connect with
|
||||
* @return 0 on success
|
||||
* @param ssid Name of the network to connect to
|
||||
* @param pass Security passphrase to connect to the network
|
||||
* @param security Type of encryption for connection
|
||||
* @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
|
||||
* @return 0 on success
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
virtual int32_t disconnect() = 0;
|
||||
virtual int disconnect() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue