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