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.
Dependents: BLE_file_test BLE_Blink ExternalEncoder
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 15:19:48 by
