1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include "amp_platform.h"
6 #include "aos_system.h"
7 #include "amp_defines.h"
8 #include "aiot_state_api.h"
9 #include "aiot_sysdep_api.h"
10 #include "aiot_dynreg_api.h"
11 #include "aiot_mqtt_api.h"
12 #include "module_aiot.h"
13 #include "be_inl.h"
14 
15 #define MOD_STR "AIOT_DYNREG"
16 
17 /* 位于portfiles/aiot_port文件夹下的系统适配函数集合 */
18 extern aiot_sysdep_portfile_t g_aiot_sysdep_portfile;
19 
20 /* 位于external/ali_ca_cert.c中的服务器证书 */
21 extern const char *ali_ca_cert;
22 
aiot_app_dynreg_recv_handler(void * handle,const aiot_dynreg_recv_t * packet,void * userdata)23 void aiot_app_dynreg_recv_handler(void *handle, const aiot_dynreg_recv_t *packet, void *userdata)
24 {
25     int js_cb_ref = 0;
26 
27     if (packet->type == AIOT_DYNREGRECV_STATUS_CODE)
28     {
29         amp_debug(MOD_STR, "dynreg rsp code = %d", packet->data.status_code.code);
30     }
31     else if (packet->type == AIOT_DYNREGRECV_DEVICE_INFO)
32     {
33         amp_debug(MOD_STR, "dynreg DS = %s", packet->data.device_info.device_secret);
34         aos_kv_set(AMP_CUSTOMER_DEVICESECRET, packet->data.device_info.device_secret, strlen(packet->data.device_info.device_secret), 1);
35         int js_cb_ref = (int *)userdata;
36         duk_context *ctx = be_get_context();
37         be_push_ref(ctx, js_cb_ref);
38         duk_push_string(ctx, packet->data.device_info.device_secret);
39         if (duk_pcall(ctx, 1) != DUK_EXEC_SUCCESS) {
40             amp_console("%s", duk_safe_to_stacktrace(ctx, -1));
41         }
42         be_unref(ctx, js_cb_ref);
43         duk_pop(ctx);
44         duk_gc(ctx, 0);
45     }
46 }
47 
aiot_dynreg_http(int js_cb_ref)48 int32_t aiot_dynreg_http(int js_cb_ref)
49 {
50     int32_t res = STATE_SUCCESS;
51     char *auth_url = "iot-auth.cn-shanghai.aliyuncs.com";    /* 阿里云平台上海站点的域名后缀 */
52     char host[100] = {0};                                    /* 用这个数组拼接设备连接的云平台站点全地址, 规则是 ${productKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com */
53     uint16_t port = 443;                                     /* 无论设备是否使用TLS连接阿里云平台, 目的端口都是443 */
54     aiot_sysdep_network_cred_t cred;                         /* 安全凭据结构体, 如果要用TLS, 这个结构体中配置CA证书等参数 */
55 
56     /* get device tripple info */
57     char product_key[IOTX_PRODUCT_KEY_LEN] = {0};
58     char product_secret[IOTX_PRODUCT_SECRET_LEN] = {0};
59     char device_name[IOTX_DEVICE_NAME_LEN] = {0};
60     char device_secret[IOTX_DEVICE_SECRET_LEN] = {0};
61 
62     int productkey_len = IOTX_PRODUCT_KEY_LEN;
63     int productsecret_len = IOTX_PRODUCT_SECRET_LEN;
64     int devicename_len = IOTX_DEVICE_NAME_LEN;
65     int devicesecret_len = IOTX_DEVICE_SECRET_LEN;
66 
67     aos_kv_get(AMP_CUSTOMER_PRODUCTKEY, product_key, &productkey_len);
68     aos_kv_get(AMP_CUSTOMER_PRODUCTSECRET, product_secret, &productsecret_len);
69     aos_kv_get(AMP_CUSTOMER_DEVICENAME, device_name, &devicename_len);
70     amp_debug(MOD_STR, "dev info pk: %s, ps: %s, dn: %s", product_key, product_secret, device_name);
71     /* end get device tripple info */
72 
73     /* 配置SDK的底层依赖 */
74     aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
75     /* 配置SDK的日志输出 */
76     // aiot_state_set_logcb(demo_state_logcb);
77 
78     /* 创建SDK的安全凭据, 用于建立TLS连接 */
79     memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t));
80     cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA; /* 使用RSA证书校验MQTT服务端 */
81     cred.max_tls_fragment = 16384;                     /* 最大的分片长度为16K, 其它可选值还有4K, 2K, 1K, 0.5K */
82     cred.sni_enabled = 1;                              /* TLS建连时, 支持Server Name Indicator */
83     cred.x509_server_cert = ali_ca_cert;               /* 用来验证MQTT服务端的RSA根证书 */
84     cred.x509_server_cert_len = strlen(ali_ca_cert);   /* 用来验证MQTT服务端的RSA根证书长度 */
85 
86     aos_kv_get(AMP_CUSTOMER_DEVICESECRET, device_secret, &devicesecret_len);
87     if (device_secret[0] == '\0' || device_secret[IOTX_DEVICE_SECRET_LEN] != '\0')
88     {
89 
90         if (product_secret[0] == '\0' || product_secret[IOTX_PRODUCT_SECRET_LEN] != '\0')
91         {
92             amp_error(MOD_STR, "need dynamic register, product secret is null");
93             return -1;
94         }
95 
96         void *dynreg_handle = NULL;
97 
98         dynreg_handle = aiot_dynreg_init();
99         if (dynreg_handle == NULL)
100         {
101             amp_error(MOD_STR, "dynreg handle is null");
102             aos_task_exit(0);
103             return NULL;
104         }
105 
106         /* 配置网络连接的安全凭据, 上面已经创建好了 */
107         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_NETWORK_CRED, (void *)&cred);
108         /* 配置MQTT服务器地址 */
109         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_HOST, (void *)auth_url);
110         /* 配置MQTT服务器端口 */
111         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PORT, (void *)&port);
112         /* 配置设备productKey */
113         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PRODUCT_KEY, (void *)product_key);
114         /* 配置设备productSecret */
115         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PRODUCT_SECRET, (void *)product_secret);
116         /* 配置设备deviceName */
117         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_DEVICE_NAME, (void *)device_name);
118         /* 配置DYNREG默认消息接收回调函数 */
119         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_RECV_HANDLER, (void *)aiot_app_dynreg_recv_handler);
120         /* 配置DYNREG默认消息接收回调函数参数 */
121         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_USERDATA, js_cb_ref);
122 
123         res = aiot_dynreg_send_request(dynreg_handle);
124         if (res < STATE_SUCCESS)
125         {
126             amp_error(MOD_STR, "dynamic register send  fail res = %d\n\r", res);
127             aiot_dynreg_deinit(&dynreg_handle);
128             return -1;
129         }
130 
131         res = aiot_dynreg_recv(dynreg_handle);
132         if (res < STATE_SUCCESS)
133         {
134             amp_error(MOD_STR, "dynamic register recv fail res = %d\n\r", res);
135             aiot_dynreg_deinit(&dynreg_handle);
136             return -1;
137         }
138 
139         aos_kv_get(AMP_CUSTOMER_DEVICESECRET, device_secret, &devicesecret_len);
140 
141         res = aiot_dynreg_deinit(&dynreg_handle);
142         if (res < STATE_SUCCESS)
143         {
144             amp_error(MOD_STR, "dynamic register deinit fail res = %d\n\r", res);
145             return -1;
146         }
147     } else {
148         amp_debug(MOD_STR, "device is already activated");
149         return -1;
150     }
151 
152     return STATE_SUCCESS;
153 }
154