1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "dev_bind_internal.h"
5
6 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
7 extern "C" {
8 #endif
9
10 #define AWSS_REPORT_LEN_MAX (256)
11 #define AWSS_TOKEN_TIMEOUT_MS (120 * 1000)
12 #define MATCH_MONITOR_TIMEOUT_MS (10 * 1000)
13 #define MATCH_REPORT_CNT_MAX (2)
14
15 volatile char awss_report_token_suc = 0; // avoid be optimized by the compiler
16 volatile char awss_report_token_cnt = 0; // avoid be optimized by the compiler
17 static char awss_report_id = 0;
18 #ifdef WIFI_PROVISION_ENABLED
19 static uint8_t switchap_bssid[ETH_ALEN] = { 0 };
20 static char switchap_ssid[OS_MAX_SSID_LEN] = { 0 };
21 static char switchap_passwd[OS_MAX_PASSWD_LEN] = { 0 };
22 static void *switchap_timer = NULL;
23 #endif
24
25 static uint32_t awss_report_token_time = 0;
26 static void *report_token_timer = NULL;
27
28 static int awss_report_token_to_cloud();
29 #ifdef WIFI_PROVISION_ENABLED
30 static int awss_switch_ap_online();
31 static int awss_reboot_system();
32 #endif
33
awss_token_remain_time()34 int awss_token_remain_time()
35 {
36 int remain = 0;
37 uint32_t cur = os_get_time_ms();
38 uint32_t diff = (uint32_t)(cur - awss_report_token_time);
39
40 if (awss_report_token_suc == 0) {
41 return remain;
42 }
43
44 if (diff < AWSS_TOKEN_TIMEOUT_MS) {
45 remain = AWSS_TOKEN_TIMEOUT_MS - diff;
46 }
47
48 return remain;
49 }
50
awss_update_token()51 int awss_update_token()
52 {
53 awss_report_token_time = 0;
54 awss_report_token_cnt = 0;
55 awss_report_token_suc = 0;
56
57 produce_random(aes_random, sizeof(aes_random));
58 if (report_token_timer == NULL) {
59 report_token_timer = HAL_Timer_Create(
60 "rp_token", (void (*)(void *))awss_report_token_to_cloud, NULL);
61 }
62 HAL_Timer_Stop(report_token_timer);
63 HAL_Timer_Start(report_token_timer, 10);
64 awss_info("update token");
65
66 return 0;
67 }
68
awss_token_timeout()69 int awss_token_timeout()
70 {
71 uint32_t cur;
72 if (awss_report_token_time == 0) {
73 return 1;
74 }
75
76 cur = os_get_time_ms();
77 if ((uint32_t)(cur - awss_report_token_time) > AWSS_TOKEN_TIMEOUT_MS) {
78 return 1;
79 }
80 return 0;
81 }
82
awss_report_token_reply(void * pcontext,void * pclient,void * msg)83 void awss_report_token_reply(void *pcontext, void *pclient, void *msg)
84 {
85 int ret, len;
86 char *payload;
87 char *id = NULL;
88 char reply_id = 0;
89 uint32_t payload_len;
90
91 ret = awss_cmp_mqtt_get_payload(msg, &payload, &payload_len);
92
93 if (ret != 0 || payload == NULL || payload_len == 0) {
94 return;
95 }
96
97 id = json_get_value_by_name(payload, payload_len, AWSS_JSON_ID, &len, NULL);
98 if (id == NULL) {
99 return;
100 }
101
102 reply_id = atoi(id);
103 if (reply_id + 1 < awss_report_id) {
104 return;
105 }
106 awss_info("%s\r\n", __func__);
107 awss_report_token_suc = 1;
108 awss_stop_timer(report_token_timer);
109 report_token_timer = NULL;
110 AWSS_DB_UPDATE_STATIS(AWSS_DB_STATIS_SUC);
111 AWSS_DB_DISP_STATIS();
112 return;
113 }
114
115 #ifdef WIFI_PROVISION_ENABLED
awss_online_switchap(void * pcontext,void * pclient,void * msg)116 void awss_online_switchap(void *pcontext, void *pclient, void *msg)
117 {
118 #define SWITCHAP_RSP_LEN (64)
119 #define AWSS_BSSID_STR_LEN (17)
120 #define AWSS_SSID "ssid"
121 #define AWSS_PASSWD "passwd"
122 #define AWSS_BSSID "bssid"
123 #define AWSS_SWITCH_MODE "switchMode"
124 #define AWSS_TIMEOUT "timeout"
125
126 int len = 0, timeout = 0;
127 char *packet = NULL, *awss_info = NULL, *elem = NULL;
128 int packet_len = SWITCHAP_RSP_LEN, awss_info_len = 0;
129
130 uint32_t payload_len;
131 char *payload;
132 int ret;
133
134 ret = awss_cmp_mqtt_get_payload(msg, &payload, &payload_len);
135
136 if (ret != 0) {
137 goto ONLINE_SWITCHAP_FAIL;
138 }
139
140 if (payload == NULL || payload_len == 0) {
141 goto ONLINE_SWITCHAP_FAIL;
142 }
143
144 awss_debug("online switchap len:%u, payload:%s\r\n", payload_len, payload);
145 packet = awss_zalloc(packet_len + 1);
146 if (packet == NULL) {
147 goto ONLINE_SWITCHAP_FAIL;
148 }
149
150 awss_info = json_get_value_by_name(payload, payload_len, AWSS_JSON_PARAM,
151 &awss_info_len, NULL);
152 if (awss_info == NULL || awss_info_len == 0) {
153 goto ONLINE_SWITCHAP_FAIL;
154 }
155
156 /*
157 * get SSID , PASSWD, BSSID of router
158 */
159 elem =
160 json_get_value_by_name(awss_info, awss_info_len, AWSS_SSID, &len, NULL);
161 if (elem == NULL || len <= 0 || len >= OS_MAX_SSID_LEN) {
162 goto ONLINE_SWITCHAP_FAIL;
163 }
164
165 memset(switchap_ssid, 0, sizeof(switchap_ssid));
166 memcpy(switchap_ssid, elem, len);
167
168 len = 0;
169 elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_PASSWD, &len,
170 NULL);
171 if (elem == NULL || len <= 0 || len >= OS_MAX_PASSWD_LEN) {
172 goto ONLINE_SWITCHAP_FAIL;
173 }
174
175 memset(switchap_passwd, 0, sizeof(switchap_passwd));
176 memcpy(switchap_passwd, elem, len);
177
178 len = 0;
179 memset(switchap_bssid, 0, sizeof(switchap_bssid));
180 elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_BSSID, &len,
181 NULL);
182
183 if (elem != NULL && len == AWSS_BSSID_STR_LEN) {
184 uint8_t i = 0;
185 char *bssid_str = elem;
186 /* convert bssid string to bssid value */
187 while (i < OS_ETH_ALEN) {
188 switchap_bssid[i++] = (uint8_t)strtol(bssid_str, &bssid_str, 16);
189 ++bssid_str;
190 /*
191 * fix the format of bssid string is not legal.
192 */
193 if ((uint32_t)((unsigned long)bssid_str - (unsigned long)elem) >
194 AWSS_BSSID_STR_LEN) {
195 memset(switchap_bssid, 0, sizeof(switchap_bssid));
196 break;
197 }
198 }
199 }
200
201 len = 0;
202 elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_SWITCH_MODE,
203 &len, NULL);
204 if (elem != NULL && (elem[0] == '0' || elem[0] == 0)) {
205 elem = json_get_value_by_name(awss_info, awss_info_len, AWSS_TIMEOUT,
206 &len, NULL);
207 if (elem) {
208 timeout = (int)strtol(elem, &elem, 16);
209 }
210 }
211
212 do {
213 /* reduce stack used */
214 char *id = NULL;
215 char id_str[MSG_REQ_ID_LEN] = { 0 };
216 id = json_get_value_by_name(payload, payload_len, AWSS_JSON_ID, &len,
217 NULL);
218 memcpy(id_str, id, len > MSG_REQ_ID_LEN - 1 ? MSG_REQ_ID_LEN - 1 : len);
219 awss_build_packet(AWSS_CMP_PKT_TYPE_RSP, id_str, ILOP_VER,
220 METHOD_EVENT_ZC_SWITCHAP, "{}", 200, packet,
221 &packet_len);
222 } while (0);
223
224 do {
225 char reply[TOPIC_LEN_MAX] = { 0 };
226 awss_build_topic(TOPIC_SWITCHAP_REPLY, reply, TOPIC_LEN_MAX);
227 awss_cmp_mqtt_send(reply, packet, packet_len, 1);
228 HAL_Free(packet);
229 } while (0);
230
231 /*
232 * make sure the response would been received
233 */
234 if (timeout < 1000) {
235 timeout = 1000;
236 }
237
238 do {
239 uint8_t bssid[ETH_ALEN] = { 0 };
240 char ssid[OS_MAX_SSID_LEN + 1] = { 0 },
241 passwd[OS_MAX_PASSWD_LEN + 1] = { 0 };
242 HAL_Wifi_Get_Ap_Info(ssid, passwd, bssid);
243 /*
244 * switch ap when destination ap is differenct from current ap
245 */
246 if (strncmp(ssid, switchap_ssid, sizeof(ssid)) ||
247 memcmp(bssid, switchap_bssid, sizeof(bssid)) ||
248 strncmp(passwd, switchap_passwd, sizeof(passwd))) {
249 if (switchap_timer == NULL) {
250 switchap_timer = HAL_Timer_Create(
251 "swichap_online", (void (*)(void *))awss_switch_ap_online,
252 NULL);
253 }
254
255 HAL_Timer_Stop(switchap_timer);
256 HAL_Timer_Start(switchap_timer, timeout);
257 }
258 } while (0);
259
260 return;
261
262 ONLINE_SWITCHAP_FAIL:
263 awss_warn("ilop online switchap failed");
264 memset(switchap_ssid, 0, sizeof(switchap_ssid));
265 memset(switchap_bssid, 0, sizeof(switchap_bssid));
266 memset(switchap_passwd, 0, sizeof(switchap_passwd));
267 if (packet) {
268 HAL_Free(packet);
269 }
270 return;
271 }
272
273 static void *reboot_timer = NULL;
awss_switch_ap_online()274 static int awss_switch_ap_online()
275 {
276 HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT_MS, switchap_ssid,
277 switchap_passwd, AWSS_AUTH_TYPE_INVALID,
278 AWSS_ENC_TYPE_INVALID, switchap_bssid, 0);
279
280 awss_stop_timer(switchap_timer);
281 switchap_timer = NULL;
282
283 memset(switchap_ssid, 0, sizeof(switchap_ssid));
284 memset(switchap_bssid, 0, sizeof(switchap_bssid));
285 memset(switchap_passwd, 0, sizeof(switchap_passwd));
286
287 reboot_timer = HAL_Timer_Create("rb_timer",
288 (void (*)(void *))awss_reboot_system, NULL);
289 HAL_Timer_Start(reboot_timer, 1000);
290 ;
291
292 return 0;
293 }
294
awss_reboot_system()295 static int awss_reboot_system()
296 {
297 awss_stop_timer(reboot_timer);
298 reboot_timer = NULL;
299 HAL_Reboot();
300 return 0;
301 }
302 #endif
303
awss_report_token_to_cloud()304 static int awss_report_token_to_cloud()
305 {
306 int packet_len, ret;
307 char *packet;
308 char topic[TOPIC_LEN_MAX] = { 0 };
309 #define REPORT_TOKEN_PARAM_LEN (64)
310 if (awss_report_token_suc) { /* success ,no need to report */
311 return 0;
312 }
313
314 AWSS_DB_UPDATE_STATIS(AWSS_DB_STATIS_START);
315
316 /*
317 * it is still failed after try to report token MATCH_REPORT_CNT_MAX times
318 */
319 if (awss_report_token_cnt++ > MATCH_REPORT_CNT_MAX) {
320 awss_stop_timer(report_token_timer);
321 report_token_timer = NULL;
322 awss_info("try %d times fail", awss_report_token_cnt);
323 return -2;
324 }
325
326 if (report_token_timer == NULL) {
327 report_token_timer = HAL_Timer_Create(
328 "rp_token", (void (*)(void *))awss_report_token_to_cloud, NULL);
329 }
330 HAL_Timer_Stop(report_token_timer);
331 HAL_Timer_Start(report_token_timer, 3 * 1000);
332
333 packet_len = AWSS_REPORT_LEN_MAX;
334
335 packet = awss_zalloc(packet_len + 1);
336 if (packet == NULL) {
337 awss_err("alloc mem(%d) failed", packet_len);
338 return -1;
339 }
340
341 do {
342 /* reduce stack used */
343 uint8_t i;
344 char id_str[MSG_REQ_ID_LEN] = { 0 };
345 char param[REPORT_TOKEN_PARAM_LEN] = { 0 };
346 char token_str[(RANDOM_MAX_LEN << 1) + 1] = { 0 };
347
348 for (i = 0; i < sizeof(aes_random);
349 i++) /* check aes_random is initialed or not */
350 if (aes_random[i] != 0x00) {
351 break;
352 }
353
354 if (i >= sizeof(aes_random)) { /* aes_random needs to be initialed */
355 produce_random(aes_random, sizeof(aes_random));
356 }
357
358 awss_report_token_time = os_get_time_ms();
359
360 HAL_Snprintf(id_str, MSG_REQ_ID_LEN - 1, "\"%u\"", awss_report_id++);
361 utils_hex_to_str(aes_random, RANDOM_MAX_LEN, token_str,
362 sizeof(token_str) - 1);
363 HAL_Snprintf(param, REPORT_TOKEN_PARAM_LEN - 1, "{\"token\":\"%s\"}",
364 token_str);
365 awss_build_packet(AWSS_CMP_PKT_TYPE_REQ, id_str, ILOP_VER,
366 METHOD_MATCH_REPORT, param, 0, packet, &packet_len);
367 } while (0);
368
369 awss_debug("report token:%s\r\n", packet);
370 awss_build_topic(TOPIC_MATCH_REPORT, topic, TOPIC_LEN_MAX);
371
372 ret = awss_cmp_mqtt_send(topic, packet, packet_len, 1);
373 awss_info("report token res:%d\r\n", ret);
374 HAL_Free(packet);
375
376 return ret;
377 }
378
awss_report_token()379 int awss_report_token()
380 {
381 awss_report_token_cnt = 0;
382 awss_report_token_suc = 0;
383
384 return awss_report_token_to_cloud();
385 }
386
awss_stop_report_token()387 int awss_stop_report_token()
388 {
389 if (report_token_timer) {
390 awss_stop_timer(report_token_timer);
391 report_token_timer = NULL;
392 }
393
394 memset(aes_random, 0x00, sizeof(aes_random));
395
396 return 0;
397 }
398
399 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
400 }
401 #endif
402