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.
Dependencies: nRF51_Vdd TextLCD BME280
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 Jul 12 2022 15:15:41 by
