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.
CellularUtil.cpp
00001 /* 00002 * Copyright (c) , Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "CellularUtil.h" 00018 #include <string.h> 00019 #include <stdlib.h> 00020 00021 00022 #include "randLIB.h" 00023 #define RANDOM_PORT_NUMBER_START 49152 00024 #define RANDOM_PORT_NUMBER_END 65535 00025 #define RANDOM_PORT_NUMBER_COUNT (RANDOM_PORT_NUMBER_END - RANDOM_PORT_NUMBER_START + 1) 00026 #define RANDOM_PORT_NUMBER_MAX_STEP 100 00027 00028 00029 namespace mbed_cellular_util { 00030 00031 void convert_ipv6(char *ip) 00032 { 00033 if (!ip) { 00034 return; 00035 } 00036 00037 int len = strlen(ip); 00038 int pos = 0; 00039 int i; 00040 00041 for (i = 0; i < len; i++) { 00042 if (ip[i] == '.') { 00043 pos++; 00044 } 00045 if (pos > 3) { 00046 break; 00047 } 00048 } 00049 00050 // more that 3 periods mean that it was ipv6 but in format of a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12.a13.a14.a15.a16 00051 // we need to convert it to hexadecimal format separated with colons 00052 if (pos > 3) { 00053 pos = 0; 00054 int ip_pos = 0; 00055 char b; 00056 bool set_colon = false; 00057 for (i = 0; i < len; i++) { 00058 if (ip[i] == '.') { 00059 b = (char)strtol(ip + ip_pos, NULL, 10); // convert to char to int so we can change it to hex string 00060 pos += char_str_to_hex_str(&b, 1, ip + pos, !set_colon); // omit leading zeroes with using set_colon flag 00061 if (set_colon) { 00062 ip[pos++] = ':'; 00063 set_colon = false; 00064 } else { 00065 set_colon = true; 00066 } 00067 ip_pos = i + 1; // skip the '.' 00068 } 00069 00070 // handle the last part which does not end with '.' but '\0' 00071 if (i == len - 1) { 00072 b = (char)strtol(ip + ip_pos, NULL, 10); 00073 pos += char_str_to_hex_str(&b, 1, ip + pos, !set_colon); 00074 ip[pos] = '\0'; 00075 } 00076 } 00077 } 00078 } 00079 00080 // For example "32.1.13.184.0.0.205.48.0.0.0.0.0.0.0.0" 00081 void separate_ip4like_addresses(char *orig, char *ip, size_t ip_size, char *ip2, size_t ip2_size) 00082 { 00083 // ipv4-like notation 00084 int len = strlen(orig); 00085 int count = 0, i = 0, pos = 0; 00086 char *temp; 00087 00088 for (; i < len; i++) { 00089 if (orig[i] == '.') { 00090 count++; 00091 if (count == 4) { 00092 pos = i; 00093 } else if (count == 16) { 00094 pos = i; 00095 } 00096 } 00097 } 00098 00099 if (count == 3) { // normal ipv4, copy to ip 00100 if (ip_size > strlen(orig)) { 00101 memcpy(ip, orig, strlen(orig)); 00102 ip[strlen(orig)] = '\0'; 00103 } else { 00104 ip[0] = '\0'; 00105 } 00106 if (ip2) { 00107 ip2[0] = '\0'; 00108 } 00109 } else if (count == 7) { // ipv4 and subnet mask. Need to separate those. 00110 temp = &orig[pos]; 00111 if ((uint8_t)ip_size > temp - orig) { 00112 memcpy(ip, orig, temp - orig); 00113 ip[temp - orig] = '\0'; 00114 } 00115 temp++; // skip the '.' 00116 if (ip2 && (ip2_size > strlen(temp))) { 00117 memcpy(ip2, temp, strlen(temp)); 00118 ip2[strlen(temp)] = '\0'; 00119 } 00120 } else if (count == 15) { // only one ipv6 address in ipv4-like notation 00121 if (ip_size > strlen(orig)) { 00122 memcpy(ip, orig, strlen(orig)); 00123 ip[strlen(orig)] = '\0'; 00124 convert_ipv6(ip); 00125 } else { 00126 ip[0] = '\0'; 00127 } 00128 if (ip2) { 00129 ip2[0] = '\0'; 00130 } 00131 } else if (count == 31) { // ipv6 + ipv6subnet mask in ipv4-like notation separated by dot '.' 00132 temp = &orig[pos]; 00133 if ((uint8_t)ip_size > temp - orig) { 00134 memcpy(ip, orig, temp - orig); 00135 ip[temp - orig] = '\0'; 00136 convert_ipv6(ip); 00137 } 00138 temp++; // skip the '.' 00139 if (ip2 && (ip2_size > strlen(temp))) { 00140 memcpy(ip2, temp, strlen(temp)); 00141 ip2[strlen(temp)] = '\0'; 00142 convert_ipv6(ip2); 00143 } 00144 } 00145 } 00146 00147 void separate_ip_addresses(char *orig, char *ip, size_t ip_size, char *ip2, size_t ip2_size) 00148 { 00149 // orig can include ipv4, ipv6, both or two ip4/ipv6 addresses. 00150 // also format depends on possible AT+CGPIAF 00151 if (!orig || !ip) { 00152 if (ip) { 00153 ip[0] = '\0'; 00154 } 00155 if (ip2) { 00156 ip2[0] = '\0'; 00157 } 00158 return; 00159 } 00160 // 1. try to found ':'. If it's found then we know that possible addresses are separated with space 00161 char *temp; 00162 temp = strchr(orig, ':'); 00163 00164 if (temp != NULL) { 00165 // found ':' 00166 temp = strstr(orig, " "); 00167 // found space as separator and it wasn't in beginning --> contains 2 ip addresses 00168 if (temp && temp != orig) { 00169 if ((uint8_t)ip_size > temp - orig) { 00170 memcpy(ip, orig, temp - orig); 00171 ip[temp - orig] = '\0'; 00172 } else { 00173 ip[0] = '\0'; 00174 } 00175 temp++; // skip the space 00176 if (ip2 && (ip2_size > strlen(temp))) { 00177 memcpy(ip2, temp, strlen(temp)); 00178 ip2[strlen(temp)] = '\0'; 00179 } else if (ip2) { 00180 ip2[0] = '\0'; 00181 } 00182 } else { 00183 // Space was the first char or no space found ---> only one ip, copy to ip 00184 size_t size = strlen(orig); 00185 if (temp) { 00186 size = strlen(temp); 00187 } 00188 00189 if (ip_size > size) { 00190 memcpy(ip, orig, size); 00191 ip[size] = '\0'; 00192 } else { 00193 ip[0] = '\0'; 00194 } 00195 if (ip2) { 00196 ip2[0] = '\0'; 00197 } 00198 } 00199 } else { 00200 temp = strstr(orig, " "); 00201 // found space as separator and it wasn't in beginning --> contains 2 ip addresses 00202 if (temp && temp != orig) { 00203 separate_ip4like_addresses(temp++, ip2, ip2_size, NULL, 0); 00204 orig[temp - orig - 1] = '\0'; 00205 separate_ip4like_addresses(orig, ip, ip_size, NULL, 0); 00206 orig[temp - orig - 1] = ' '; // put space back to keep orig as original 00207 } else { 00208 separate_ip4like_addresses(orig, ip, ip_size, ip2, ip2_size); 00209 } 00210 } 00211 } 00212 00213 void prefer_ipv6(char *ip, size_t ip_size, char *ip2, size_t ip2_size) 00214 { 00215 if (!ip || !ip2) { 00216 return; 00217 } 00218 // assume that that ipv6 is already in formatted to use ':' 00219 // 1. try to found ':'. If it's found then we know that this is ipv6 00220 char *temp; 00221 temp = strchr(ip, ':'); 00222 if (temp) { 00223 // ip has ipv6 address, we can leave 00224 return; 00225 } else { 00226 // ip was not ipv6, check if ip2 is 00227 temp = strchr(ip2, ':'); 00228 if (temp) { 00229 // ipv6 was found in ip2 but not in ip ---> we must swap them. Sadly ip and ip2 might not be pointers 00230 // so we can't just swap them, must use copy. 00231 if (strlen(ip) < ip2_size && strlen(ip2) < ip_size && strlen(ip) < 64) { 00232 char tmp[64]; 00233 strncpy(tmp, ip, strlen(ip)); 00234 tmp[strlen(ip)] = '\0'; 00235 strncpy(ip, ip2, strlen(ip2)); 00236 ip[strlen(ip2)] = '\0'; 00237 strncpy(ip2, tmp, strlen(tmp)); 00238 ip2[strlen(tmp)] = '\0'; 00239 } 00240 } 00241 } 00242 } 00243 00244 void int_to_hex_str(uint8_t num, char *buf) 00245 { 00246 char charNum = num; 00247 char_str_to_hex_str(&charNum, 1, buf); 00248 } 00249 00250 int hex_str_to_int(const char *hex_string, int hex_string_length) 00251 { 00252 const int base = 16; 00253 int character_as_integer, integer_output = 0; 00254 00255 for (int i = 0; i < hex_string_length && hex_string[i] != '\0'; i++) { 00256 if (hex_string[i] >= '0' && hex_string[i] <= '9') { 00257 character_as_integer = hex_string[i] - '0'; 00258 } else if (hex_string[i] >= 'A' && hex_string[i] <= 'F') { 00259 character_as_integer = hex_string[i] - 'A' + 10; 00260 } else { 00261 character_as_integer = hex_string[i] - 'a' + 10; 00262 } 00263 integer_output *= base; 00264 integer_output += character_as_integer; 00265 } 00266 00267 return integer_output; 00268 } 00269 00270 int hex_str_to_char_str(const char *str, uint16_t len, char *buf) 00271 { 00272 int strcount = 0; 00273 for (int i = 0; i + 1 < len; i += 2) { 00274 int upper = hex_str_to_int(str + i, 1); 00275 int lower = hex_str_to_int(str + i + 1, 1); 00276 buf[strcount] = ((upper << 4) & 0xF0) | (lower & 0x0F); 00277 strcount++; 00278 } 00279 00280 return strcount; 00281 } 00282 00283 void uint_to_binary_str(uint32_t num, char *str, int str_size, int bit_cnt) 00284 { 00285 if (!str || str_size < bit_cnt) { 00286 return; 00287 } 00288 int tmp, pos = 0; 00289 00290 for (int i = 31; i >= 0; i--) { 00291 tmp = num >> i; 00292 if (i < bit_cnt) { 00293 if (tmp & 1) { 00294 str[pos] = 1 + '0'; 00295 } else { 00296 str[pos] = 0 + '0'; 00297 } 00298 pos++; 00299 } 00300 } 00301 } 00302 00303 int char_str_to_hex_str(const char *str, uint16_t len, char *buf, bool omit_leading_zero) 00304 { 00305 if (!str || !buf) { 00306 return 0; 00307 } 00308 00309 char *ptr = buf; 00310 int i = 0; 00311 while (i < len) { 00312 if (omit_leading_zero == true && i == 0 && !(str[i] >> 4 & 0x0F)) { 00313 *ptr++ = hex_values[(str[i]) & 0x0F]; 00314 } else { 00315 *ptr++ = hex_values[((str[i]) >> 4) & 0x0F]; 00316 *ptr++ = hex_values[(str[i]) & 0x0F]; 00317 } 00318 i++; 00319 } 00320 return ptr - buf; 00321 } 00322 00323 uint16_t get_dynamic_ip_port() 00324 { 00325 static uint16_t port_counter = RANDOM_PORT_NUMBER_COUNT; 00326 00327 if (port_counter == RANDOM_PORT_NUMBER_COUNT) { 00328 randLIB_seed_random(); 00329 port_counter = randLIB_get_random_in_range(0, RANDOM_PORT_NUMBER_COUNT - 1); 00330 } 00331 00332 port_counter += randLIB_get_random_in_range(1, RANDOM_PORT_NUMBER_MAX_STEP); 00333 port_counter %= RANDOM_PORT_NUMBER_COUNT; 00334 00335 return (RANDOM_PORT_NUMBER_START + port_counter); 00336 } 00337 00338 } // namespace mbed_cellular_util
Generated on Tue Aug 9 2022 00:37:03 by
1.7.2