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