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