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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers socket.cpp Source File

socket.cpp

00001 /**
00002  * Copyright (c) 2012, Roy van Dam <roy@vandam-innovations.com>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright notice, this
00009  *    list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright notice,
00011  *    this list of conditions and the following disclaimer in the documentation
00012  *    and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00015  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00016  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00017  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00018  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00019  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00020  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00021  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00022  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00023  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00024  */
00025 
00026 #include "socket.hpp"
00027 using namespace network::udp;
00028 
00029 int
00030 Socket::open()
00031 {
00032     // Check socket status
00033     if (this->_status != Socket::Closed) {
00034         return -1;
00035     }
00036     
00037     // Open socket
00038     this->_socket = lwip_socket(AF_INET, SOCK_DGRAM, 0);
00039     if (this->_socket < 0) {
00040         return -1;
00041     }
00042     
00043     // Update status and return
00044     this->_status = Socket::Open;
00045     return 0;
00046 }
00047 
00048 int
00049 Socket::send(Buffer &buffer, ip::Address &address, int port)
00050 {
00051     ip::Endpoint endpoint(address, port);
00052     return this->send(buffer.data(), buffer.length(), endpoint);
00053 }
00054 
00055 int
00056 Socket::send(Buffer &buffer, ip::Endpoint &endpoint)
00057 {
00058     return this->send(buffer.data(), buffer.length(), endpoint);
00059 }
00060 
00061 int
00062 Socket::send(void *data, size_t size, ip::Address &address, int port)
00063 {
00064     ip::Endpoint endpoint(address, port);
00065     return this->send(data, size, endpoint);
00066 }
00067 
00068 int
00069 Socket::send(void *data, size_t size, ip::Endpoint &endpoint)
00070 {
00071     // Check data buffer and size
00072     if (data == NULL || size == 0) {
00073         return -1;
00074     }
00075 
00076     // Check socket status
00077     if (this->_status != Socket::Open) {
00078         return -1;
00079     }
00080     
00081     // Create native endpoint
00082     struct sockaddr_in native_endpoint;
00083     endpoint.toNative(&native_endpoint);
00084     
00085     // Update status
00086     this->_status = Socket::Sending;
00087     
00088     // Try to write the specified amount of bytes.
00089     int bytes_written = lwip_sendto(this->_socket, data, size, 0,
00090         (const struct sockaddr *)&native_endpoint, sizeof(native_endpoint));
00091     
00092     // Update status
00093     this->_status = Socket::Open;
00094     
00095     // Return the result.
00096     return bytes_written;
00097 }
00098 
00099 int
00100 Socket::receive(Buffer &buffer)
00101 {
00102     int result = this->receive(buffer.data(), buffer.size());
00103     if (result >= 0) {
00104         buffer.length(result);
00105     }
00106     
00107     return result;
00108 }
00109 
00110 int
00111 Socket::receive(void *data, size_t max_size)
00112 {
00113     return this->receive(data, max_size, this->_remote_endpoint);
00114 }
00115 
00116 int
00117 Socket::receive(void *data, size_t max_size, ip::Endpoint &endpoint)
00118 {
00119     // Check data buffer and size
00120     if (data == NULL || max_size == 0) {
00121         return -1;
00122     }
00123 
00124     // Check socket status
00125     if (this->_status != Socket::Open) {
00126         return -1;
00127     }
00128 
00129     // Create native endpoint
00130     struct sockaddr_in native_endpoint;
00131     int native_endpoint_size = sizeof(native_endpoint);
00132     std::memset(&native_endpoint, 0, sizeof(native_endpoint));
00133     
00134     // Update status
00135     this->_status = Socket::Receiving;
00136     
00137     // Try to read a packet from the socket.
00138     int bytes_read = lwip_recvfrom(this->_socket, data, max_size, 0,
00139         (struct sockaddr*)&native_endpoint, (u32_t *)&native_endpoint_size);
00140     
00141     // Update status and return
00142     this->_status = Socket::Open;
00143     
00144     // Did we succeed? 
00145     if (bytes_read < 0) {
00146         return -1;
00147     }
00148     
00149     // Check if we received the endpoint information correctly
00150     if (native_endpoint_size != sizeof(native_endpoint)) {
00151         printf("Warning: invalid endpoint size received\n\r");
00152         return bytes_read;
00153     }
00154     
00155     // Copy remote endpoint information
00156     endpoint.fromNative(&native_endpoint);
00157     
00158     // Return bytes read
00159     return bytes_read;
00160 }