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/2231/head
parent
b032d1886f
commit
697ac558be
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
174
LWIPInterface.h
174
LWIPInterface.h
|
@ -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
|
||||
|
|
33
lwip/COPYING
33
lwip/COPYING
|
@ -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>
|
||||
*
|
||||
*/
|
||||
|
||||
|
Loading…
Reference in New Issue