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 char b; 00070 int scanned = sscanf(&addr[i], "%hhu", &b); 00071 if (scanned < 1) { 00072 return; 00073 } 00074 00075 bytes[count] = b; 00076 00077 for (; addr[i] != '.'; i++) { 00078 if (!addr[i]) { 00079 return; 00080 } 00081 } 00082 00083 i++; 00084 } 00085 } 00086 00087 static int ipv6_scan_chunk(uint16_t *shorts, const char *chunk) { 00088 int count = 0; 00089 int i = 0; 00090 00091 for (; count < NSAPI_IPv6_BYTES/2; count++) { 00092 unsigned short s; 00093 int scanned = sscanf(&chunk[i], "%hx", &s); 00094 if (scanned < 1) { 00095 return count; 00096 } 00097 00098 shorts[count] = s; 00099 00100 for (; chunk[i] != ':'; i++) { 00101 if (!chunk[i]) { 00102 return count+1; 00103 } 00104 } 00105 00106 i++; 00107 } 00108 00109 return count; 00110 } 00111 00112 static void ipv6_from_address(uint8_t *bytes, const char *addr) 00113 { 00114 // Start with zeroed address 00115 uint16_t shorts[NSAPI_IPv6_BYTES/2]; 00116 int suffix = 0; 00117 00118 // Find double colons and scan suffix 00119 for (int i = 0; addr[i]; i++) { 00120 if (addr[i] == ':' && addr[i+1] == ':') { 00121 suffix = ipv6_scan_chunk(shorts, &addr[i+2]); 00122 break; 00123 } 00124 } 00125 00126 // Move suffix to end 00127 memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0], 00128 suffix*sizeof(uint16_t)); 00129 memset(&shorts[0], 0, 00130 (NSAPI_IPv6_BYTES/2-suffix)*sizeof(uint16_t)); 00131 00132 // Scan prefix 00133 ipv6_scan_chunk(shorts, &addr[0]); 00134 00135 // Flip bytes 00136 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) { 00137 bytes[2*i+0] = (uint8_t)(shorts[i] >> 8); 00138 bytes[2*i+1] = (uint8_t)(shorts[i] >> 0); 00139 } 00140 } 00141 00142 static void ipv4_to_address(char *addr, const uint8_t *bytes) 00143 { 00144 sprintf(addr, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); 00145 } 00146 00147 static void ipv6_to_address(char *addr, const uint8_t *bytes) 00148 { 00149 for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) { 00150 sprintf(&addr[5*i], "%02x%02x", bytes[2*i], bytes[2*i+1]); 00151 addr[5*i+4] = ':'; 00152 } 00153 addr[NSAPI_IPv6_SIZE-1] = '\0'; 00154 } 00155 00156 00157 SocketAddress::SocketAddress(nsapi_addr_t addr, uint16_t port) 00158 { 00159 _ip_address[0] = '\0'; 00160 set_addr(addr); 00161 set_port(port); 00162 } 00163 00164 SocketAddress::SocketAddress(const char *addr, uint16_t port) 00165 { 00166 _ip_address[0] = '\0'; 00167 set_ip_address(addr); 00168 set_port(port); 00169 } 00170 00171 SocketAddress::SocketAddress(const void *bytes, nsapi_version_t version, uint16_t port) 00172 { 00173 _ip_address[0] = '\0'; 00174 set_ip_bytes(bytes, version); 00175 set_port(port); 00176 } 00177 00178 SocketAddress::SocketAddress(const SocketAddress &addr) 00179 { 00180 _ip_address[0] = '\0'; 00181 set_addr(addr.get_addr()); 00182 set_port(addr.get_port()); 00183 } 00184 00185 bool SocketAddress::set_ip_address(const char *addr) 00186 { 00187 _ip_address[0] = '\0'; 00188 00189 if (addr && ipv4_is_valid(addr)) { 00190 _addr.version = NSAPI_IPv4 ; 00191 ipv4_from_address(_addr.bytes, addr); 00192 return true; 00193 } else if (addr && ipv6_is_valid(addr)) { 00194 _addr.version = NSAPI_IPv6 ; 00195 ipv6_from_address(_addr.bytes, addr); 00196 return true; 00197 } else { 00198 _addr = nsapi_addr_t(); 00199 return false; 00200 } 00201 } 00202 00203 void SocketAddress::set_ip_bytes(const void *bytes, nsapi_version_t version) 00204 { 00205 nsapi_addr_t addr; 00206 00207 addr = nsapi_addr_t(); 00208 addr.version = version; 00209 if (version == NSAPI_IPv6 ) { 00210 memcpy(addr.bytes, bytes, NSAPI_IPv6_BYTES); 00211 } else if (version == NSAPI_IPv4 ) { 00212 memcpy(addr.bytes, bytes, NSAPI_IPv4_BYTES); 00213 } 00214 set_addr(addr); 00215 } 00216 00217 void SocketAddress::set_addr(nsapi_addr_t addr) 00218 { 00219 _ip_address[0] = '\0'; 00220 _addr = addr; 00221 } 00222 00223 void SocketAddress::set_port(uint16_t port) 00224 { 00225 _port = port; 00226 } 00227 00228 const char *SocketAddress::get_ip_address() const 00229 { 00230 if (_addr.version == NSAPI_UNSPEC ) { 00231 return NULL; 00232 } 00233 00234 if (!_ip_address[0]) { 00235 if (_addr.version == NSAPI_IPv4 ) { 00236 ipv4_to_address(_ip_address, _addr.bytes); 00237 } else if (_addr.version == NSAPI_IPv6 ) { 00238 ipv6_to_address(_ip_address, _addr.bytes); 00239 } 00240 } 00241 00242 return _ip_address; 00243 } 00244 00245 const void *SocketAddress::get_ip_bytes() const 00246 { 00247 return _addr.bytes; 00248 } 00249 00250 nsapi_version_t SocketAddress::get_ip_version() const 00251 { 00252 return _addr.version; 00253 } 00254 00255 nsapi_addr_t SocketAddress::get_addr() const 00256 { 00257 return _addr; 00258 } 00259 00260 uint16_t SocketAddress::get_port() const 00261 { 00262 return _port; 00263 } 00264 00265 SocketAddress::operator bool() const 00266 { 00267 if (_addr.version == NSAPI_IPv4 ) { 00268 for (int i = 0; i < NSAPI_IPv4_BYTES; i++) { 00269 if (_addr.bytes[i]) { 00270 return true; 00271 } 00272 } 00273 00274 return false; 00275 } else if (_addr.version == NSAPI_IPv6 ) { 00276 for (int i = 0; i < NSAPI_IPv6_BYTES; i++) { 00277 if (_addr.bytes[i]) { 00278 return true; 00279 } 00280 } 00281 00282 return false; 00283 } else { 00284 return false; 00285 } 00286 } 00287 00288 bool operator==(const SocketAddress &a, const SocketAddress &b) 00289 { 00290 if (!a && !b) { 00291 return true; 00292 } else if (a._addr.version != b._addr.version) { 00293 return false; 00294 } else if (a._addr.version == NSAPI_IPv4 ) { 00295 return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv4_BYTES) == 0; 00296 } else if (a._addr.version == NSAPI_IPv6 ) { 00297 return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv6_BYTES) == 0; 00298 } 00299 00300 MBED_UNREACHABLE; 00301 } 00302 00303 bool operator!=(const SocketAddress &a, const SocketAddress &b) 00304 { 00305 return !(a == b); 00306 } 00307 00308 void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port) 00309 { 00310 _ip_address[0] = '\0'; 00311 00312 // gethostbyname must check for literals, so can call it directly 00313 int err = iface->gethostbyname(host, this); 00314 _port = port; 00315 if (err) { 00316 _addr = nsapi_addr_t(); 00317 _port = 0; 00318 } 00319 }
Generated on Tue Jul 12 2022 13:31:29 by
