1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include <string.h>
6 #include "uagent.h"
7 #include "uagent_inner_api.h"
8 #include "aos/kernel.h"
9 #include "aos/errno.h"
10 #include "k_config.h"
11 #include "uagent_config.h"
12 #define UAGENT_CONFIG_SUPPORT_BASE64 1
13 static int pub_info(const unsigned short len, void *str, const bool trans_guarantee);
14 
15 static char           msg_pub[UAGENT_INFO_PAYLOAD_SIZE];
16 #ifdef UAGENT_CONFIG_SUPPORT_BASE64
17 #include "mbedtls/base64.h"
18 static unsigned char  msg_pub_base64[UAGENT_INFO_PAYLOAD_BASE64_SIZE];
19 #endif
20 
21 static char          *msg_delay_pub = NULL;
22 static unsigned short msg_delay_pub_len = 0;
23 static unsigned long  out_msg_index = 0;
24 
25 static unsigned long uganet_send_id = 0;
26 
delay_send(const ua_mod_t mod,const ua_func_t func,const unsigned short len,const void * data,const ua_send_policy_t policy)27 static int delay_send(const ua_mod_t mod, const ua_func_t func,
28     const unsigned short len, const void *data, const ua_send_policy_t policy)
29 {
30     int rc = -1;
31     bool send_directly = false;
32     bool append_new = false;
33     char *out = (char*)data;
34     UAGENT_DEBUG("call %s policy 0x%x len %d, old %d\n",__func__,policy, len,msg_delay_pub_len);
35     if(NULL==msg_delay_pub){
36         msg_delay_pub = (char*)aos_malloc(UAGENT_INFO_PAYLOAD_SIZE);
37         if(NULL==msg_delay_pub){
38             UAGENT_ERR("[uA]allock memory for delay send fail\n");
39             return -ENOMEM;
40         }
41     }
42     if (POLICY_SET(policy, send_policy_delay_dump)) {
43         if (msg_delay_pub_len != 0) {
44             out = msg_delay_pub;
45             send_directly = true;
46         }
47     } else {
48         if (0 == msg_delay_pub_len) {
49 
50             if (len < UAGENT_INFO_NEAR_FULL) {
51                 memset(msg_delay_pub, 0, UAGENT_INFO_PAYLOAD_SIZE);
52                 append_new = true;
53             } else {
54                 /* send out right now */
55                 send_directly = true;
56             }
57         } else {
58             if ((len + msg_delay_pub_len) >= UAGENT_INFO_PAYLOAD_SIZE) {
59                 send_directly = true;
60                 out = msg_delay_pub;
61                 append_new = true;
62 
63             } else if ((len + msg_delay_pub_len) >= UAGENT_INFO_NEAR_FULL) {
64                 send_directly = true;
65                 out = msg_delay_pub;
66                 memcpy(&msg_delay_pub[msg_delay_pub_len], data, len);
67                 msg_delay_pub_len += len;
68             } else {
69                 append_new = true;
70             }
71         }
72     }
73 
74     if (send_directly) {
75         UAGENT_DEBUG("call %s will pop out (%d)\n",__func__,msg_delay_pub_len);
76         if (msg_delay_pub_len != 0) {
77             /* stop the alarm */
78             stop_monitor_delay_out();
79         }
80         if (uagent_get_mutex()) {
81             int msg_len = 0;
82 #ifdef UAGENT_CONFIG_SUPPORT_BASE64
83             size_t actual_len = 0;
84             memset(msg_pub_base64, 0, UAGENT_INFO_PAYLOAD_BASE64_SIZE);
85             if(0==mbedtls_base64_encode(msg_pub_base64, UAGENT_INFO_PAYLOAD_BASE64_SIZE, &actual_len,
86                 (unsigned char *)out, strlen(out)) && actual_len<=UAGENT_INFO_PAYLOAD_BASE64_SIZE){
87                 msg_len = snprintf(msg_pub, sizeof(msg_pub), UAGENT_INFO_STR, uganet_send_id++,
88                    out_msg_index++, uagent_service_attr.dn, uagent_service_attr.to_console, mod, func, msg_pub_base64);
89             } else {
90                 msg_len = snprintf(msg_pub, sizeof(msg_pub), UAGENT_INFO_STR, uganet_send_id++,
91                     out_msg_index++, uagent_service_attr.dn, uagent_service_attr.to_console, mod, func, out);
92             }
93 #else
94             msg_len = snprintf(msg_pub, sizeof(msg_pub), UAGENT_INFO_STR, uganet_send_id++,
95                 out_msg_index++, uagent_service_attr.dn, uagent_service_attr.to_console, mod, func, out);
96 #endif
97 
98             if (msg_len > 0 && msg_len < UAGENT_INFO_PAYLOAD_SIZE) {
99                 UAGENT_DEBUG("[uA]upload payload %s", msg_pub);
100                 rc = pub_info(msg_len, msg_pub, (policy&send_policy_trans_guarantee) ? 1 : 0);
101             } else {
102                 UAGENT_ERR("[uA]miss pub as payload over flow %d\n", msg_len);
103             }
104             uagent_release_mutex();
105         }
106         msg_delay_pub_len = 0;
107         memset(msg_delay_pub, 0, UAGENT_INFO_PAYLOAD_SIZE);
108     }
109     if (append_new) {
110         if (msg_delay_pub_len == 0) {
111             UAGENT_DEBUG("call %s create new alarm (%d)\n",__func__,len);
112             /* 0->1 create alarm */
113             start_monitor_delay_out();
114         }
115         UAGENT_DEBUG("call %s save len %d, old %d\n",__func__, len,msg_delay_pub_len);
116         memcpy(&msg_delay_pub[msg_delay_pub_len], data, len);
117         msg_delay_pub_len += len;
118         rc = 0;
119     }
120     return rc;
121 }
122 
uagent_send(const ua_mod_t mod,const ua_func_t func,const unsigned short len,const void * data,const ua_send_policy_t policy)123 int uagent_send(const ua_mod_t mod, const ua_func_t func,
124                 const unsigned short len, const void *data,
125                 const ua_send_policy_t policy)
126 {
127     int rc = -EINVAL;
128 
129     if(0==len || NULL !=data) {
130         rc = -1;
131 
132         if (UAGENT_INITED_FINISH) {
133             rc = -ENOMEM;
134 
135             if (len < UAGENT_INFO_PAYLOAD_SIZE) {
136 
137                 if (uagent_get_mutex()) {
138 
139                     if (POLICY_SET(policy,send_policy_delay) && !POLICY_SET(policy,send_policy_object)) {
140                         rc = delay_send(mod, func, len, data, policy);
141 
142                     }else{
143                         short msg_len = snprintf(msg_pub, sizeof(msg_pub), UAGENT_FORMAT_PRE, uganet_send_id++,
144                                                out_msg_index++, uagent_service_attr.dn, uagent_service_attr.to_console, mod, func);
145 
146                         if(msg_len>0){
147                             short empty_room_for_data = 0;
148                             if (POLICY_SET(policy,send_policy_object)) {
149                                 empty_room_for_data = UAGENT_INFO_PAYLOAD_SIZE-msg_len-strlen(UAGENT_FORMAT_OBJ_SUFFIX)-1;
150                                 strncpy(&msg_pub[msg_len], data, len<empty_room_for_data?len:empty_room_for_data);
151                                 msg_len += (len<empty_room_for_data?len:empty_room_for_data);
152                                 strncpy(&msg_pub[msg_len], UAGENT_FORMAT_OBJ_SUFFIX, UAGENT_INFO_PAYLOAD_SIZE-msg_len-1);
153                                 msg_len += strlen(UAGENT_FORMAT_OBJ_SUFFIX);
154                                 if (msg_len < UAGENT_INFO_PAYLOAD_SIZE) {
155                                     rc = pub_info(msg_len, msg_pub, POLICY_SET(policy,send_policy_trans_guarantee));
156                                 } else {
157                                     UAGENT_ERR("[uA]miss pub as payload over flow %d\n", msg_len);
158                                 }
159                             } else {
160                                 msg_pub[msg_len++] = '"';
161                                 empty_room_for_data = UAGENT_INFO_PAYLOAD_SIZE-msg_len-strlen(UAGENT_FORMAT_STR_SUFFIX)-1;
162                                 size_t actual_len = 0;
163 #ifdef UAGENT_CONFIG_SUPPORT_BASE64
164                                 memset(msg_pub_base64, 0, UAGENT_INFO_PAYLOAD_BASE64_SIZE);
165                                 if(0==mbedtls_base64_encode(msg_pub_base64, UAGENT_INFO_PAYLOAD_BASE64_SIZE, &actual_len,
166                                     data, len)){
167                                     strncpy(&msg_pub[msg_len], (char *)msg_pub_base64, empty_room_for_data);
168                                 } else {
169                                     actual_len = len;
170                                     strncpy(&msg_pub[msg_len], data, empty_room_for_data);
171                                 }
172 #else
173                                 actual_len = len;
174                                 strncpy(&msg_pub[msg_len], data, empty_room_for_data);
175 #endif
176                                 msg_len += (actual_len<empty_room_for_data?actual_len:empty_room_for_data);
177                                 strncpy(&msg_pub[msg_len], UAGENT_FORMAT_STR_SUFFIX, UAGENT_INFO_PAYLOAD_SIZE-msg_len-1);
178                                 msg_len += strlen(UAGENT_FORMAT_STR_SUFFIX);
179 
180                                 if (msg_len < UAGENT_INFO_PAYLOAD_SIZE) {
181                                     rc = pub_info(msg_len, msg_pub, POLICY_SET(policy,send_policy_trans_guarantee));
182                                 } else {
183                                     UAGENT_ERR("[uA]miss pub as payload over flow %d\n", msg_len);
184                                 }
185                             }
186                         }
187 
188 
189                     }
190 
191                     uagent_release_mutex();
192                 }
193             }
194         }else{
195             UAGENT_ERR("[uA]uagent send may fail from 0x%x 0x%x as not inited", mod, func);
196         }
197     }
198     return rc;
199 }
200 
uagent_ack(const service_agent_rlt_t rlt,const unsigned long id,const ua_mod_t mod,const ua_func_t func,const void * data)201 int uagent_ack(const service_agent_rlt_t rlt, const unsigned long id,
202                const ua_mod_t mod, const ua_func_t func, const void *data)
203 {
204     int rc = -1;
205     if (UAGENT_INITED_FINISH) {
206         int msg_len = 0;
207         char msg_pub_ack[256];
208         if (SERVICE_AGENT_OK == rlt) {
209             msg_len = snprintf(msg_pub_ack, sizeof(msg_pub_ack), UAGENT_INFO_ACK_OK,
210             uganet_send_id++, uagent_service_attr.dn, uagent_service_attr.to_console, mod, func,
211                 SERVICE_AGENT_OK, id);
212         } else {
213             msg_len = snprintf(msg_pub_ack, sizeof(msg_pub_ack), UAGENT_INFO_ACK_FAIL, uganet_send_id++,
214             uagent_service_attr.dn, uagent_service_attr.to_console, mod, func,
215                 SERVICE_AGENT_FAIL,
216                 (NULL == data) ? "unknown reason" : (char*)data, id);
217         }
218         UAGENT_DEBUG("call %s ack %d mod 0x%x func 0x%x id %ld\n", __func__,rlt, mod, func,id);
219         if (msg_len > 0 && msg_len < UAGENT_INFO_PAYLOAD_SIZE) {
220             rc = pub_info(msg_len, msg_pub_ack, 0);
221         } else {
222             UAGENT_ERR("[uA]miss pub as payload over flow %d\n", msg_len);
223         }
224     }
225     return rc;
226 }
227 
pub_info(const unsigned short len,void * str,const bool trans_guarantee)228 static int pub_info(const unsigned short len, void *str, const bool trans_guarantee)
229 {
230     int rc = -EINVAL;
231     if (len > 0 && NULL != str) {
232         rc = uagent_ext_comm_publish(len, str, trans_guarantee);
233         UAGENT_INFO("[uA]send(%d) %s rc %d\n", len, (char*)str, rc);
234     }
235     return rc;
236 }
237