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.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "mbed.h"
|
||||||
#include "LWIPInterface.h"
|
#include "LWIPInterface.h"
|
||||||
|
|
||||||
#include "mbed.h"
|
|
||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
#include "lwip/dhcp.h"
|
#include "lwip/dhcp.h"
|
||||||
|
@ -26,15 +26,11 @@
|
||||||
#include "netif/etharp.h"
|
#include "netif/etharp.h"
|
||||||
#include "eth_arch.h"
|
#include "eth_arch.h"
|
||||||
|
|
||||||
|
|
||||||
#define LWIP_TIMEOUT 15000
|
|
||||||
|
|
||||||
|
|
||||||
/* TCP/IP and Network Interface Initialisation */
|
/* TCP/IP and Network Interface Initialisation */
|
||||||
static struct netif netif;
|
static struct netif netif;
|
||||||
|
|
||||||
static char ip_addr[NS_IP_SIZE] = "\0";
|
static char ip_addr[NSAPI_IP_SIZE] = "\0";
|
||||||
static char mac_addr[NS_MAC_SIZE] = "\0";
|
static char mac_addr[NSAPI_MAC_SIZE] = "\0";
|
||||||
|
|
||||||
static Semaphore tcpip_inited(0);
|
static Semaphore tcpip_inited(0);
|
||||||
static Semaphore netif_linked(0);
|
static Semaphore netif_linked(0);
|
||||||
|
@ -86,8 +82,7 @@ static void set_mac_address(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// LWIPInterface implementation
|
int LWIPInterface::connect()
|
||||||
int32_t LWIPInterface::connect()
|
|
||||||
{
|
{
|
||||||
// Set up network
|
// Set up network
|
||||||
set_mac_address();
|
set_mac_address();
|
||||||
|
@ -100,14 +95,14 @@ int32_t LWIPInterface::connect()
|
||||||
|
|
||||||
// Wait for an IP Address
|
// Wait for an IP Address
|
||||||
// -1: error, 0: timeout
|
// -1: error, 0: timeout
|
||||||
if (netif_up.wait(LWIP_TIMEOUT) < 0) {
|
if (netif_up.wait(1500) < 0) {
|
||||||
return NS_ERROR_TIMEOUT;
|
return NSAPI_ERROR_DHCP_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t LWIPInterface::disconnect()
|
int LWIPInterface::disconnect()
|
||||||
{
|
{
|
||||||
dhcp_release(&netif);
|
dhcp_release(&netif);
|
||||||
dhcp_stop(&netif);
|
dhcp_stop(&netif);
|
||||||
|
@ -117,90 +112,204 @@ int32_t LWIPInterface::disconnect()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *LWIPInterface::getIPAddress()
|
const char *LWIPInterface::get_ip_address()
|
||||||
{
|
{
|
||||||
return ip_addr;
|
return ip_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *LWIPInterface::getMACAddress()
|
const char *LWIPInterface::get_mac_address()
|
||||||
{
|
{
|
||||||
return mac_addr;
|
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);
|
int fd = lwip_socket(AF_INET, type, 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
return 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;
|
int fd = (int)handle-1;
|
||||||
lwip_close(socket->fd);
|
lwip_close(fd);
|
||||||
|
|
||||||
delete socket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LWIPInterface::socket_set_option(void *handle, int optname, const void *optval, unsigned optlen)
|
||||||
// TCP SocketInterface implementation
|
|
||||||
int32_t LWIPInterface::LWIPSocket::open(const char *ip, uint16_t port)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_in host;
|
int fd = (int)handle-1;
|
||||||
memset(&host, 0, sizeof host);
|
return lwip_setsockopt(fd, SOL_SOCKET, optname, optval, (socklen_t)optlen);
|
||||||
inet_aton(ip, &host.sin_addr);
|
}
|
||||||
host.sin_family = AF_INET;
|
|
||||||
host.sin_port = htons(port);
|
|
||||||
|
|
||||||
if (lwip_connect(fd, (const struct sockaddr *)&host, sizeof host) < 0) {
|
int LWIPInterface::socket_get_option(void *handle, int optname, void *optval, unsigned *optlen)
|
||||||
return NS_ERROR_NO_CONNECTION;
|
{
|
||||||
|
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;
|
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;
|
return NSAPI_ERROR_UNSUPPORTED;
|
||||||
uint32_t writtenLen = 0;
|
}
|
||||||
|
|
||||||
while (writtenLen < size) {
|
int LWIPInterface::socket_send(void *handle, const void *p, unsigned size)
|
||||||
int ret = lwip_send(fd, data + writtenLen, size - writtenLen, 0);
|
{
|
||||||
|
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) {
|
if (ret > 0) {
|
||||||
writtenLen += ret;
|
written += ret;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
return NS_ERROR_NO_CONNECTION;
|
return NSAPI_ERROR_NO_CONNECTION;
|
||||||
} else {
|
} 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);
|
int ret = lwip_recv(fd, data, size, MSG_DONTWAIT);
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
return ret;
|
return ret;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
return NS_ERROR_NO_CONNECTION;
|
return NSAPI_ERROR_NO_CONNECTION;
|
||||||
} else if (ret == -1) {
|
} else if (ret == -1) {
|
||||||
return NS_ERROR_WOULD_BLOCK;
|
return NSAPI_ERROR_WOULD_BLOCK;
|
||||||
} else {
|
} 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
|
class LWIPInterface : public EthernetInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/** Start the interface
|
||||||
|
* @return 0 on success, negative on failure
|
||||||
|
*/
|
||||||
|
virtual int connect();
|
||||||
|
|
||||||
// Implementation of EthernetInterface
|
/** Stop the interface
|
||||||
virtual int32_t connect();
|
* @return 0 on success, negative on failure
|
||||||
virtual int32_t disconnect();
|
*/
|
||||||
|
virtual int disconnect();
|
||||||
|
|
||||||
// Implementation of NetworkInterface
|
/** Get the internally stored IP address
|
||||||
virtual const char *getIPAddress();
|
/return IP address of the interface or null if not yet connected
|
||||||
virtual const char *getMACAddress();
|
*/
|
||||||
|
virtual const char *get_ip_address();
|
||||||
|
|
||||||
virtual SocketInterface *createSocket(ns_protocol_t proto);
|
/** Get the internally stored MAC address
|
||||||
virtual void destroySocket(SocketInterface *socket);
|
/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
|
/** Destroy a socket
|
||||||
class LWIPSocket : public SocketInterface
|
/param socket Previously allocated socket
|
||||||
{
|
*/
|
||||||
public:
|
virtual void socket_destroy(void *handle);
|
||||||
|
|
||||||
LWIPSocket(int fd) : fd(fd) {}
|
/** Set socket options
|
||||||
int fd;
|
\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
|
/** Get socket options
|
||||||
virtual int32_t open(const char *ip, uint16_t port);
|
\param handle Socket handle
|
||||||
virtual int32_t close();
|
\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);
|
/** Bind a server socket to a specific port
|
||||||
virtual int32_t recv(void *data, uint32_t size);
|
\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
|
#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