1 /*
2  * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3  */
4 #include <stdio.h>
5 
6 #include "string.h"
7 #include "linkkit/infra/infra_types.h"
8 #include "linkkit/infra/infra_defs.h"
9 #include "linkkit/infra/infra_string.h"
10 #include "linkkit/infra/infra_httpc.h"
11 #include "linkkit/infra/infra_sha256.h"
12 #include "dynreg_internal.h"
13 #include "linkkit/dynreg_api.h"
14 #ifdef MQTT_DYNAMIC_REGISTER
15 #include "linkkit/dev_sign_api.h"
16 #include "linkkit/mqtt_api.h"
17 #endif
18 
19 #define HTTP_RESPONSE_PAYLOAD_LEN     (256)
20 
21 #define DYNREG_RANDOM_KEY_LENGTH      (15)
22 #define DYNREG_SIGN_LENGTH            (65)
23 #define DYNREG_SIGN_METHOD_HMACSHA256 "hmacsha256"
24 
25 typedef struct {
26     char *payload;
27     int payload_len;
28 } dynreg_http_response_t;
29 
_parse_string_value(char * payload,int * pos,int * start,int * end)30 static int _parse_string_value(char *payload, int *pos, int *start, int *end)
31 {
32     int idx = 0;
33 
34     for (idx = *pos + 1; idx < strlen(payload); idx++) {
35         if (payload[idx] == '\"') {
36             break;
37         }
38     }
39     *start = *pos + 1;
40     *end = idx - 1;
41     *pos = idx;
42 
43     return 0;
44 }
45 
_parse_dynreg_value(char * payload,char * key,int * pos,int * start,int * end)46 static int _parse_dynreg_value(char *payload, char *key, int *pos, int *start,
47                                int *end)
48 {
49     int idx = 0;
50     /* printf("=====%s\n",&payload[*pos]); */
51 
52     if (memcmp(key, "code", strlen("code")) == 0) {
53         for (idx = *pos; idx < strlen(payload); idx++) {
54             if (payload[idx] < '0' || payload[idx] > '9') {
55                 break;
56             }
57         }
58         *start = *pos;
59         *end = idx - 1;
60         *pos = *end;
61         return 0;
62     } else if (memcmp(key, "data", strlen("data")) == 0) {
63         int bracket_cnt = 0;
64         if (payload[*pos] != '{') {
65             return -1;
66         }
67         for (idx = *pos; idx < strlen(payload); idx++) {
68             if (payload[idx] == '{') {
69                 bracket_cnt++;
70             } else if (payload[idx] == '}') {
71                 bracket_cnt--;
72             }
73             if (bracket_cnt == 0) {
74                 break;
75             }
76         }
77         *start = *pos;
78         *end = idx;
79         *pos = *end;
80         return 0;
81     } else {
82         if (payload[*pos] != '\"') {
83             return -1;
84         }
85         return _parse_string_value(payload, pos, start, end);
86     }
87 
88     /* return -1; */
89 }
90 
_parse_dynreg_result(char * payload,char * key,int * start,int * end)91 static int _parse_dynreg_result(char *payload, char *key, int *start, int *end)
92 {
93     int res = 0, idx = 0, pos = 0;
94 
95     for (idx = 0; idx < strlen(payload); idx++) {
96         /* printf("loop start: %s\n",&payload[idx]); */
97         if (payload[idx] == '\"') {
98             for (pos = idx + 1; pos < strlen(payload); pos++) {
99                 if (payload[pos] == '\"') {
100                     /* printf("key: %.*s\n",pos - idx - 1, &payload[idx+1]); */
101                     break;
102                 }
103             }
104 
105             if (pos == strlen(payload) || payload[pos + 1] != ':') {
106                 return -1;
107             }
108 
109             pos += 2;
110             res = _parse_dynreg_value(payload, key, &pos, start, end);
111             if (res == 0 && memcmp(key, &payload[idx + 1], strlen(key)) == 0) {
112                 /* printf("value: %.*s\n",*end - *start + 1,&payload[*start]);
113                  */
114                 return 0;
115             }
116 
117             idx = pos;
118         }
119     }
120 
121     printf("exit 4\n");
122     return -1;
123 }
124 
_calc_dynreg_sign(char product_key[IOTX_PRODUCT_KEY_LEN],char product_secret[IOTX_PRODUCT_SECRET_LEN],char device_name[IOTX_DEVICE_NAME_LEN],char random[DYNREG_RANDOM_KEY_LENGTH+1],char sign[DYNREG_SIGN_LENGTH])125 static int _calc_dynreg_sign(char product_key[IOTX_PRODUCT_KEY_LEN],
126                              char product_secret[IOTX_PRODUCT_SECRET_LEN],
127                              char device_name[IOTX_DEVICE_NAME_LEN],
128                              char random[DYNREG_RANDOM_KEY_LENGTH + 1],
129                              char sign[DYNREG_SIGN_LENGTH])
130 {
131     int sign_source_len = 0;
132     uint8_t signnum[32];
133     uint8_t *sign_source = NULL;
134     const char *dynamic_register_sign_fmt = "deviceName%sproductKey%srandom%s";
135 
136     /* Start Dynamic Register */
137     memset(random, 0, DYNREG_RANDOM_KEY_LENGTH + 1);
138     memcpy(random, "8Ygb7ULYh53B6OA", strlen("8Ygb7ULYh53B6OA"));
139     dynreg_info("Random Key: %s", random);
140 
141     /* Calculate SHA256 Value */
142     sign_source_len = strlen(dynamic_register_sign_fmt) + strlen(device_name) +
143                       strlen(product_key) + strlen(random) + 1;
144     sign_source = dynreg_malloc(sign_source_len);
145     if (sign_source == NULL) {
146         dynreg_err("Memory Not Enough");
147         return FAIL_RETURN;
148     }
149     memset(sign_source, 0, sign_source_len);
150     HAL_Snprintf((char *)sign_source, sign_source_len,
151                  dynamic_register_sign_fmt, device_name, product_key, random);
152 
153     utils_hmac_sha256(sign_source, strlen((const char *)sign_source),
154                       (uint8_t *)product_secret, strlen(product_secret),
155                       signnum);
156     infra_hex2str(signnum, 32, sign);
157     dynreg_free(sign_source);
158     dynreg_info("Sign: %s", sign);
159 
160     return SUCCESS_RETURN;
161 }
162 
_recv_callback(char * ptr,int length,int total_length,void * userdata)163 static int _recv_callback(char *ptr, int length, int total_length,
164                           void *userdata)
165 {
166     dynreg_http_response_t *response = (dynreg_http_response_t *)userdata;
167     if (strlen(response->payload) + length > response->payload_len) {
168         return FAIL_RETURN;
169     }
170     memcpy(response->payload + strlen(response->payload), ptr, length);
171 
172     return length;
173 }
174 
_fetch_dynreg_http_resp(char * request_payload,char * response_payload,iotx_http_region_types_t region,char device_secret[IOTX_DEVICE_SECRET_LEN])175 static int _fetch_dynreg_http_resp(char *request_payload,
176                                    char *response_payload,
177                                    iotx_http_region_types_t region,
178                                    char device_secret[IOTX_DEVICE_SECRET_LEN])
179 {
180     int res = 0;
181     const char *domain = NULL;
182     const char *url_format = "http://%s/auth/register/device";
183     char *url = NULL;
184     int url_len = 0;
185     const char *pub_key = NULL;
186     void *http_handle = NULL;
187     int port = 443;
188     iotx_http_method_t method = IOTX_HTTP_POST;
189     int timeout_ms = 10000;
190     char *header =
191         "Accept: text/xml,text/javascript,text/html,application/json\r\n"
192         "Content-Type: application/x-www-form-urlencoded\r\n";
193     int http_recv_maxlen = HTTP_RESPONSE_PAYLOAD_LEN;
194     dynreg_http_response_t response;
195     int start = 0, end = 0, data_start = 0, data_end = 0;
196 
197     domain = g_infra_http_domain[region];
198     if (NULL == domain) {
199         dynreg_err("Get domain failed");
200         return FAIL_RETURN;
201     }
202     url_len = strlen(url_format) + strlen(domain) + 1;
203     url = (char *)dynreg_malloc(url_len);
204     if (NULL == url) {
205         dynreg_err("Not Enough Memory");
206         return FAIL_RETURN;
207     }
208     memset(url, 0, url_len);
209     HAL_Snprintf(url, url_len, url_format, domain);
210 
211     memset(&response, 0, sizeof(dynreg_http_response_t));
212     response.payload = response_payload;
213     response.payload_len = HTTP_RESPONSE_PAYLOAD_LEN;
214 #ifdef SUPPORT_TLS
215     {
216         extern const char *iotx_ca_crt;
217         pub_key = iotx_ca_crt;
218     }
219 #endif
220 
221     http_handle = wrapper_http_init();
222     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_URL, (void *)url);
223     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_PORT, (void *)&port);
224     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_METHOD, (void *)&method);
225     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_HEADER, (void *)header);
226     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_CERT, (void *)pub_key);
227     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_TIMEOUT, (void *)&timeout_ms);
228     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_RECVCALLBACK,
229                         (void *)_recv_callback);
230     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_RECVMAXLEN,
231                         (void *)&http_recv_maxlen);
232     wrapper_http_setopt(http_handle, IOTX_HTTPOPT_RECVCONTEXT,
233                         (void *)&response);
234 
235     res = wrapper_http_perform(http_handle, request_payload,
236                                strlen(request_payload));
237     wrapper_http_deinit(&http_handle);
238 
239     if (res < SUCCESS_RETURN) {
240         dynreg_err("Http Download Failed");
241         dynreg_free(url);
242         return FAIL_RETURN;
243     }
244     dynreg_free(url);
245     dynreg_info("Http Response Payload: %s", response_payload);
246 
247     _parse_dynreg_result(response_payload, "code", &start, &end);
248     dynreg_info("Dynamic Register Code: %.*s", end - start + 1,
249                 &response_payload[start]);
250 
251     if (memcmp(&response_payload[start], "200", strlen("200")) != 0) {
252         return FAIL_RETURN;
253     }
254 
255     _parse_dynreg_result(response_payload, "data", &data_start, &data_end);
256     /*  dynreg_info("value: %.*s\n",data_end - data_start +
257      * 1,&response_payload[data_start]); */
258 
259     _parse_dynreg_result(&response_payload[data_start + 1], "deviceSecret",
260                          &start, &end);
261     dynreg_info("Dynamic Register Device Secret: %.*s", end - start + 1,
262                 &response_payload[data_start + 1 + start]);
263 
264     if (end - start + 1 > IOTX_DEVICE_SECRET_LEN) {
265         return FAIL_RETURN;
266     }
267 
268     memcpy(device_secret, &response_payload[data_start + 1 + start],
269            end - start + 1);
270 
271     return SUCCESS_RETURN;
272 }
273 
_http_dynamic_register(iotx_http_region_types_t region,iotx_dev_meta_info_t * meta)274 int32_t _http_dynamic_register(iotx_http_region_types_t region,
275                                iotx_dev_meta_info_t *meta)
276 {
277     int res = 0, dynamic_register_request_len = 0;
278     char sign[DYNREG_SIGN_LENGTH] = { 0 };
279     char random[DYNREG_RANDOM_KEY_LENGTH + 1] = { 0 };
280     const char *dynamic_register_format =
281         "productKey=%s&deviceName=%s&random=%s&sign=%s&signMethod=%s";
282     char *dynamic_register_request = NULL;
283     char *dynamic_register_response = NULL;
284 
285     if (strlen(meta->product_key) > IOTX_PRODUCT_KEY_LEN ||
286         strlen(meta->product_secret) > IOTX_PRODUCT_SECRET_LEN ||
287         strlen(meta->device_name) > IOTX_DEVICE_NAME_LEN) {
288         return FAIL_RETURN;
289     }
290 
291     /* Calcute Signature */
292     res = _calc_dynreg_sign(meta->product_key, meta->product_secret,
293                             meta->device_name, random, sign);
294     if (res != SUCCESS_RETURN) {
295         dynreg_err("Calculate Sign Failed");
296         return FAIL_RETURN;
297     }
298 
299     /* Assemble Http Dynamic Register Request Payload */
300     dynamic_register_request_len =
301         strlen(dynamic_register_format) + strlen(meta->product_key) +
302         strlen(meta->device_name) + strlen(random) + strlen(sign) +
303         strlen(DYNREG_SIGN_METHOD_HMACSHA256) + 1;
304     dynamic_register_request = dynreg_malloc(dynamic_register_request_len);
305     if (dynamic_register_request == NULL) {
306         dynreg_err("Not Enough Memory");
307         return FAIL_RETURN;
308     }
309     memset(dynamic_register_request, 0, dynamic_register_request_len);
310     HAL_Snprintf(dynamic_register_request, dynamic_register_request_len,
311                  dynamic_register_format, meta->product_key, meta->device_name,
312                  random, sign, DYNREG_SIGN_METHOD_HMACSHA256);
313 
314     dynamic_register_response = dynreg_malloc(HTTP_RESPONSE_PAYLOAD_LEN);
315     if (dynamic_register_response == NULL) {
316         dynreg_err("Not Enough Memory");
317         dynreg_free(dynamic_register_request);
318         return FAIL_RETURN;
319     }
320     memset(dynamic_register_response, 0, HTTP_RESPONSE_PAYLOAD_LEN);
321 
322     /* Send Http Request For Getting Device Secret */
323     res = _fetch_dynreg_http_resp(dynamic_register_request,
324                                   dynamic_register_response, region,
325                                   meta->device_secret);
326 
327 #ifdef INFRA_LOG_NETWORK_PAYLOAD
328     dynreg_dbg("Downstream Payload:");
329     iotx_facility_json_print(dynamic_register_response, LOG_DEBUG_LEVEL, '<');
330 #endif
331 
332     dynreg_free(dynamic_register_request);
333     dynreg_free(dynamic_register_response);
334     if (res != SUCCESS_RETURN) {
335         dynreg_err("Get Device Secret Failed");
336         return FAIL_RETURN;
337     }
338 
339     return SUCCESS_RETURN;
340 }
341 
342 #ifdef MQTT_DYNAMIC_REGISTER
_mqtt_dynreg_sign_password(iotx_dev_meta_info_t * meta_info,iotx_sign_mqtt_t * signout,char * rand)343 static int _mqtt_dynreg_sign_password(iotx_dev_meta_info_t *meta_info,
344                                       iotx_sign_mqtt_t *signout, char *rand)
345 {
346     char signsource[DEV_SIGN_SOURCE_MAXLEN] = { 0 };
347     uint16_t signsource_len = 0;
348     const char sign_fmt[] = "deviceName%sproductKey%srandom%s";
349     uint8_t sign_hex[32] = { 0 };
350 
351     signsource_len = strlen(sign_fmt) + strlen(meta_info->device_name) + 1 +
352                      strlen(meta_info->product_key) + strlen(rand) + 1;
353     if (signsource_len >= DEV_SIGN_SOURCE_MAXLEN) {
354         return ERROR_DEV_SIGN_SOURCE_TOO_SHORT;
355     }
356     memset(signsource, 0, signsource_len);
357     memcpy(signsource, "deviceName", strlen("deviceName"));
358     memcpy(signsource + strlen(signsource), meta_info->device_name,
359            strlen(meta_info->device_name));
360     memcpy(signsource + strlen(signsource), "productKey", strlen("productKey"));
361     memcpy(signsource + strlen(signsource), meta_info->product_key,
362            strlen(meta_info->product_key));
363     memcpy(signsource + strlen(signsource), "random", strlen("random"));
364     memcpy(signsource + strlen(signsource), rand, strlen(rand));
365 
366     utils_hmac_sha256((const uint8_t *)signsource, strlen(signsource),
367                       (uint8_t *)meta_info->product_secret,
368                       strlen(meta_info->product_secret), sign_hex);
369     infra_hex2str(sign_hex, 32, signout->password);
370 
371     return SUCCESS_RETURN;
372 }
373 
_mqtt_dynreg_sign_clientid(iotx_dev_meta_info_t * meta_info,iotx_sign_mqtt_t * signout,char * rand)374 static int32_t _mqtt_dynreg_sign_clientid(iotx_dev_meta_info_t *meta_info,
375                                           iotx_sign_mqtt_t *signout, char *rand)
376 {
377     const char *clientid1 = "|authType=register,random=";
378     const char *clientid2 = ",signmethod=hmacsha256,securemode=2|";
379     uint32_t clientid_len = 0;
380 
381     clientid_len = strlen(meta_info->product_key) + 1 +
382                    strlen(meta_info->device_name) + strlen(clientid1) +
383                    strlen(rand) + strlen(clientid2) + 1;
384     if (clientid_len >= DEV_SIGN_CLIENT_ID_MAXLEN) {
385         return ERROR_DEV_SIGN_CLIENT_ID_TOO_SHORT;
386     }
387     memset(signout->clientid, 0, clientid_len);
388     memcpy(signout->clientid, meta_info->product_key,
389            strlen(meta_info->product_key));
390     memcpy(signout->clientid + strlen(signout->clientid), ".", strlen("."));
391     memcpy(signout->clientid + strlen(signout->clientid),
392            meta_info->device_name, strlen(meta_info->device_name));
393     memcpy(signout->clientid + strlen(signout->clientid), clientid1,
394            strlen(clientid1));
395     memcpy(signout->clientid + strlen(signout->clientid), rand, strlen(rand));
396     memcpy(signout->clientid + strlen(signout->clientid), clientid2,
397            strlen(clientid2));
398 
399     return SUCCESS_RETURN;
400 }
401 
_mqtt_dynreg_topic_handle(void * pcontext,void * pclient,iotx_mqtt_event_msg_pt msg)402 void _mqtt_dynreg_topic_handle(void *pcontext, void *pclient,
403                                iotx_mqtt_event_msg_pt msg)
404 {
405     int32_t res = 0;
406     char *ds = (char *)pcontext;
407     iotx_mqtt_topic_info_t *topic_info = (iotx_mqtt_topic_info_pt)msg->msg;
408     const char *asterisk = "**********************";
409 
410     switch (msg->event_type) {
411     case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
412         {
413             /* print topic name and topic message */
414             char *device_secret = NULL;
415             uint32_t device_secret_len = 0;
416 
417             /* parse secret */
418             res = infra_json_value((char *)topic_info->payload,
419                                    topic_info->payload_len, "deviceSecret",
420                                    strlen("deviceSecret"), &device_secret,
421                                    &device_secret_len);
422             if (res == SUCCESS_RETURN) {
423                 memcpy(ds, device_secret + 1, device_secret_len - 2);
424                 memcpy(device_secret + 1 + 5, asterisk, strlen(asterisk));
425                 dynreg_info("Topic  : %.*s", topic_info->topic_len,
426                             topic_info->ptopic);
427                 dynreg_info("Payload: %.*s", topic_info->payload_len,
428                             topic_info->payload);
429             }
430         }
431         break;
432     default:
433         break;
434     }
435 }
436 
_mqtt_dynamic_register(iotx_http_region_types_t region,iotx_dev_meta_info_t * meta)437 int32_t _mqtt_dynamic_register(iotx_http_region_types_t region,
438                                iotx_dev_meta_info_t *meta)
439 {
440     void *pClient = NULL;
441     iotx_mqtt_param_t mqtt_params;
442     int32_t res = 0;
443     uint32_t length = 0, rand = 0;
444     char rand_str[9] = { 0 };
445     iotx_sign_mqtt_t signout;
446     uint64_t timestart = 0, timenow = 0;
447     char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = { 0 };
448 
449     memset(&signout, 0, sizeof(iotx_sign_mqtt_t));
450 
451     /* setup hostname */
452     if (IOTX_HTTP_REGION_CUSTOM == region) {
453         if (g_infra_mqtt_domain[region] == NULL) {
454             return ERROR_DEV_SIGN_CUSTOM_DOMAIN_IS_NULL;
455         }
456 
457         length = strlen(g_infra_mqtt_domain[region]) + 1;
458         if (length >= DEV_SIGN_HOSTNAME_MAXLEN) {
459             return ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT;
460         }
461 
462         memset(signout.hostname, 0, DEV_SIGN_HOSTNAME_MAXLEN);
463         memcpy(signout.hostname, g_infra_mqtt_domain[region],
464                strlen(g_infra_mqtt_domain[region]));
465     } else {
466         length =
467             strlen(meta->product_key) + strlen(g_infra_mqtt_domain[region]) + 2;
468         if (length >= DEV_SIGN_HOSTNAME_MAXLEN) {
469             return ERROR_DEV_SIGN_HOST_NAME_TOO_SHORT;
470         }
471         memset(signout.hostname, 0, DEV_SIGN_HOSTNAME_MAXLEN);
472         memcpy(signout.hostname, meta->product_key, strlen(meta->product_key));
473         memcpy(signout.hostname + strlen(signout.hostname), ".", strlen("."));
474         memcpy(signout.hostname + strlen(signout.hostname),
475                g_infra_mqtt_domain[region],
476                strlen(g_infra_mqtt_domain[region]));
477     }
478 
479     /* setup port */
480     signout.port = 443;
481 
482     /* setup username */
483     length = strlen(meta->device_name) + strlen(meta->product_key) + 2;
484     if (length >= DEV_SIGN_USERNAME_MAXLEN) {
485         return ERROR_DEV_SIGN_USERNAME_TOO_SHORT;
486     }
487     memset(signout.username, 0, DEV_SIGN_USERNAME_MAXLEN);
488     memcpy(signout.username, meta->device_name, strlen(meta->device_name));
489     memcpy(signout.username + strlen(signout.username), "&", strlen("&"));
490     memcpy(signout.username + strlen(signout.username), meta->product_key,
491            strlen(meta->product_key));
492 
493     /* password */
494     rand = HAL_Random(0xffffffff);
495     infra_hex2str((unsigned char *)&rand, 4, rand_str);
496     res = _mqtt_dynreg_sign_password(meta, &signout, rand_str);
497     if (res < 0) {
498         return res;
499     }
500 
501     /* client id */
502     res = _mqtt_dynreg_sign_clientid(meta, &signout, rand_str);
503     if (res < 0) {
504         return res;
505     }
506 
507     memset(&mqtt_params, 0, sizeof(iotx_mqtt_param_t));
508     mqtt_params.host = signout.hostname;
509     mqtt_params.port = signout.port;
510     mqtt_params.username = signout.username;
511     mqtt_params.password = signout.password;
512     mqtt_params.client_id = signout.clientid;
513     mqtt_params.request_timeout_ms = 5000;
514     mqtt_params.clean_session = 1;
515     mqtt_params.keepalive_interval_ms = 60000;
516     mqtt_params.read_buf_size = 1000;
517     mqtt_params.write_buf_size = 1000;
518 
519     pClient = wrapper_mqtt_init(&mqtt_params);
520     if (pClient == NULL) {
521         return FAIL_RETURN;
522     }
523 
524     res = wrapper_mqtt_connect(pClient);
525     if (res < SUCCESS_RETURN) {
526         wrapper_mqtt_release(&pClient);
527         return FAIL_RETURN;
528     }
529 
530     res = wrapper_mqtt_subscribe(pClient, "/ext/register", IOTX_MQTT_QOS1,
531                                  _mqtt_dynreg_topic_handle, device_secret);
532     if (res < 0) {
533         wrapper_mqtt_release(&pClient);
534         return FAIL_RETURN;
535     }
536 
537     timestart = HAL_UptimeMs();
538     while (1) {
539         timenow = HAL_UptimeMs();
540         if (timenow < timestart) {
541             timestart = timenow;
542         }
543 
544         if (timestart - timenow >= MQTT_DYNREG_TIMEOUT_MS) {
545             break;
546         }
547 
548         wrapper_mqtt_yield(pClient, 200);
549 
550         if (strlen(device_secret) > 0) {
551             break;
552         }
553     }
554 
555     if (strlen(device_secret) > 0) {
556         res = SUCCESS_RETURN;
557     } else {
558         res = FAIL_RETURN;
559     }
560 
561     wrapper_mqtt_release(&pClient);
562 
563     memcpy(meta->device_secret, device_secret, strlen(device_secret));
564 
565     return res;
566 }
567 #endif
568 
IOT_Dynamic_Register(iotx_http_region_types_t region,iotx_dev_meta_info_t * meta)569 int32_t IOT_Dynamic_Register(iotx_http_region_types_t region,
570                              iotx_dev_meta_info_t *meta)
571 {
572 #ifdef MQTT_DYNAMIC_REGISTER
573     return _mqtt_dynamic_register(region, meta);
574 #else
575     return _http_dynamic_register(region, meta);
576 #endif
577 }
578