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
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::tcp; 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_STREAM, 0); 00039 if (this->_socket < 0) { 00040 return -2; 00041 } 00042 00043 // Update status and return 00044 this->_status = Socket::Open; 00045 return 0; 00046 } 00047 00048 int 00049 Socket::connect(const char *hostname, int port) 00050 { 00051 ip::Address address; 00052 if (address.fromHostname(hostname) < 0) { 00053 return -1; 00054 } 00055 00056 return this->connect(address, port); 00057 } 00058 00059 int 00060 Socket::connect(const std::string hostname, int port) 00061 { 00062 ip::Address address; 00063 if (address.fromHostname(hostname) < 0) { 00064 return -1; 00065 } 00066 00067 return this->connect(address, port); 00068 } 00069 00070 int 00071 Socket::connect(const ip::Address &address, int port) 00072 { 00073 ip::Endpoint endpoint(address, port); 00074 return this->connect(endpoint); 00075 } 00076 00077 int 00078 Socket::connect(ip::Endpoint &endpoint) 00079 { 00080 // Check socket status 00081 if ((this->_status != Socket::Open) && 00082 (this->_status != Socket::Disconnected)) 00083 { 00084 return -1; 00085 } 00086 00087 // Create native endpoint 00088 struct sockaddr_in native_endpoint; 00089 endpoint.toNative(&native_endpoint); 00090 00091 // Attempt to connect with remote endpoint. 00092 int result = lwip_connect(this->_socket, 00093 (const struct sockaddr *)&native_endpoint, sizeof(native_endpoint)); 00094 00095 // Check result 00096 if (result < 0) { 00097 return -2; 00098 } 00099 00100 // Update remote endpoint information. 00101 this->_remote_endpoint = endpoint; 00102 00103 // Update status and return 00104 this->_status = Socket::Connected; 00105 return 0; 00106 } 00107 00108 int 00109 Socket::shutdown() 00110 { 00111 // Check socket status 00112 if (this->_status != Socket::Connected) { 00113 return -1; 00114 } 00115 00116 // Attempt to shutdown the connection. 00117 int result = lwip_shutdown(this->_socket, SHUT_RDWR); 00118 if (result < 0) { 00119 return -2; 00120 } 00121 00122 // Update status and return 00123 this->_status = Socket::Disconnected; 00124 return 0; 00125 } 00126 00127 int 00128 Socket::listen(int max_pending) 00129 { 00130 // Check socket status 00131 if (this->_status != Socket::Open) { 00132 return -1; 00133 } 00134 00135 // Put socket into listening mode. 00136 int result = lwip_listen(this->_socket, max_pending); 00137 if (result < 0) { 00138 return -2; 00139 } 00140 00141 // Update status and return 00142 this->_status = Socket::Listening; 00143 return 0; 00144 } 00145 00146 int 00147 Socket::accept(Socket &client) 00148 { 00149 // Check socket status 00150 if (this->_status != Socket::Listening) { 00151 return -1; 00152 } 00153 00154 // Check client socket status 00155 if (client._status != Socket::Closed) { 00156 return -2; 00157 } 00158 00159 // Create native endpoint 00160 struct sockaddr_in native_endpoint; 00161 int native_endpoint_size = sizeof(native_endpoint); 00162 std::memset(&native_endpoint, 0, sizeof(native_endpoint)); 00163 00164 // Accept new (pending) connections. 00165 int socket = lwip_accept(this->_socket, 00166 (struct sockaddr*)&native_endpoint, (u32_t *)&native_endpoint_size); 00167 00168 // Did we succeed? 00169 if (socket < 0) { 00170 return -3; 00171 } 00172 00173 // Check if we received the endpoint information correctly. 00174 if (native_endpoint_size != sizeof(native_endpoint)) { 00175 printf("Warning: invalid endpoint size received\n\r"); 00176 } 00177 00178 // Populate client socket 00179 client._socket = socket; 00180 client._status = Socket::Connected; 00181 client._remote_endpoint.fromNative(&native_endpoint); 00182 00183 return 0; 00184 } 00185 00186 int 00187 Socket::write(Buffer &buffer) 00188 { 00189 return this->write(buffer.data(), buffer.length()); 00190 } 00191 00192 int 00193 Socket::write(void *data, size_t size) 00194 { 00195 // Check data buffer and size 00196 if (data == NULL || size == 0) { 00197 return -1; 00198 } 00199 00200 // Check socket status 00201 if (this->_status != Socket::Connected) { 00202 return -2; 00203 } 00204 00205 // Update status 00206 this->_status = Socket::Sending; 00207 00208 // Try to send the specified amount of bytes. 00209 int bytes_written = lwip_send(this->_socket, data, size, 0); 00210 00211 // Update status 00212 this->_status = (bytes_written == 0) 00213 ? Socket::Disconnected 00214 : Socket::Connected; 00215 00216 // Return the result. 00217 return bytes_written; 00218 } 00219 00220 int 00221 Socket::read(Buffer &buffer) 00222 { 00223 int result = this->read(buffer.data(), buffer.size()); 00224 if (result >= 0) { 00225 buffer.length(result); 00226 } 00227 00228 return result; 00229 } 00230 00231 int 00232 Socket::read(void *data, size_t max_size) 00233 { 00234 // Check data buffer and size 00235 if (data == NULL || max_size == 0) { 00236 return -1; 00237 } 00238 00239 // Check socket status 00240 if (this->_status != Socket::Connected) { 00241 return -2; 00242 } 00243 00244 // Update status 00245 this->_status = Socket::Receiving; 00246 00247 // Try to read data from the socket. 00248 int bytes_read = lwip_recv(this->_socket, data, max_size, 0); 00249 00250 // Update status 00251 this->_status = (bytes_read == 0) 00252 ? Socket::Disconnected 00253 : Socket::Connected; 00254 00255 // Return bytes read 00256 return bytes_read; 00257 }
Generated on Tue Jul 12 2022 12:58:20 by 1.7.2