1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdlib.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <aos/kernel.h>
9 //#include <aos/osal_debug.h>
10
11 #include "internal.h"
12
rpc_buffer_free(rpc_buffer_t * data)13 static void rpc_buffer_free(rpc_buffer_t *data)
14 {
15 if (data->buffer) {
16 aos_free(data->buffer);
17 data->buffer = NULL;
18 }
19
20 if (aos_sem_is_valid(&data->sem))
21 aos_sem_free(&data->sem);
22
23 aos_free(data);
24 }
25
rpc_init(rpc_t * rpc,int cmd_id,int timeout_ms)26 int rpc_init(rpc_t *rpc, int cmd_id, int timeout_ms)
27 {
28 aos_assert(rpc);
29
30 int ret = 0;
31
32 memset(rpc, 0, sizeof(rpc_t));
33 rpc->cmd_id = cmd_id;
34
35 if (timeout_ms != 0) {
36 rpc->data = aos_zalloc(sizeof(rpc_buffer_t));
37
38 if (rpc->data == NULL)
39 return -ENOMEM;
40
41 rpc->data->timeout_ms = timeout_ms;
42 ret = aos_sem_new(&rpc->data->sem, 0);
43 if (ret != 0) {
44 aos_free(rpc->data);
45 rpc->data = NULL;
46 }
47 }
48
49 return ret;
50 }
51
rpc_wait(rpc_t * rpc)52 int rpc_wait(rpc_t *rpc)
53 {
54 aos_assert(rpc);
55 int ret = 0;
56 if (rpc->data && aos_sem_is_valid(&rpc->data->sem))
57 ret = aos_sem_wait(&rpc->data->sem, rpc->data->timeout_ms);
58 return ret;
59 }
60
rpc_free(rpc_t * rpc)61 void rpc_free(rpc_t *rpc)
62 {
63 aos_assert(rpc);
64 if (rpc->data)
65 rpc_buffer_free(rpc->data);
66 }
67
rpc_deinit(rpc_t * rpc)68 void rpc_deinit(rpc_t *rpc)
69 {
70 aos_assert(rpc);
71
72 if (rpc->data == NULL)
73 return;
74
75 int cached = 0;
76 utask_t *task = rpc->srv->task;
77
78 aos_assert(task);
79
80 TASK_LOCK(task);
81
82 rpc_buffer_t *data;
83 slist_for_each_entry(&task->rpc_buffer_gc_cache, data, rpc_buffer_t, next) {
84 if (data == rpc->data) {
85 slist_del(&data->next, &task->rpc_buffer_gc_cache);
86 rpc_buffer_free(data);
87
88 cached = 1;
89 break;
90 }
91 }
92
93 if (cached == 0) {
94 slist_add_tail(&rpc->data->next, &task->rpc_buffer_gc_cache);
95 }
96
97 TASK_UNLOCK(task);
98 }
99
rpc_reply(rpc_t * rpc)100 void rpc_reply(rpc_t *rpc)
101 {
102 aos_assert(rpc);
103 aos_assert(rpc->srv);
104 aos_assert(rpc->srv->task);
105
106 if (rpc->data) {
107 if (aos_sem_is_valid(&rpc->data->sem)) {
108 aos_sem_signal(&(rpc->data->sem));
109 } else {
110 // is async call, free this data.
111 // LOGI("RPC", "async rpc cannot have return value.");
112 // rpc_buffer_free(rpc->data);
113 }
114 rpc_deinit(rpc);
115 }
116 }
117
rpc_buffer_need_size(rpc_buffer_t * rpc,int size)118 static uint8_t *rpc_buffer_need_size(rpc_buffer_t *rpc, int size)
119 {
120 void *p = NULL;
121 aos_assert(rpc);
122
123 uint8_t *buf = aos_malloc(size + rpc->buf_size);
124
125 if (buf) {
126 if (rpc->buffer) {
127 memcpy(buf, rpc->buffer, rpc->buf_size);
128 aos_free(rpc->buffer);
129 }
130
131 rpc->buffer = buf;
132 p = rpc->buffer + rpc->buf_size;
133 rpc->buf_size += size;
134 }
135
136 return p;
137 };
138
rpc_put_reset(rpc_t * rpc)139 void rpc_put_reset(rpc_t *rpc)
140 {
141 aos_assert(rpc);
142 if (rpc->data && rpc->data->buffer) {
143 aos_free(rpc->data->buffer);
144 rpc->data->buffer = NULL;
145 rpc->data->buf_size = 0;
146 rpc->data->pos = 0;
147 }
148 }
149
rpc_get_reset(rpc_t * rpc)150 void rpc_get_reset(rpc_t *rpc)
151 {
152 aos_assert(rpc);
153 if (rpc->data)
154 rpc->data->pos = 0;
155 }
156
157 #define RPC_PUT(rpc, type, v) return rpc_put_buffer(rpc, &v, sizeof(v))
158
rpc_put_int(rpc_t * rpc,int i)159 int rpc_put_int(rpc_t *rpc, int i)
160 {
161 RPC_PUT(rpc, int, i);
162 }
163
rpc_put_uint8(rpc_t * rpc,uint8_t c)164 int rpc_put_uint8(rpc_t *rpc, uint8_t c)
165 {
166 RPC_PUT(rpc, uint8_t, c);
167 }
168
rpc_put_double(rpc_t * rpc,double c)169 int rpc_put_double(rpc_t *rpc, double c)
170 {
171 RPC_PUT(rpc, double, c);
172 }
173
rpc_put_point(rpc_t * rpc,const void * p)174 int rpc_put_point(rpc_t *rpc, const void *p)
175 {
176 RPC_PUT(rpc, void *, p);
177 }
178
rpc_put_buffer(rpc_t * rpc,const void * data,size_t size)179 int rpc_put_buffer(rpc_t *rpc, const void *data, size_t size)
180 {
181 aos_assert(rpc);
182 if (data == NULL || size == 0)
183 return -EINVAL;
184
185 if (rpc->data == NULL) {
186 rpc->data = aos_zalloc(sizeof(rpc_buffer_t));
187
188 if (rpc->data == NULL)
189 return -ENOMEM;
190 }
191
192 uint8_t *p = rpc_buffer_need_size(rpc->data, size + sizeof(uint32_t));
193
194 if (p) {
195 memcpy(p, (uint8_t *)&size, sizeof(uint32_t));
196 p += sizeof(uint32_t);
197 memcpy(p, data, size);
198 }
199
200 return p ? 0 : -ENOMEM;
201 }
202
rpc_put_string(rpc_t * rpc,char * text)203 int rpc_put_string(rpc_t *rpc, char *text)
204 {
205 return rpc_put_buffer(rpc, text, strlen(text) + 1);
206 }
207
208 #define RPC_GET(rpc, type) \
209 do { \
210 int count = -1; \
211 void *p = rpc_get_buffer(rpc, &count); \
212 aos_assert(count == sizeof(type)); \
213 type v; \
214 memcpy(&v, p, sizeof(type)); \
215 return v; \
216 } while (0)
217
rpc_get_int(rpc_t * rpc)218 int rpc_get_int(rpc_t *rpc)
219 {
220 RPC_GET(rpc, int);
221 }
222
rpc_get_uint8(rpc_t * rpc)223 uint8_t rpc_get_uint8(rpc_t *rpc)
224 {
225 RPC_GET(rpc, uint8_t);
226 }
227
rpc_get_double(rpc_t * rpc)228 double rpc_get_double(rpc_t *rpc)
229 {
230 RPC_GET(rpc, double);
231 }
232
rpc_get_point(rpc_t * rpc)233 void *rpc_get_point(rpc_t *rpc)
234 {
235 RPC_GET(rpc, void *);
236 }
237
rpc_get_string(rpc_t * rpc)238 char *rpc_get_string(rpc_t *rpc)
239 {
240 return rpc_get_buffer(rpc, NULL);
241 }
242
rpc_get_buffer(rpc_t * rpc,int * count)243 void *rpc_get_buffer(rpc_t *rpc, int *count)
244 {
245 aos_assert(rpc);
246 void *p = NULL;
247
248 if (rpc->data) {
249 int len;
250
251 memcpy((uint8_t *)&len, (int *)(rpc->data->buffer + rpc->data->pos), sizeof(int));
252 p = rpc->data->buffer + rpc->data->pos + sizeof(uint32_t);
253 rpc->data->pos += sizeof(uint32_t) + len;
254
255 if (count)
256 *count = len;
257 }
258
259 return p;
260 }
261