A new object oriented network api that can be used to replace the one provided by the EthernetInterface library.

Dependents:   NetRelais TCP_Client_Example TCP_Server_Example UDP_Server_Example ... more

Object oriented network interface for the mbed platform

Currently implemented:

  • Address
  • Endpoint
  • UDP Socket
  • TCP Socket
  • Databuffer
  • Select API

It depends on the EthernetInterface for the lwip network stack.

Please do not hesitate to contact me with any remarks, improvements or questions.

The API is also available for unix at GitHub: LibNosa

Examples

Files at this revision

API Documentation at this revision

Comitter:
NegativeBlack
Date:
Wed Jul 18 13:20:32 2012 +0000
Parent:
3:d30db8752485
Child:
5:4b6bc10437cb
Commit message:
Implemented buffer class, some scaffolding for a TCP server. And fixed some bugs in the TCP socket.

Changed in this revision

buffer.cpp Show annotated file Show diff for this revision Revisions of this file
buffer.hpp Show annotated file Show diff for this revision Revisions of this file
socket.hpp Show annotated file Show diff for this revision Revisions of this file
tcp/server.hpp Show annotated file Show diff for this revision Revisions of this file
tcp/socket.cpp Show annotated file Show diff for this revision Revisions of this file
tcp/socket.hpp Show annotated file Show diff for this revision Revisions of this file
--- a/buffer.cpp	Wed Jul 18 11:22:37 2012 +0000
+++ b/buffer.cpp	Wed Jul 18 13:20:32 2012 +0000
@@ -0,0 +1,160 @@
+/**
+ * Copyright (c) 2012, Roy van Dam <roy@vandam-innovations.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#include "buffer.hpp"
+using namespace network;
+
+Buffer::Buffer():
+    _memory(NULL), _size(0), _length(0)
+{}
+
+Buffer::Buffer(const size_t size):
+    _size(size), _length(0)
+{
+    this->_memory_allocate(size);
+}
+
+Buffer::Buffer(const Buffer &other):
+    _size(other._size), _length(other._length)
+{
+    if (this->_memory_allocate(other._size) != -1) {
+        std::memcpy(this->_memory, other._memory, other._size);
+    }
+}
+
+Buffer::~Buffer()
+{
+    this->_memory_free();
+}
+
+Buffer &
+Buffer::operator=(const Buffer &other)
+{
+    this->_memory_free();
+    if (this->_memory_allocate(other._size) < 0) {
+        return (*this);
+    }
+    
+    std::memcpy(this->_memory, other._memory, other._size);
+    this->_size = other._size;
+    this->_length = other._length;
+    
+    return (*this);
+}
+
+int
+Buffer::read(void *data, size_t max_length, size_t offset)
+{
+    if ((offset >= this->_size) || (this->_memory == NULL)) {
+        return 0;
+    }
+    
+    int bytes_to_copy = (max_length > this->_size - offset)
+        ? this->_size - offset
+        : max_length;
+    
+    std::memcpy(data, (unsigned char*)this->_memory + offset, bytes_to_copy);
+    return bytes_to_copy;
+}
+
+int
+Buffer::write(const void *data, size_t length, size_t offset)
+{
+    if ((offset >= this->_size) || (this->_memory == NULL)) {
+        return 0;
+    }
+    
+    int bytes_to_copy = (length > this->_size - offset)
+        ? this->_size - offset
+        : length;
+        
+    std::memcpy((unsigned char*)this->_memory + offset, data, bytes_to_copy);
+    this->_length += bytes_to_copy;
+    return bytes_to_copy;
+}
+
+void *
+Buffer::pointer(size_t offset)
+{
+    if (this->_memory == NULL) {
+        return NULL;
+    }
+
+    if (offset >= this->_size) {
+        return NULL;
+    }
+
+    return ((unsigned char*)this->_memory + offset);
+}
+
+void
+Buffer::setLength(size_t length)
+{
+    if (length > this->_size) {
+        this->_length = this->_size;
+    } else {
+        this->_length = length;
+    }
+}
+
+size_t
+Buffer::size()
+{
+    return this->_size;
+}
+
+size_t
+Buffer::length()
+{
+    return this->_length;
+}
+
+size_t
+Buffer::free()
+{
+    return this->_size - this->_length;
+}
+
+int
+Buffer::_memory_allocate(size_t size)
+{
+    this->_memory = std::calloc(size, sizeof(unsigned char));
+
+    if (this->_memory == NULL) {
+        this->_size = 0;
+        this->_length = 0;
+        return -1;
+    }
+    
+    return 0;
+}
+
+void
+Buffer::_memory_free()
+{
+    if (this->_memory != NULL) {
+        std::free(this->_memory);
+    }
+}
\ No newline at end of file
--- a/buffer.hpp	Wed Jul 18 11:22:37 2012 +0000
+++ b/buffer.hpp	Wed Jul 18 13:20:32 2012 +0000
@@ -26,31 +26,41 @@
 #ifndef _NETWORK_BUFFER_HPP_
 #define _NETWORK_BUFFER_HPP_
 
-#include "
+#include <stdlib.h>
+#include <cstring>
 
-namespace network {
-
+namespace network
+{
     class Buffer
     {
         protected:
-            unsigned char *_memory;
-            size_t _bytes_allocated;
-            size_t _bytes_used;
+            void *_memory;
+            size_t _size;
+            size_t _length;
             
         public:
             Buffer();
+            explicit Buffer(const Buffer &other);
             explicit Buffer(const size_t size);
         
             ~Buffer();
             
-            int read(void *data, size_t max_length);
-            int write(const void *data, size_t length);
+            int read(void *data, size_t max_length, size_t offset = 0);
+            int write(const void *data, size_t length, size_t offset = 0);
+            
+            void *pointer(size_t offset = 0);
+            void setLength(size_t length);
             
-            void *getPointer(bool offset = false);
+            size_t size();
+            size_t length();
+            size_t free();
             
-            size_t getUsed();
-            size_t getFree();
-            size_t getTotal();
+            Buffer &operator=(const Buffer &other);
+       
+       protected:
+            int _memory_allocate(size_t size);
+            void _memory_free();
+            
     };
 
 } // namespace network
--- a/socket.hpp	Wed Jul 18 11:22:37 2012 +0000
+++ b/socket.hpp	Wed Jul 18 13:20:32 2012 +0000
@@ -60,8 +60,8 @@
             virtual ~Socket();
             
             virtual int open();
-            virtual int close();
-            virtual int bind(int port);
+            int close();
+            int bind(int port);
             
             ip::Endpoint &getRemoteEndpoint();
             ip::Endpoint &getLocalEndpoint();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/server.hpp	Wed Jul 18 13:20:32 2012 +0000
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2012, Roy van Dam <roy@vandam-innovations.com>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+ */
+
+#ifndef _NETWORK_TCP_SERVER_HPP_
+#define _NETWORK_TCP_SERVER_HPP_
+
+#include <vector>
+
+#include "socket.hpp"
+
+namespace network {
+namespace tcp {
+
+    class Server
+    {
+        public:
+            enum Status {
+                Stopped = 0,
+                Running = 1,
+            };
+    
+        protected:
+            Status _status;
+        
+            Socket _socket;
+            std::vector<Socket *> _clients;
+        
+        public:
+            Server();
+            ~Server();
+            
+            int start(int port, int max_pending);
+            int stop();
+            
+            int run(int timeout = 0);
+            
+            // Todo: design callback interface
+    };
+
+} // namespace tcp
+} // namespace network
+
+#endif // _NETWORK_TCP_SERVER_HPP_
\ No newline at end of file
--- a/tcp/socket.cpp	Wed Jul 18 11:22:37 2012 +0000
+++ b/tcp/socket.cpp	Wed Jul 18 13:20:32 2012 +0000
@@ -37,7 +37,7 @@
     // Open socket
     this->_socket = ::socket(AF_INET, SOCK_STREAM, 0);
     if (this->_socket < 0) {
-        return -1;
+        return -2;
     }
     
     // Update status and return
@@ -46,7 +46,29 @@
 }
 
 int
-Socket::connect(ip::Address &address, int port)
+Socket::connect(const char *hostname, int port)
+{
+    ip::Address address;
+    if (address.fromHostname(hostname) < 0) {
+        return -1;
+    }
+    
+    return this->connect(address, port);
+}
+
+int
+Socket::connect(const std::string hostname, int port)
+{
+    ip::Address address;
+    if (address.fromHostname(hostname) < 0) {
+        return -1;
+    }
+    
+    return this->connect(address, port);
+}
+
+int
+Socket::connect(const ip::Address &address, int port)
 {
     ip::Endpoint endpoint(address, port);
     return this->connect(endpoint);
@@ -56,7 +78,7 @@
 Socket::connect(ip::Endpoint &endpoint)
 {
     // Check socket status
-    if ((this->_status != Socket::Open) ||
+    if ((this->_status != Socket::Open) &&
         (this->_status != Socket::Disconnected))
     {
         return -1;
@@ -72,7 +94,7 @@
     
     // Check result
     if (result < 0) {
-        return -1;
+        return -2;
     }
     
     // Update remote endpoint information.
@@ -94,7 +116,7 @@
     // Attempt to shutdown the connection.
     int result = ::shutdown(this->_socket, SHUT_RDWR);
     if (result < 0) {
-        return -1;
+        return -2;
     }
     
     // Update status and return
@@ -113,7 +135,7 @@
     // Put socket into listening mode.
     int result = ::listen(this->_socket, max_pending);
     if (result < 0) {
-        return -1;
+        return -2;
     }
     
     // Update status and return
@@ -131,7 +153,7 @@
     
     // Check client socket status
     if (client._status != Socket::Closed) {
-        return -1;
+        return -2;
     }
     
     // Create native endpoint
@@ -145,7 +167,7 @@
     
     // Did we succeed?
     if (socket < 0) {
-        return -1;
+        return -3;
     }
     
     // Check if we received the endpoint information correctly.
@@ -162,6 +184,12 @@
 }
 
 int
+Socket::write(Buffer &buffer)
+{
+    return this->write(buffer.pointer(), buffer.length());
+}
+
+int
 Socket::write(void *data, size_t size)
 {
     // Check data buffer and size
@@ -171,7 +199,7 @@
 
     // Check socket status
     if (this->_status != Socket::Connected) {
-        return -1;
+        return -2;
     }
     
     // Update status
@@ -189,6 +217,16 @@
     return bytes_written;
 }
 
+int
+Socket::read(Buffer &buffer)
+{
+    int result = this->read(buffer.pointer(), buffer.size());
+    if (result >= 0) {
+        buffer.setLength(result);
+    }
+    
+    return result;
+}
 
 int
 Socket::read(void *data, size_t max_size)
@@ -200,7 +238,7 @@
 
     // Check socket status
     if (this->_status != Socket::Connected) {
-        return -1;
+        return -2;
     }
     
     // Update status
--- a/tcp/socket.hpp	Wed Jul 18 11:22:37 2012 +0000
+++ b/tcp/socket.hpp	Wed Jul 18 13:20:32 2012 +0000
@@ -26,6 +26,7 @@
 #ifndef _NETWORK_TCP_SOCKET_HPP_
 #define _NETWORK_TCP_SOCKET_HPP_
 
+#include "../buffer.hpp"
 #include "../socket.hpp"
 #include "../ip/address.hpp"
 #include "../ip/endpoint.hpp"
@@ -39,14 +40,19 @@
         public:            
             int open();
             
-            int connect(ip::Address &address, int port);
+            int connect(const char *hostname, int port);
+            int connect(const std::string hostname, int port);
+            int connect(const ip::Address &address, int port);
             int connect(ip::Endpoint &endpoint);
             int shutdown();
             
             int listen(int max_pending = 10);
             int accept(Socket &client);
         
+            int write(Buffer &buffer);
             int write(void *data, size_t size);
+            
+            int read(Buffer &buffer);
             int read(void *data, size_t max_size);
     };