Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SocketAddress.cpp
00001 /* Socket 00002 * Copyright (c) 2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "SocketAddress.h" 00018 #include "NetworkInterface.h" 00019 #include "NetworkStack.h" 00020 #include <string.h> 00021 #include "mbed.h" 00022 00023 00024 static bool ipv4_is_valid(const char *addr) 00025 { 00026 int i = 0; 00027 00028 // Check each digit for [0-9.] 00029 for (; addr[i]; i++) { 00030 if (!(addr[i] >= '0' && addr[i] <= '9') && addr[i] != '.') { 00031 return false; 00032 } 00033 } 00034 00035 // Ending with '.' garuntees host 00036 if (i > 0 && addr[i-1] == '.') { 00037 return false; 00038 } 00039 00040 return true; 00041 } 00042 00043 static bool ipv6_is_valid(const char *addr) 00044 { 00045 // Check each digit for [0-9a-fA-F:] 00046 // Must also have at least 2 colons 00047 int colons = 0; 00048 for (int i = 0; addr[i]; i++) { 00049 if (!(addr[i] >= '0' && addr[i] <= '9') && 00050 !(addr[i] >= 'a' && addr[i] <= 'f') && 00051 !(addr[i] >= 'A' && addr[i] <= 'F') && 00052 addr[i] != ':') { 00053 return false; 00054 } 00055 if (addr[i] == ':') { 00056 colons++; 00057 } 00058 } 00059 00060 return colons >= 2; 00061 } 00062 00063 static void ipv4_from_address(uint8_t *bytes, const char *addr) 00064 { 00065 int count = 0; 00066 int i = 0; 00067 00068 for (; count < NSAPI_IPv4_BYTES; count++) { 00069 unsigned d; 00070 // Not using %hh, since it might be missing in newlib-based toolchains. 00071 // See also: https://git.io/vxiw5 00072 int scanned = sscanf(&addr[i], "%u", &d); 00073 if (scanned < 1) { 00074 return; 00075 } 00076 00077 bytes[count] = static_cast<uint8_t>(d); 00078 00079 for (; addr[i] != '.'; i++) { 00080 if (!addr[i]) { 00081 return; 00082 } 00083 } 00084 00085 i++; 00086 } 00087 } 00088 00089 static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) { 00090 int count = 0; 00091 int i = 0; 00092 00093 for (; count < NSAPI_IPv6_BYTES/2; count++) { 00094 unsigned short s; 00095 int scanned = sscanf(&chunk[i], "%hx", &s); 00096 if (scanned < 1) { 00097 return count; 00098 } 00099 00100 shorts[count] = s; 00101 00102 for (; chunk[i] != ':'; i++) { 00103 if (!chunk[i]) { 00104 return count+1; 00105 } 00106 } 00107 00108 i++; 00109 } 00110 00111 return count; 00112 } 00113 00114 static void ipv6_from_address(uint8_t *bytes, const char *addr) 00115 { 00116 // Start with zeroed address 00117 uint16_t shorts[NSAPI_IPv6_BYTES/2]; 00118 int suffix = 0; 00119 00120 // Find double colons and scan suffix 00121 for (int i = 0; addr[i]; i++) { 00122 if (addr[i] == ':' && addr[i+1] == ':') { 00123 suffix = ipv6_scan_chunk(shorts, &addr[i+2]); 00124 break; 00125 } 00126 } 00127 00128 // Move suffix to end 00129 memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0], 00130 suffix*sizeof(uint16_t)); 00131 memset(&shorts[0], 0, 00132 (NSAPI_IPv6_BYTES/2-suffix)*sizeof(uint16_t)); 00133 00134 // Scan prefix 00135 ipv6_scan_chunk(shorts, &addr[0]); 00136 00137 // Flip bytes 00138 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) { 00139 bytes[2*i+0] = (uint8_t)(shorts[i] >> 8); 00140 bytes[2*i+1] = (uint8_t)(shorts[i] >> 0); 00141 } 00142 } 00143 00144 static void ipv4_to_address(char *addr, const uint8_t *bytes) 00145 { 00146 sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); 00147 } 00148 00149 static void ipv6_to_address(char *addr, const uint8_t *bytes) 00150 { 00151 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) { 00152 sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]); 00153 addr[5*i+4] = ':'; 00154 } 00155 addr[NSAPI_IPv6_SIZE-1] = '\0'; 00156 } 00157 00158 00159 SocketAddress::SocketAddress(nsapi_addr_t addr, uint16_t port) 00160 { 00161 _ip_address[0] = '\0'; 00162 set_addr(addr); 00163 set_port(port); 00164 } 00165 00166 SocketAddress::SocketAddress(const char *addr, uint16_t port) 00167 { 00168 _ip_address[0] = '\0'; 00169 set_ip_address(addr); 00170 set_port(port); 00171 } 00172 00173 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port) 00174 { 00175 _ip_address[0] = '\0'; 00176 set_ip_bytes(bytes, version); 00177 set_port(port); 00178 } 00179 00180 SocketAddress::SocketAddress(const SocketAddress &addr) 00181 { 00182 _ip_address[0] = '\0'; 00183 set_addr(addr.get_addr()); 00184 set_port(addr.get_port()); 00185 } 00186 00187 bool SocketAddress::set_ip_address(const char *addr) 00188 { 00189 _ip_address[0] = '\0'; 00190 00191 if (addr && ipv4_is_valid(addr)) { 00192 _addr.version = NSAPI_IPv4 ; 00193 ipv4_from_address(_addr.bytes, addr); 00194 return true; 00195 } else if (addr && ipv6_is_valid(addr)) { 00196 _addr.version = NSAPI_IPv6 ; 00197 ipv6_from_address(_addr.bytes, addr); 00198 return true; 00199 } else { 00200 _addr = nsapi_addr_t(); 00201 return false; 00202 } 00203 } 00204 00205 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version) 00206 { 00207 nsapi_addr_t addr; 00208 00209 addr = nsapi_addr_t(); 00210 addr.version = version; 00211 if (version == NSAPI_IPv6 ) { 00212 memcpy(addr.bytes, bytes, NSAPI_IPv6_BYTES); 00213 } else if (version == NSAPI_IPv4 ) { 00214 memcpy(addr.bytes, bytes, NSAPI_IPv4_BYTES); 00215 } 00216 set_addr(addr); 00217 } 00218 00219 void SocketAddress::set_addr(nsapi_addr_t addr) 00220 { 00221 _ip_address[0] = '\0'; 00222 _addr = addr; 00223 } 00224 00225 void SocketAddress::set_port(uint16_t port) 00226 { 00227 _port = port; 00228 } 00229 00230 const char *SocketAddress::get_ip_address() const 00231 { 00232 if (_addr.version == NSAPI_UNSPEC ) { 00233 return NULL; 00234 } 00235 00236 if (!_ip_address[0]) { 00237 if (_addr.version == NSAPI_IPv4 ) { 00238 ipv4_to_address(_ip_address, _addr.bytes); 00239 } else if (_addr.version == NSAPI_IPv6 ) { 00240 ipv6_to_address(_ip_address, _addr.bytes); 00241 } 00242 } 00243 00244 return _ip_address; 00245 } 00246 00247 const void *SocketAddress::get_ip_bytes() const 00248 { 00249 return _addr.bytes; 00250 } 00251 00252 nsapi_version_t SocketAddress::get_ip_version() const 00253 { 00254 return _addr.version; 00255 } 00256 00257 nsapi_addr_t SocketAddress::get_addr() const 00258 { 00259 return _addr; 00260 } 00261 00262 uint16_t SocketAddress::get_port() const 00263 { 00264 return _port; 00265 } 00266 00267 SocketAddress::operator bool() const 00268 { 00269 if (_addr.version == NSAPI_IPv4 ) { 00270 for (int i = 0; i < NSAPI_IPv4_BYTES; i++) { 00271 if (_addr.bytes[i]) { 00272 return true; 00273 } 00274 } 00275 00276 return false; 00277 } else if (_addr.version == NSAPI_IPv6 ) { 00278 for (int i = 0; i < NSAPI_IPv6_BYTES; i++) { 00279 if (_addr.bytes[i]) { 00280 return true; 00281 } 00282 } 00283 00284 return false; 00285 } else { 00286 return false; 00287 } 00288 } 00289 00290 bool operator==(const SocketAddress &a, const SocketAddress &b) 00291 { 00292 if (!a && !b) { 00293 return true; 00294 } else if (a._addr.version != b._addr.version) { 00295 return false; 00296 } else if (a._addr.version == NSAPI_IPv4 ) { 00297 return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv4_BYTES) == 0; 00298 } else if (a._addr.version == NSAPI_IPv6 ) { 00299 return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv6_BYTES) == 0; 00300 } 00301 00302 MBED_UNREACHABLE; 00303 } 00304 00305 bool operator!=(const SocketAddress &a, const SocketAddress &b) 00306 { 00307 return !(a == b); 00308 } 00309 00310 void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port) 00311 { 00312 _ip_address[0] = '\0'; 00313 00314 // gethostbyname must check for literals, so can call it directly 00315 int err = iface->gethostbyname(host, this); 00316 _port = port; 00317 if (err) { 00318 _addr = nsapi_addr_t(); 00319 _port = 0; 00320 } 00321 }
Generated on Tue Jul 12 2022 12:32:55 by
