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 } 00208 else { 00209 separate_ip4like_addresses(orig, ip, ip_size, ip2, ip2_size); 00210 } 00211 } 00212 } 00213 00214 void prefer_ipv6(char* ip, size_t ip_size, char* ip2, size_t ip2_size) 00215 { 00216 if (!ip || !ip2) { 00217 return; 00218 } 00219 // assume that that ipv6 is already in formatted to use ':' 00220 // 1. try to found ':'. If it's found then we know that this is ipv6 00221 char *temp; 00222 temp = strchr(ip, ':'); 00223 if (temp) { 00224 // ip has ipv6 address, we can leave 00225 return; 00226 } else { 00227 // ip was not ipv6, check if ip2 is 00228 temp = strchr(ip2, ':'); 00229 if (temp) { 00230 // ipv6 was found in ip2 but not in ip ---> we must swap them. Sadly ip and ip2 might not be pointers 00231 // so we can't just swap them, must use copy. 00232 if (strlen(ip) < ip2_size && strlen(ip2) < ip_size && strlen(ip) < 64) { 00233 char tmp[64]; 00234 strncpy(tmp, ip, strlen(ip)); 00235 tmp[strlen(ip)] = '\0'; 00236 strncpy(ip, ip2, strlen(ip2)); 00237 ip[strlen(ip2)] = '\0'; 00238 strncpy(ip2, tmp, strlen(tmp)); 00239 ip2[strlen(tmp)] = '\0'; 00240 } 00241 } 00242 } 00243 } 00244 00245 void int_to_hex_str(uint8_t num, char* buf) 00246 { 00247 char charNum = num; 00248 char_str_to_hex_str(&charNum, 1, buf); 00249 } 00250 00251 int hex_str_to_int(const char *hex_string, int hex_string_length) 00252 { 00253 const int base = 16; 00254 int character_as_integer, integer_output = 0; 00255 00256 for (int i=0;i<hex_string_length && hex_string[i] != '\0';i++) { 00257 if (hex_string[i] >= '0' && hex_string[i] <= '9') { 00258 character_as_integer = hex_string[i] - '0'; 00259 } else if (hex_string[i] >= 'A' && hex_string[i] <= 'F') { 00260 character_as_integer = hex_string[i] - 'A' + 10; 00261 } else { 00262 character_as_integer = hex_string[i] - 'a' + 10; 00263 } 00264 integer_output *= base; 00265 integer_output += character_as_integer; 00266 } 00267 00268 return integer_output; 00269 } 00270 00271 int hex_str_to_char_str(const char* str, uint16_t len, char *buf) 00272 { 00273 int strcount = 0; 00274 for (int i = 0; i+1 < len; i += 2) { 00275 int upper = hex_str_to_int(str+i, 1); 00276 int lower = hex_str_to_int(str+i+1, 1); 00277 buf[strcount] = ((upper<<4) & 0xF0) | (lower & 0x0F); 00278 strcount++; 00279 } 00280 00281 return strcount; 00282 } 00283 00284 void uint_to_binary_str(uint32_t num, char* str, int str_size, int bit_cnt) 00285 { 00286 if (!str || str_size < bit_cnt) { 00287 return; 00288 } 00289 int tmp, pos = 0; 00290 00291 for (int i = 31; i >= 0; i--) { 00292 tmp = num >> i; 00293 if (i < bit_cnt) { 00294 if (tmp&1) { 00295 str[pos] = 1 + '0'; 00296 } else { 00297 str[pos] = 0 + '0'; 00298 } 00299 pos++; 00300 } 00301 } 00302 } 00303 00304 int char_str_to_hex_str(const char* str, uint16_t len, char *buf, bool omit_leading_zero) 00305 { 00306 if (!str || !buf) { 00307 return 0; 00308 } 00309 00310 char *ptr = buf; 00311 int i=0; 00312 while (i < len) { 00313 if (omit_leading_zero == true && i == 0 && !(str[i]>>4 & 0x0F)) { 00314 *ptr++ = hex_values[(str[i]) & 0x0F]; 00315 } else { 00316 *ptr++ = hex_values[((str[i])>>4) & 0x0F]; 00317 *ptr++ = hex_values[(str[i]) & 0x0F]; 00318 } 00319 i++; 00320 } 00321 return ptr-buf; 00322 } 00323 00324 uint16_t get_dynamic_ip_port() 00325 { 00326 static uint16_t port_counter = RANDOM_PORT_NUMBER_COUNT; 00327 00328 if (port_counter == RANDOM_PORT_NUMBER_COUNT) { 00329 randLIB_seed_random(); 00330 port_counter = randLIB_get_random_in_range(0, RANDOM_PORT_NUMBER_COUNT - 1); 00331 } 00332 00333 port_counter += randLIB_get_random_in_range(1, RANDOM_PORT_NUMBER_MAX_STEP); 00334 if (port_counter >= RANDOM_PORT_NUMBER_COUNT) { 00335 port_counter -= RANDOM_PORT_NUMBER_COUNT; 00336 } 00337 00338 return (RANDOM_PORT_NUMBER_START + port_counter); 00339 } 00340 00341 } // namespace mbed_cellular_util
Generated on Tue Jul 12 2022 12:43:38 by
1.7.2