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.
parent
f396e3165f
commit
03475f35bb
|
@ -14,9 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "mbed.h"
|
||||
#include "LWIPInterface.h"
|
||||
|
||||
#include "mbed.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/dhcp.h"
|
||||
|
@ -26,15 +26,11 @@
|
|||
#include "netif/etharp.h"
|
||||
#include "eth_arch.h"
|
||||
|
||||
|
||||
#define LWIP_TIMEOUT 15000
|
||||
|
||||
|
||||
/* TCP/IP and Network Interface Initialisation */
|
||||
static struct netif netif;
|
||||
|
||||
static char ip_addr[NS_IP_SIZE] = "\0";
|
||||
static char mac_addr[NS_MAC_SIZE] = "\0";
|
||||
static char ip_addr[NSAPI_IP_SIZE] = "\0";
|
||||
static char mac_addr[NSAPI_MAC_SIZE] = "\0";
|
||||
|
||||
static Semaphore tcpip_inited(0);
|
||||
static Semaphore netif_linked(0);
|
||||
|
@ -86,8 +82,7 @@ static void set_mac_address(void)
|
|||
}
|
||||
|
||||
|
||||
// LWIPInterface implementation
|
||||
int32_t LWIPInterface::connect()
|
||||
int LWIPInterface::connect()
|
||||
{
|
||||
// Set up network
|
||||
set_mac_address();
|
||||
|
@ -100,14 +95,14 @@ int32_t LWIPInterface::connect()
|
|||
|
||||
// Wait for an IP Address
|
||||
// -1: error, 0: timeout
|
||||
if (netif_up.wait(LWIP_TIMEOUT) < 0) {
|
||||
return NS_ERROR_TIMEOUT;
|
||||
if (netif_up.wait(1500) < 0) {
|
||||
return NSAPI_ERROR_DHCP_FAILURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t LWIPInterface::disconnect()
|
||||
int LWIPInterface::disconnect()
|
||||
{
|
||||
dhcp_release(&netif);
|
||||
dhcp_stop(&netif);
|
||||
|
@ -117,90 +112,204 @@ int32_t LWIPInterface::disconnect()
|
|||
return 0;
|
||||
}
|
||||
|
||||
const char *LWIPInterface::getIPAddress()
|
||||
const char *LWIPInterface::get_ip_address()
|
||||
{
|
||||
return ip_addr;
|
||||
}
|
||||
|
||||
const char *LWIPInterface::getMACAddress()
|
||||
const char *LWIPInterface::get_mac_address()
|
||||
{
|
||||
return mac_addr;
|
||||
}
|
||||
|
||||
SocketInterface *LWIPInterface::createSocket(ns_protocol_t proto)
|
||||
void *LWIPInterface::socket_create(nsapi_protocol_t proto)
|
||||
{
|
||||
int type = (proto == NS_UDP) ? SOCK_DGRAM : SOCK_STREAM;
|
||||
int type = (proto == NSAPI_UDP) ? SOCK_DGRAM : SOCK_STREAM;
|
||||
int fd = lwip_socket(AF_INET, type, 0);
|
||||
if (fd < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new LWIPSocket(fd);
|
||||
return (void *)(fd+1);
|
||||
}
|
||||
|
||||
void LWIPInterface::destroySocket(SocketInterface *siface)
|
||||
void LWIPInterface::socket_destroy(void *handle)
|
||||
{
|
||||
LWIPSocket *socket = (LWIPSocket *)siface;
|
||||
lwip_close(socket->fd);
|
||||
|
||||
delete socket;
|
||||
int fd = (int)handle-1;
|
||||
lwip_close(fd);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TCP SocketInterface implementation
|
||||
int32_t LWIPInterface::LWIPSocket::open(const char *ip, uint16_t port)
|
||||
int LWIPInterface::socket_set_option(void *handle, int optname, const void *optval, unsigned optlen)
|
||||
{
|
||||
struct sockaddr_in host;
|
||||
memset(&host, 0, sizeof host);
|
||||
inet_aton(ip, &host.sin_addr);
|
||||
host.sin_family = AF_INET;
|
||||
host.sin_port = htons(port);
|
||||
int fd = (int)handle-1;
|
||||
return lwip_setsockopt(fd, SOL_SOCKET, optname, optval, (socklen_t)optlen);
|
||||
}
|
||||
|
||||
if (lwip_connect(fd, (const struct sockaddr *)&host, sizeof host) < 0) {
|
||||
return NS_ERROR_NO_CONNECTION;
|
||||
int LWIPInterface::socket_get_option(void *handle, int optname, void *optval, unsigned *optlen)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
return lwip_getsockopt(fd, SOL_SOCKET, optname, optval, (socklen_t*)optlen);
|
||||
}
|
||||
|
||||
int LWIPInterface::socket_bind(void *handle, int port)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
struct sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof sa);
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (lwip_bind(fd, (const struct sockaddr *)&sa, sizeof sa) < 0) {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LWIPInterface::socket_listen(void *handle, int backlog)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int LWIPInterface::socket_connect(void *handle, const SocketAddress &addr)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
struct sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof sa);
|
||||
inet_aton(addr.get_ip_address(), &sa.sin_addr);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(addr.get_port());
|
||||
|
||||
if (lwip_connect(fd, (const struct sockaddr *)&sa, sizeof sa) < 0) {
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t LWIPInterface::LWIPSocket::close()
|
||||
|
||||
bool LWIPInterface::socket_is_connected(void *handle)
|
||||
{
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t LWIPInterface::LWIPSocket::send(const void *voiddata, uint32_t size)
|
||||
int LWIPInterface::socket_accept(void *handle, void **connection)
|
||||
{
|
||||
uint8_t *data = (uint8_t *)voiddata;
|
||||
uint32_t writtenLen = 0;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
while (writtenLen < size) {
|
||||
int ret = lwip_send(fd, data + writtenLen, size - writtenLen, 0);
|
||||
int LWIPInterface::socket_send(void *handle, const void *p, unsigned size)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
uint8_t *data = (uint8_t *)p;
|
||||
unsigned written = 0;
|
||||
|
||||
while (written < size) {
|
||||
int ret = lwip_send(fd, data + written, size - written, 0);
|
||||
|
||||
if (ret > 0) {
|
||||
writtenLen += ret;
|
||||
written += ret;
|
||||
} else if (ret == 0) {
|
||||
return NS_ERROR_NO_CONNECTION;
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
} else {
|
||||
return NS_ERROR_DEVICE_ERROR;
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return writtenLen;
|
||||
return written;
|
||||
}
|
||||
|
||||
int32_t LWIPInterface::LWIPSocket::recv(void *data, uint32_t size)
|
||||
int LWIPInterface::socket_recv(void *handle, void *data, unsigned size)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
int ret = lwip_recv(fd, data, size, MSG_DONTWAIT);
|
||||
|
||||
if (ret > 0) {
|
||||
return ret;
|
||||
} else if (ret == 0) {
|
||||
return NS_ERROR_NO_CONNECTION;
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
} else if (ret == -1) {
|
||||
return NS_ERROR_WOULD_BLOCK;
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
} else {
|
||||
return NS_ERROR_DEVICE_ERROR;
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int LWIPInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *p, unsigned size)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
uint8_t *data = (uint8_t *)p;
|
||||
unsigned written = 0;
|
||||
|
||||
struct sockaddr_in sa;
|
||||
memset(&sa, 0, sizeof sa);
|
||||
inet_aton(addr.get_ip_address(), &sa.sin_addr);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(addr.get_port());
|
||||
|
||||
while (written < size) {
|
||||
int ret = lwip_sendto(fd, data + written, size - written, 0,
|
||||
(const struct sockaddr *)&sa, sizeof sa);
|
||||
|
||||
if (ret > 0) {
|
||||
written += ret;
|
||||
} else if (ret == 0) {
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
} else {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
int LWIPInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
struct sockaddr_in sa;
|
||||
socklen_t sa_len = sizeof sa;
|
||||
|
||||
int ret = lwip_recvfrom(fd, data, size, MSG_DONTWAIT,
|
||||
(struct sockaddr *)&sa, &sa_len);
|
||||
|
||||
if (ret > 0 && addr) {
|
||||
addr->set_ip_address(inet_ntoa(sa.sin_addr));
|
||||
addr->set_port(ntohs(sa.sin_port));
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
return ret;
|
||||
} else if (ret == 0) {
|
||||
return NSAPI_ERROR_NO_CONNECTION;
|
||||
} else if (ret == -1) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
} else {
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
int LWIPInterface::socket_close(void *handle, bool shutdown)
|
||||
{
|
||||
int fd = (int)handle-1;
|
||||
if (shutdown) {
|
||||
lwip_shutdown(fd, SHUT_RDWR);
|
||||
}
|
||||
|
||||
lwip_close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LWIPInterface::socket_attach_accept(void *handle, void (*callback)(void *), void *id)
|
||||
{
|
||||
}
|
||||
|
||||
void LWIPInterface::socket_attach_send(void *handle, void (*callback)(void *), void *id)
|
||||
{
|
||||
}
|
||||
|
||||
void LWIPInterface::socket_attach_recv(void *handle, void (*callback)(void *), void *id)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -28,36 +28,166 @@
|
|||
class LWIPInterface : public EthernetInterface
|
||||
{
|
||||
public:
|
||||
/** Start the interface
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
virtual int connect();
|
||||
|
||||
// Implementation of EthernetInterface
|
||||
virtual int32_t connect();
|
||||
virtual int32_t disconnect();
|
||||
/** Stop the interface
|
||||
* @return 0 on success, negative on failure
|
||||
*/
|
||||
virtual int disconnect();
|
||||
|
||||
// Implementation of NetworkInterface
|
||||
virtual const char *getIPAddress();
|
||||
virtual const char *getMACAddress();
|
||||
/** Get the internally stored IP address
|
||||
/return IP address of the interface or null if not yet connected
|
||||
*/
|
||||
virtual const char *get_ip_address();
|
||||
|
||||
virtual SocketInterface *createSocket(ns_protocol_t proto);
|
||||
virtual void destroySocket(SocketInterface *socket);
|
||||
/** Get the internally stored MAC address
|
||||
/return MAC address of the interface
|
||||
*/
|
||||
virtual const char *get_mac_address();
|
||||
|
||||
private:
|
||||
protected:
|
||||
/** Create a socket
|
||||
/param proto The type of socket to open, TCP or UDP
|
||||
/return The alocated socket or null on failure
|
||||
*/
|
||||
virtual void *socket_create(nsapi_protocol_t proto);
|
||||
|
||||
// Implementation of the TCP SocketInterface for LWIP
|
||||
class LWIPSocket : public SocketInterface
|
||||
{
|
||||
public:
|
||||
/** Destroy a socket
|
||||
/param socket Previously allocated socket
|
||||
*/
|
||||
virtual void socket_destroy(void *handle);
|
||||
|
||||
LWIPSocket(int fd) : fd(fd) {}
|
||||
int fd;
|
||||
/** 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);
|
||||
|
||||
// Implementation of SocketInterface
|
||||
virtual int32_t open(const char *ip, uint16_t port);
|
||||
virtual int32_t close();
|
||||
/** 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);
|
||||
|
||||
virtual int32_t send(const void *data, uint32_t size);
|
||||
virtual int32_t recv(void *data, uint32_t size);
|
||||
};
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** Check if the socket is connected
|
||||
\param handle Socket handle
|
||||
\return true if connected, false otherwise
|
||||
*/
|
||||
virtual bool socket_is_connected(void *handle);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
@ -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,21 +168,49 @@ 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
|
||||
delete packet;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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,42 @@
|
|||
#ifndef NETWORK_INTERFACE_H
|
||||
#define NETWORK_INTERFACE_H
|
||||
|
||||
#include "SocketInterface.h"
|
||||
#include "stdint.h"
|
||||
|
||||
/** Maximum storage needed for IP address and MAC addresses
|
||||
*/
|
||||
#define NS_IP_SIZE 16
|
||||
#define NS_MAC_SIZE 18
|
||||
#ifndef MBED_OPERATORS
|
||||
#define MBED_OPERATORS
|
||||
#endif
|
||||
#include "FunctionPointer.h"
|
||||
#include "SocketAddress.h"
|
||||
|
||||
/**
|
||||
* @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 ns_opt_t
|
||||
* @brief enum of available options
|
||||
*/
|
||||
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 +64,175 @@ class NetworkInterface
|
|||
public:
|
||||
virtual ~NetworkInterface() {};
|
||||
|
||||
/** Get the IP address
|
||||
* @return IP address of the interface or 0 if not yet connected
|
||||
*/
|
||||
virtual const char *getIPAddress() = 0;
|
||||
/** Get the internally stored IP address
|
||||
/return IP address of the interface or null if not yet connected
|
||||
*/
|
||||
virtual const char *get_ip_address() = 0;
|
||||
|
||||
/** Get the current MAC address
|
||||
* @return String MAC address of the interface
|
||||
*/
|
||||
virtual const char *getMACAddress() = 0;
|
||||
/** Get the internally stored MAC address
|
||||
/return MAC address of the interface
|
||||
*/
|
||||
virtual const char *get_mac_address() = 0;
|
||||
|
||||
/** Get the current status of the interface
|
||||
* @return true if connected
|
||||
*/
|
||||
virtual bool isConnected();
|
||||
/return true if connected
|
||||
*/
|
||||
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
|
||||
*/
|
||||
virtual int32_t getHostByName(const char *name, char *ip);
|
||||
/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 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
|
||||
*/
|
||||
virtual SocketInterface *createSocket(ns_protocol_t proto) = 0;
|
||||
/** Create a socket
|
||||
/param proto The type of socket to open, TCP or UDP
|
||||
/return The alocated socket or null on failure
|
||||
*/
|
||||
virtual void *socket_create(nsapi_protocol_t proto) = 0;
|
||||
|
||||
/** Internally destroy a socket
|
||||
* @param socket An allocated SocketInterface
|
||||
* @returns 0 on success
|
||||
*/
|
||||
virtual void destroySocket(SocketInterface *socket) = 0;
|
||||
/** Destroy a socket
|
||||
/param socket Previously allocated socket
|
||||
*/
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
mbed::FuncPtr<void()> *fptr = (mbed::FuncPtr<void()> *)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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
/** Set blocking or non-blocking mode of the socket
|
||||
\param blocking true for blocking mode, false for non-blocking mode.
|
||||
*/
|
||||
void set_blocking(bool blocking);
|
||||
|
||||
/** Set timeout on a socket operation if blocking behaviour is enabled
|
||||
\param timeout timeout in ms
|
||||
*/
|
||||
void set_timeout(unsigned int timeout);
|
||||
|
||||
/** Close an open connection
|
||||
* @return 0 on success
|
||||
*/
|
||||
int32_t close();
|
||||
|
||||
/** 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
|
||||
*/
|
||||
int32_t send(const void *data, uint32_t size);
|
||||
|
||||
/** 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
|
||||
*/
|
||||
int32_t recv(void *data, uint32_t size, bool blocking = true);
|
||||
|
||||
/** Gets the IP address
|
||||
* @return IP address to connect to
|
||||
*/
|
||||
const char *getIPAddress() const;
|
||||
|
||||
/** Gets the port
|
||||
* @return Port to connect to
|
||||
*/
|
||||
uint16_t getPort() const;
|
||||
|
||||
/** Returns status of socket
|
||||
* @return true if connected
|
||||
*/
|
||||
bool isConnected();
|
||||
/** 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
|
||||
*/
|
||||
int set_option(int optname, const void *optval, unsigned optlen);
|
||||
|
||||
/** 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
|
||||
*/
|
||||
int get_option(int optname, void *optval, unsigned *optlen);
|
||||
|
||||
/** Close the socket
|
||||
\param shutdown free the left-over data in message queues
|
||||
*/
|
||||
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(mbed::FuncPtr<void()> 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(mbed::FuncPtr<void()> callback);
|
||||
|
||||
template <typename T, typename M>
|
||||
void attach_accept(T *tptr, M mptr) {
|
||||
attach_accept(mbed::FuncPtr<void()>(tptr, mptr));
|
||||
}
|
||||
|
||||
private:
|
||||
mbed::FuncPtr<void()> _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(mbed::FuncPtr<void()> 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(mbed::FuncPtr<void()> 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);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* TCPSocket
|
||||
/* Socket
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -14,26 +14,82 @@
|
|||
* 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.
|
||||
*/
|
||||
class TCPSocket : public Socket
|
||||
{
|
||||
/**
|
||||
TCP socket connection
|
||||
*/
|
||||
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
|
||||
*/
|
||||
TCPSocket(NetworkInterface *iface)
|
||||
: Socket(iface, NS_TCP) {}
|
||||
/** TCP socket lifetime
|
||||
*/
|
||||
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(mbed::FuncPtr<void()> callback);
|
||||
|
||||
template <typename T, typename M>
|
||||
void attach_send(T *tptr, M mptr) {
|
||||
attach_send(mbed::FuncPtr<void()>(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(mbed::FuncPtr<void()> callback);
|
||||
|
||||
template <typename T, typename M>
|
||||
void attach_recv(T *tptr, M mptr) {
|
||||
attach_recv(mbed::FuncPtr<void()>(tptr, mptr));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class TCPServer;
|
||||
|
||||
mbed::FuncPtr<void()> _send_cb;
|
||||
mbed::FuncPtr<void()> _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(mbed::FuncPtr<void()> 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(mbed::FuncPtr<void()> 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);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* UDPSocket
|
||||
/* Socket
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -14,26 +14,71 @@
|
|||
* 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.
|
||||
*/
|
||||
class UDPSocket : public Socket
|
||||
{
|
||||
/**
|
||||
UDP 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(NetworkInterface *iface)
|
||||
: Socket(iface, NS_UDP) {}
|
||||
/** UDPSocket lifetime
|
||||
*/
|
||||
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(mbed::FuncPtr<void()> callback);
|
||||
|
||||
template <typename T, typename M>
|
||||
void attach_send(T *tptr, M mptr) {
|
||||
attach_send(mbed::FuncPtr<void()>(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(mbed::FuncPtr<void()> callback);
|
||||
|
||||
template <typename T, typename M>
|
||||
void attach_recv(T *tptr, M mptr) {
|
||||
attach_recv(mbed::FuncPtr<void()>(tptr, mptr));
|
||||
}
|
||||
|
||||
private:
|
||||
mbed::FuncPtr<void()> _send_cb;
|
||||
mbed::FuncPtr<void()> _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");
|
||||
|
@ -20,15 +20,14 @@
|
|||
#include "NetworkInterface.h"
|
||||
|
||||
/** 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
|
||||
*/
|
||||
virtual int32_t connect(const char *ssid, const char *pass, ns_security_t security = NS_SECURITY_NONE) = 0;
|
||||
/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 int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE) = 0;
|
||||
|
||||
/** Stop the interface
|
||||
* @return 0 on success
|
||||
*/
|
||||
virtual int32_t disconnect() = 0;
|
||||
/return 0 on success, negative on failure
|
||||
*/
|
||||
virtual int disconnect() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue