Base class for IP Based Networking Libraries

Dependencies:   DnsQuery

Dependents:   TempTower BSDInterfaceTests HelloBSDInterface ESP8266InterfaceTests ... more

For a complete getting started guide see the wiki...

Network Socket API

The Network Socket API provides a common interface for using sockets on network devices. The API provides a simple class-based interface that should be familiar to users experienced with other socket APIs. Additionally, the API provides a simple interface for implementing network devices, making it easy to connect hardware agnostic programs to new devices.

Network Interfaces

The NetworkInterface provides an abstract class for network devices that support sockets. Devices should provide a DeviceInterface class that inherits this interface and adds implementation specific methods for using the device. A NetworkInterface must be provided to a Socket constructor to open a socket on the interface. Currently two subclasses are defined for common devices, EthernetInterface and WiFiInterface.

Sockets

The Socket class is used for managing network sockets. Once opened, the socket provides a pipe through which data can sent and recieved to a specific endpoint. The socket class can be instantiated as either a TCPSocket or a UDPSocket which defines the protocol used for the connection.

Files at this revision

API Documentation at this revision

Comitter:
Christopher Haster
Date:
Tue Apr 05 12:52:07 2016 -0500
Parent:
80:9c6673c93082
Child:
82:97d166c4a193
Commit message:
Added proper forwarding for interrupt driven callbacks

Changed in this revision

NetworkInterface.h Show annotated file Show diff for this revision Revisions of this file
Socket.h Show annotated file Show diff for this revision Revisions of this file
TCPServer.cpp Show annotated file Show diff for this revision Revisions of this file
TCPServer.h Show annotated file Show diff for this revision Revisions of this file
TCPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
TCPSocket.h Show annotated file Show diff for this revision Revisions of this file
UDPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
UDPSocket.h Show annotated file Show diff for this revision Revisions of this file
--- a/NetworkInterface.h	Tue Apr 05 12:02:56 2016 -0500
+++ b/NetworkInterface.h	Tue Apr 05 12:52:07 2016 -0500
@@ -17,6 +17,9 @@
 #ifndef NETWORK_INTERFACE_H
 #define NETWORK_INTERFACE_H
 
+#ifndef MBED_OPERATORS
+#define MBED_OPERATORS
+#endif
 #include "FunctionPointer.h"
 #include "SocketAddress.h"
 
@@ -135,31 +138,35 @@
     */
     virtual int socket_listen(void *handle, int backlog) = 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.
-    */
-    virtual int socket_accept(void *handle, void **connection) = 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;
 
@@ -168,6 +175,8 @@
     \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;
 
@@ -177,6 +186,8 @@
     \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;
 
@@ -188,6 +199,8 @@
                     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;
 
@@ -201,22 +214,25 @@
     \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, mbed::FuncPtr<void()> callback) = 0;
+    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 send will succeed, may be called in
+    \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, mbed::FuncPtr<void()> callback) = 0;
+    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 recv will succeed, may be called in
+    \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, mbed::FuncPtr<void()> callback) = 0;
+    virtual void socket_attach_recv(void *handle, void (*callback)(void *), void *id) = 0;
 };
 
 #endif
--- a/Socket.h	Tue Apr 05 12:02:56 2016 -0500
+++ b/Socket.h	Tue Apr 05 12:52:07 2016 -0500
@@ -26,7 +26,7 @@
 public:
     /** Socket lifetime
      */
-    ~Socket();
+    virtual ~Socket();
     
     /** Set blocking or non-blocking mode of the socket
     \param blocking  true for blocking mode, false for non-blocking mode.
@@ -62,6 +62,8 @@
 protected:
     Socket(NetworkInterface *iface, NetworkInterface::protocol_t proto);
 
+    static void thunk(void *);
+
     NetworkInterface *_iface;
     void *_socket;
     bool _blocking;
--- a/TCPServer.cpp	Tue Apr 05 12:02:56 2016 -0500
+++ b/TCPServer.cpp	Tue Apr 05 12:52:07 2016 -0500
@@ -56,3 +56,22 @@
 
     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);
+    }
+}
--- a/TCPServer.h	Tue Apr 05 12:02:56 2016 -0500
+++ b/TCPServer.h	Tue Apr 05 12:52:07 2016 -0500
@@ -28,6 +28,7 @@
     /** 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
@@ -53,6 +54,14 @@
                     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
--- a/TCPSocket.cpp	Tue Apr 05 12:02:56 2016 -0500
+++ b/TCPSocket.cpp	Tue Apr 05 12:52:07 2016 -0500
@@ -62,3 +62,37 @@
 
     return _iface->socket_recv(_socket, data, size);
 }
+
+
+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);
+    }
+}
--- a/TCPSocket.h	Tue Apr 05 12:02:56 2016 -0500
+++ b/TCPSocket.h	Tue Apr 05 12:52:07 2016 -0500
@@ -28,6 +28,7 @@
     /** 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
@@ -68,14 +69,27 @@
     */
     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
--- a/UDPSocket.cpp	Tue Apr 05 12:02:56 2016 -0500
+++ b/UDPSocket.cpp	Tue Apr 05 12:52:07 2016 -0500
@@ -47,3 +47,35 @@
 
     return _iface->socket_recvfrom(_socket, address, buffer, size);
 }
+
+
+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);
+    }
+}
--- a/UDPSocket.h	Tue Apr 05 12:02:56 2016 -0500
+++ b/UDPSocket.h	Tue Apr 05 12:52:07 2016 -0500
@@ -28,6 +28,7 @@
     /** 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
@@ -59,11 +60,25 @@
     */
     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