Implementation of the NetworkSocketAPI for LWIP

Dependencies:   lwip-eth lwip-sys lwip

Dependents:   HelloLWIPInterface HelloLWIPInterfaceNonBlocking LWIPInterfaceTests SimpleHTTPExample ... more

Revision:
13:57d9e1721826
Parent:
12:899403b675fe
Child:
14:67b325c56cde
--- a/LWIPInterface.cpp	Tue Apr 05 19:20:42 2016 +0000
+++ b/LWIPInterface.cpp	Tue Apr 05 15:29:20 2016 -0500
@@ -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,12 +26,11 @@
 #include "netif/etharp.h"
 #include "eth_arch.h"
 
-#if 0
 /* 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[SocketAddress::IP_SIZE] = "\0";
+static char mac_addr[200] = "\0";
 
 static Semaphore tcpip_inited(0);
 static Semaphore netif_linked(0);
@@ -82,9 +81,8 @@
 #endif
 }
 
-#if 0
-// LWIPInterface implementation
-int32_t LWIPInterface::connect()
+
+int LWIPInterface::connect()
 {
     // Set up network
     set_mac_address();
@@ -97,14 +95,14 @@
 
     // 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);
@@ -114,285 +112,190 @@
     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(protocol_t proto)
 {
-    int type = (proto == NS_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+    int type = (proto == NetworkInterface::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;
 }
 
-void LWIPInterface::destroySocket(SocketInterface *siface)
+void LWIPInterface::socket_destroy(void *handle)
 {
-    LWIPSocket *socket = (LWIPSocket *)siface;
-    lwip_close(socket->fd);
+    int fd = (int)handle;
+    lwip_close(fd);
+    
+}
 
-    delete socket;
+int LWIPInterface::socket_set_option(void *handle, int optname, const void *optval, unsigned optlen)
+{
+    return lwip_setsockopt((int)handle, SOL_SOCKET, optname, optval, (socklen_t)optlen);
+}
+
+int LWIPInterface::socket_get_option(void *handle, int optname, void *optval, unsigned *optlen)
+{
+    return lwip_getsockopt((int)handle, SOL_SOCKET, optname, optval, (socklen_t*)optlen);
 }
 
+int LWIPInterface::socket_bind(void *handle, int port)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
 
-// TCP SocketInterface implementation
-int32_t LWIPInterface::LWIPSocket::open(const char *ip, uint16_t port)
+int LWIPInterface::socket_listen(void *handle, int backlog)
 {
-    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);
+    return NSAPI_ERROR_UNSUPPORTED;
+}
 
-    if (lwip_connect(fd, (const struct sockaddr *)&host, sizeof host) < 0) {
-        return NS_ERROR_NO_CONNECTION;
+int LWIPInterface::socket_connect(void *handle, const SocketAddress &addr)
+{
+    int fd = (int)handle;
+    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;
 }
+    
+bool LWIPInterface::socket_is_connected(void *handle)
+{
+    return true;
+}
 
-int32_t LWIPInterface::LWIPSocket::close()
+int LWIPInterface::socket_accept(void *handle, void **connection)
 {
-    return 0;
+    return NSAPI_ERROR_UNSUPPORTED;
 }
 
-int32_t LWIPInterface::LWIPSocket::send(const void *voiddata, uint32_t size)
+int LWIPInterface::socket_send(void *handle, const void *p, unsigned size)
 {
-    uint8_t *data = (uint8_t *)voiddata;
-    uint32_t writtenLen = 0;
+    int fd = (int)handle;
+    uint8_t *data = (uint8_t *)p;
+    unsigned written = 0;
 
-    while (writtenLen < size) {
-        int ret = lwip_send(fd, data + writtenLen, size - writtenLen, 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;
     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;
     }
 }
-#endif
 
-    /** Start the interface
-     *  @return     0 on success, negative on failure
-     */
-    virtual int connect() = 0;
-
-    /** Stop the interface
-     *  @return     0 on success, negative on failure
-     */
-    virtual int disconnect() = 0;
-
-class NetworkInterface
+int LWIPInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *p, unsigned size)
 {
-public:
-    virtual ~NetworkInterface() {};
+    int fd = (int)handle;
+    uint8_t *data = (uint8_t *)p;
+    unsigned written = 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;
+    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());
 
-    /** Get the internally stored MAC address
-    /return     MAC address of the interface
-    */
-    virtual const char *get_mac_address() = 0;
+    while (written < size) {
+        int ret = lwip_sendto(fd, data + written, size - written, 0,
+            (const struct sockaddr *)&sa, sizeof sa);
 
-    /** Get the current status of the interface
-    /return     true if connected
-    */
-    virtual bool is_connected() {
-        return get_ip_address() != NULL;
+        if (ret > 0) {
+            written += ret;
+        } else if (ret == 0) {
+            return NSAPI_ERROR_NO_CONNECTION;
+        } else {
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
     }
 
-    /** Looks up the specified host's IP address
-    /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;
-
-    /** Enum of socket protocols
-    /enum protocol_t
-    */
-    enum protocol_t {
-        TCP, /*!< Socket is of TCP type */
-        UDP, /*!< Socket is of UDP type */
-    };
-
-    /** 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(protocol_t proto) = 0;
-
-    /** Destroy a socket
-    /param socket   Previously allocated socket
-    */
-    virtual void socket_destroy(void *handle) = 0;
+    return written;
+}
 
-    /** 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;
+int LWIPInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    int fd = (int)handle;
+    struct sockaddr_in sa;
+    socklen_t sa_len = sizeof sa;
 
-    /** 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;
+    int ret = lwip_recvfrom(fd, data, size, MSG_DONTWAIT, 
+        (struct sockaddr *)&sa, &sa_len);
 
-    /** 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;
+    if (ret > 0 && addr) {
+        addr->set_ip_address(inet_ntoa(sa.sin_addr));
+        addr->set_port(ntohs(sa.sin_port));
+    }
 
-    /** 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;
+    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;
+    }
+}
 
-    /** 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;
+int LWIPInterface::socket_close(void *handle, bool shutdown)
+{
+    int fd = (int)handle;
+    if (shutdown) {
+        lwip_shutdown(fd, SHUT_RDWR);
+    }
 
-    /** 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;
+    lwip_close(fd);
+    return 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;
+void LWIPInterface::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) = 0;
+void LWIPInterface::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) = 0;
-}; 
-#endif
+void LWIPInterface::socket_attach_recv(void *handle, void (*callback)(void *), void *id)
+{
+}