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