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 addr.version = version; 00207 memcpy(addr.bytes, bytes, NSAPI_IP_BYTES); 00208 set_addr(addr); 00209 } 00210 00211 void SocketAddress::set_addr(nsapi_addr_t addr) 00212 { 00213 _ip_address[0] = '\0'; 00214 _addr = addr; 00215 } 00216 00217 void SocketAddress::set_port(uint16_t port) 00218 { 00219 _port = port; 00220 } 00221 00222 const char *SocketAddress::get_ip_address() const 00223 { 00224 if (_addr.version == NSAPI_UNSPEC ) { 00225 return NULL; 00226 } 00227 00228 if (!_ip_address[0]) { 00229 if (_addr.version == NSAPI_IPv4 ) { 00230 ipv4_to_address(_ip_address, _addr.bytes); 00231 } else if (_addr.version == NSAPI_IPv6 ) { 00232 ipv6_to_address(_ip_address, _addr.bytes); 00233 } 00234 } 00235 00236 return _ip_address; 00237 } 00238 00239 const void *SocketAddress::get_ip_bytes() const 00240 { 00241 return _addr.bytes; 00242 } 00243 00244 nsapi_version_t SocketAddress::get_ip_version() const 00245 { 00246 return _addr.version; 00247 } 00248 00249 nsapi_addr_t SocketAddress::get_addr() const 00250 { 00251 return _addr; 00252 } 00253 00254 uint16_t SocketAddress::get_port() const 00255 { 00256 return _port; 00257 } 00258 00259 SocketAddress::operator bool() const 00260 { 00261 if (_addr.version == NSAPI_IPv4 ) { 00262 for (int i = 0; i < NSAPI_IPv4_BYTES; i++) { 00263 if (_addr.bytes[i]) { 00264 return true; 00265 } 00266 } 00267 00268 return false; 00269 } else if (_addr.version == NSAPI_IPv6 ) { 00270 for (int i = 0; i < NSAPI_IPv6_BYTES; i++) { 00271 if (_addr.bytes[i]) { 00272 return true; 00273 } 00274 } 00275 00276 return false; 00277 } else { 00278 return false; 00279 } 00280 } 00281 00282 bool operator==(const SocketAddress &a, const SocketAddress &b) 00283 { 00284 if (!a && !b) { 00285 return true; 00286 } else if (a._addr.version != b._addr.version) { 00287 return false; 00288 } else if (a._addr.version == NSAPI_IPv4 ) { 00289 return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv4_BYTES) == 0; 00290 } else if (a._addr.version == NSAPI_IPv6 ) { 00291 return memcmp(a._addr.bytes, b._addr.bytes, NSAPI_IPv6_BYTES) == 0; 00292 } 00293 } 00294 00295 bool operator!=(const SocketAddress &a, const SocketAddress &b) 00296 { 00297 return !(a == b); 00298 } 00299 00300 void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16_t port) 00301 { 00302 _ip_address[0] = '\0'; 00303 00304 // gethostbyname must check for literals, so can call it directly 00305 int err = iface->gethostbyname(host, this); 00306 _port = port; 00307 if (err) { 00308 _addr = nsapi_addr_t(); 00309 _port = 0; 00310 } 00311 }
Generated on Tue Jul 12 2022 18:19:34 by
