1 #include "iotx_cm_internal.h"
2 
3 #if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
4 #include "iotx_cm_mqtt.h"
5 #endif
6 #ifdef COAP_COMM_ENABLED
7 #include "iotx_cm_coap.h"
8 #endif
9 
10 static void *fd_lock = NULL;
11 static iotx_cm_connection_t *_cm_fd[CM_MAX_FD_NUM] = { NULL };
12 static int _get_fd(iotx_cm_connection_t *handle);
13 static int _recycle_fd(int fd);
14 static inline int _fd_is_valid(int fd);
15 static int inited_conn_num = 0;
16 
17 #ifdef DEVICE_MODEL_GATEWAY
18 static void *_iotx_cm_yield_thread_func(void *params);
19 static void *yield_thread = NULL;
20 static int yield_task_leave = 1;
21 #endif
22 
23 const char ERR_INVALID_PARAMS[] = "invalid parameter";
24 
iotx_cm_open(iotx_cm_init_param_t * params)25 int iotx_cm_open(iotx_cm_init_param_t *params)
26 {
27     int fd;
28     iotx_cm_connection_t *connection = NULL;
29 
30     switch (params->protocol_type) {
31     case IOTX_CM_PROTOCOL_TYPE_MQTT:
32 #if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
33         connection = iotx_cm_open_mqtt(params);
34 #endif
35         break;
36     case IOTX_CM_PROTOCOL_TYPE_COAP:
37 #ifdef COAP_COMM_ENABLED
38         connection = iotx_cm_open_coap(params);
39 #endif
40         break;
41     default:
42         break;
43     }
44 
45     if (connection == NULL) {
46         cm_err("cm opon failed");
47         return -1;
48     }
49     fd = _get_fd(connection);
50     if (fd < 0) {
51         cm_err("get fd failed");
52         connection->close_func();
53         return -1;
54     }
55     connection->fd = fd;
56     return fd;
57 }
58 
iotx_cm_connect(int fd,uint32_t timeout)59 int iotx_cm_connect(int fd, uint32_t timeout)
60 {
61     iotx_cm_connect_fp connect_func;
62     int ret;
63 
64     if (_fd_is_valid(fd) < 0) {
65         cm_err(ERR_INVALID_PARAMS);
66         return -1;
67     }
68     HAL_MutexLock(fd_lock);
69     connect_func = _cm_fd[fd]->connect_func;
70     HAL_MutexUnlock(fd_lock);
71 
72     iotx_event_post(IOTX_CONN_CLOUD);
73 
74     ret = connect_func(timeout);
75 
76     if (ret == 0) {
77         inited_conn_num++;
78         if (inited_conn_num == 1) {
79 #ifdef DEVICE_MODEL_GATEWAY
80             int stack_used;
81             hal_os_thread_param_t task_parms = { 0 };
82             task_parms.stack_size = 6144;
83             task_parms.name = "cm_yield";
84             ret = HAL_ThreadCreate(&yield_thread, _iotx_cm_yield_thread_func,
85                                    NULL, &task_parms, &stack_used);
86             if (ret < 0) {
87                 inited_conn_num--;
88             }
89 #endif
90         }
91         iotx_event_post(IOTX_CONN_CLOUD_SUC);
92     } else {
93         iotx_event_post(IOTX_CONN_CLOUD_FAIL);
94     }
95 
96     return ret;
97 }
98 
_iotx_cm_yield(int fd,unsigned int timeout)99 static int _iotx_cm_yield(int fd, unsigned int timeout)
100 {
101     iotx_cm_yield_fp yield_func;
102 
103     if (fd_lock == NULL) {
104         return NULL_VALUE_ERROR;
105     }
106 
107     if (fd == -1) {
108         int i;
109         for (i = 0; i < CM_MAX_FD_NUM; i++) {
110             yield_func = NULL;
111             HAL_MutexLock(fd_lock);
112             if (_cm_fd[i] != NULL) {
113                 yield_func = _cm_fd[i]->yield_func;
114             }
115             HAL_MutexUnlock(fd_lock);
116             if (yield_func != NULL) {
117                 yield_func(timeout);
118             }
119         }
120         return 0;
121     }
122 
123     if (_fd_is_valid(fd) < 0) {
124         cm_err(ERR_INVALID_PARAMS);
125         return -1;
126     }
127 
128     HAL_MutexLock(fd_lock);
129     yield_func = _cm_fd[fd]->yield_func;
130     HAL_MutexUnlock(fd_lock);
131     return yield_func(timeout);
132 }
133 #ifdef DEVICE_MODEL_GATEWAY
_iotx_cm_yield_thread_func(void * params)134 static void *_iotx_cm_yield_thread_func(void *params)
135 {
136     yield_task_leave = 0;
137     while (inited_conn_num > 0) {
138         _iotx_cm_yield(-1, CM_DEFAULT_YIELD_TIMEOUT);
139     }
140     yield_task_leave = 1;
141     return NULL;
142 }
143 #endif
144 
iotx_cm_yield(int fd,unsigned int timeout)145 int iotx_cm_yield(int fd, unsigned int timeout)
146 {
147 #ifdef DEVICE_MODEL_GATEWAY
148     return 0;
149 #else
150     return _iotx_cm_yield(fd, timeout);
151 #endif
152 }
153 
iotx_cm_sub(int fd,iotx_cm_ext_params_t * ext,const char * topic,iotx_cm_data_handle_cb topic_handle_func,void * pcontext)154 int iotx_cm_sub(int fd, iotx_cm_ext_params_t *ext, const char *topic,
155                 iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
156 {
157     iotx_cm_sub_fp sub_func;
158 
159     if (_fd_is_valid(fd) < 0) {
160         cm_err(ERR_INVALID_PARAMS);
161         return -1;
162     }
163 
164     HAL_MutexLock(fd_lock);
165     sub_func = _cm_fd[fd]->sub_func;
166     HAL_MutexUnlock(fd_lock);
167     return sub_func(ext, topic, topic_handle_func, pcontext);
168 }
169 
iotx_cm_unsub(int fd,const char * topic)170 int iotx_cm_unsub(int fd, const char *topic)
171 {
172     iotx_cm_unsub_fp unsub_func;
173 
174     if (_fd_is_valid(fd) < 0) {
175         cm_err(ERR_INVALID_PARAMS);
176         return -1;
177     }
178 
179     HAL_MutexLock(fd_lock);
180     unsub_func = _cm_fd[fd]->unsub_func;
181     HAL_MutexUnlock(fd_lock);
182     return unsub_func(topic);
183 }
184 
iotx_cm_pub(int fd,iotx_cm_ext_params_t * ext,const char * topic,const char * payload,unsigned int payload_len)185 int iotx_cm_pub(int fd, iotx_cm_ext_params_t *ext, const char *topic,
186                 const char *payload, unsigned int payload_len)
187 {
188     iotx_cm_pub_fp pub_func;
189 
190     if (_fd_is_valid(fd) < 0) {
191         cm_err(ERR_INVALID_PARAMS);
192         return -1;
193     }
194 
195     HAL_MutexLock(fd_lock);
196     pub_func = _cm_fd[fd]->pub_func;
197     HAL_MutexUnlock(fd_lock);
198     return pub_func(ext, topic, payload, payload_len);
199 }
200 
iotx_cm_close(int fd)201 int iotx_cm_close(int fd)
202 {
203     iotx_cm_close_fp close_func;
204 
205     if (_fd_is_valid(fd) < 0) {
206         cm_err(ERR_INVALID_PARAMS);
207         return -1;
208     }
209 
210     if (inited_conn_num > 0) {
211         inited_conn_num--;
212     }
213 
214     if (inited_conn_num == 0) {
215 #ifdef DEVICE_MODEL_GATEWAY
216         while (!yield_task_leave) {
217             HAL_SleepMs(10);
218         }
219         yield_thread = NULL;
220 #endif
221     }
222 
223     HAL_MutexLock(fd_lock);
224     close_func = _cm_fd[fd]->close_func;
225     HAL_MutexUnlock(fd_lock);
226     if (close_func() != 0) {
227         return -1;
228     }
229     if (_recycle_fd(fd) != 0) {
230         return -1;
231     }
232 
233     if (inited_conn_num == 0) {
234         if (fd_lock != NULL) {
235             HAL_MutexDestroy(fd_lock);
236             fd_lock = NULL;
237         }
238     }
239 
240     return 0;
241 }
242 
_fd_is_valid(int fd)243 static inline int _fd_is_valid(int fd)
244 {
245     int ret;
246 
247     if (fd_lock == NULL) {
248         return NULL_VALUE_ERROR;
249     }
250 
251     HAL_MutexLock(fd_lock);
252     ret = (fd >= 0 && fd < CM_MAX_FD_NUM && _cm_fd[fd] != NULL) ? 0 : -1;
253     HAL_MutexUnlock(fd_lock);
254     return ret;
255 }
256 
_recycle_fd(int fd)257 static int _recycle_fd(int fd)
258 {
259     if (fd_lock == NULL) {
260         fd_lock = HAL_MutexCreate();
261         if (fd_lock == NULL) {
262             return -1;
263         }
264     }
265 
266     if (fd < 0 || fd > CM_MAX_FD_NUM - 1) {
267         return -1;
268     }
269 
270     HAL_MutexLock(fd_lock);
271     _cm_fd[fd] = NULL;
272     HAL_MutexUnlock(fd_lock);
273 
274     return 0;
275 }
276 
_get_fd(iotx_cm_connection_t * handle)277 static int _get_fd(iotx_cm_connection_t *handle)
278 {
279     int i;
280     if (handle == NULL) {
281         return NULL_VALUE_ERROR;
282     }
283 
284     if (fd_lock == NULL) {
285         fd_lock = HAL_MutexCreate();
286         if (fd_lock == NULL) {
287             return -1;
288         }
289     }
290 
291     HAL_MutexLock(fd_lock);
292     for (i = 0; i < CM_MAX_FD_NUM; i++) {
293         if (_cm_fd[i] == NULL) {
294             _cm_fd[i] = handle;
295             HAL_MutexUnlock(fd_lock);
296             return i;
297         }
298     }
299     HAL_MutexUnlock(fd_lock);
300     cm_err("cm fd reached the limit");
301     return -1;
302 }
303