Allow to set event loop type with api
[platform/core/api/vine.git] / src / vine-data-path.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <dlfcn.h>
18 #include <stdbool.h>
19 #include <unistd.h>
20
21 #include "vine-event-loop.h"
22 #include "vine-data-path.h"
23 #include "vine-data-path-plugin.h"
24 #include "vine-security.h"
25 #include "vine-log.h"
26 #include "vine-utils.h"
27
28 typedef struct {
29         vine_address_family_e addr_family;
30         char *addr;
31         int port;
32         vine_security_h security;
33
34         vine_data_path_opened_cb opened_cb;
35         void *opened_cb_data;
36         vine_data_path_accepted_cb accepted_cb;
37         void *accepted_cb_data;
38         vine_data_path_connected_cb connected_cb;
39         void *connected_cb_data;
40         vine_data_path_received_cb recv_cb;
41         void *recv_cb_data;
42         vine_data_path_terminated_cb terminated_cb;
43         void *terminated_cb_data;
44
45         vine_dp_plugin_h plugin_handle;
46         vine_event_queue_h event_queue;
47
48         VineDataPathState *state;
49         established_notifier established;
50
51         vine_data_path_h listen_dp;     // only for client dp in the server side
52 } vine_data_path_s;
53
54 typedef struct {
55         int result;
56         int port;
57 } vine_dp_opened_event;
58
59 typedef struct {
60         int result;
61 } vine_dp_connected_event;
62
63 typedef struct {
64         size_t bytes;
65 } vine_dp_received_event;
66
67 typedef struct {
68         vine_data_path_s *connected_dp;
69 } vine_dp_accepted_event;
70
71 vine_dp_plugin_fn g_dp_plugin_fn = {
72         .init = NULL,
73         .deinit = NULL,
74         .register_callbacks = NULL,
75         .process_event = NULL,
76         .create = NULL,
77         .destroy = NULL,
78         .open = NULL,
79         .connect = NULL,
80         .read = NULL,
81         .write = NULL
82 };
83
84 static vine_dp_plugin_callbacks g_dp_plugin_cbs = {
85         .pollfd_cb = NULL,
86         .opened_cb = NULL,
87         .accepted_cb = NULL,
88         .connected_cb = NULL,
89         .received_cb = NULL,
90         .written_cb = NULL,
91         .terminated_cb = NULL,
92 };
93
94 static void (*__init_plugin)(vine_dp_plugin_fn *fn);
95 static vine_data_path_s *_vine_data_path_create(vine_address_family_e addr_family,
96                 const char *addr, int port, vine_security_h security,
97                 void *plugin_data, vine_event_queue_h event_queue);
98
99 static vine_error_e __convert_data_path_error_to_vine_error(vine_data_path_error error)
100 {
101         switch (error) {
102         case VINE_DATA_PATH_ERROR_NONE:
103                 return VINE_ERROR_NONE;
104         case VINE_DATA_PATH_ERROR_INVALID_PARAMETER:
105                 return VINE_ERROR_INVALID_PARAMETER;
106         case VINE_DATA_PATH_ERROR_INVALID_OPERATION:
107                 return VINE_ERROR_INVALID_OPERATION;
108         case VINE_DATA_PATH_ERROR_OPERATION_FAILED:
109                 return VINE_ERROR_OPERATION_FAILED;
110         case VINE_DATA_PATH_ERROR_OUT_OF_MEMORY:
111                 return VINE_ERROR_OUT_OF_MEMORY;
112         default:
113                 return VINE_ERROR_OPERATION_FAILED;
114         }
115 }
116
117 static vine_error_e __convert_address_family(vine_address_family_e addr_family,
118                 vine_dp_addr_family_e *dp_addr_family)
119 {
120         switch (addr_family) {
121         case VINE_ADDRESS_FAMILY_DEFAULT:
122                 *dp_addr_family = VINE_DP_IPV4_IPV6;
123                 break;
124         case VINE_ADDRESS_FAMILY_IPV4:
125                 *dp_addr_family = VINE_DP_IPV4;
126                 break;
127         case VINE_ADDRESS_FAMILY_IPV6:
128                 *dp_addr_family = VINE_DP_IPV6;
129                 break;
130         default:
131                 return VINE_ERROR_INVALID_PARAMETER;
132         }
133
134         return VINE_ERROR_NONE;
135 }
136
137 void __vine_dp_poll_handler(int fd, int events, void *user_data)
138 {
139         g_dp_plugin_fn.process_event(fd, events);
140 }
141
142 void __vine_dp_op_handler(int fd, int events, void *user_data)
143 {
144         uint64_t v;
145
146         vine_event_loop_del_io_handler(fd);
147         if (read(fd, &v, sizeof(v)) == -1) {
148                 VINE_LOGE("Read error(%d)", errno);
149                 return;
150         }
151         g_dp_plugin_fn.process_event(fd, events);
152 }
153
154 static void __pollfd_cb(vine_data_path_pollfd_op_e op, int fd, int events)
155 {
156         switch (op) {
157         case VINE_DATA_PATH_POLLFD_ADD:
158                 vine_event_loop_add_io_handler(fd, events, __vine_dp_poll_handler, NULL);
159                 break;
160         case VINE_DATA_PATH_POLLFD_DEL:
161                 vine_event_loop_del_io_handler(fd);
162                 break;
163         case VINE_DATA_PATH_POLLFD_MOD:
164                 vine_event_loop_mod_io_handler(fd, events, __vine_dp_poll_handler, NULL);
165                 break;
166         case VINE_DATA_PATH_POLLFD_OP:
167                 vine_event_loop_add_io_handler(fd, events, __vine_dp_op_handler, NULL);
168                 break;
169         case VINE_DATA_PATH_POLLFD_LOCK_UNLOCK:
170                 // Do not anything.
171                 break;
172         default:
173                 VINE_LOGE("invalid operation.");
174                 break;
175         }
176 }
177
178 static void __free_accepted_event(void *data)
179 {
180         if (!data)
181                 return;
182
183         vine_dp_accepted_event *event = (vine_dp_accepted_event *)data;
184         // CHECK: connected_dp should not be freed
185         free(event);
186 }
187
188 static void __invoke_accepted_user_cb(void *event, void *user_data)
189 {
190         RET_IF(event == NULL, "event is NULL");
191
192         vine_dp_accepted_event *accepted_event = (vine_dp_accepted_event *)event;
193         vine_data_path_s *listen_dp = (vine_data_path_s *)user_data;
194
195         VINE_LOGD("user callback is invoked by event queue.");
196
197         if (listen_dp && listen_dp->accepted_cb)
198                 listen_dp->accepted_cb(accepted_event->connected_dp, listen_dp->accepted_cb_data);
199 }
200
201 void notify_accepted(vine_data_path_h datapath, int result)
202 {
203         VINE_LOGD("notify_accepted dp[%p] result[%d]", datapath, result);
204
205         RET_IF(datapath == NULL, "dp is NULL");
206         vine_data_path_s *dp = (vine_data_path_s *)datapath;
207
208         if (result < 0) {
209                 // TODO: Handle auth failure
210                 VINE_LOGE("Failure dp[%p]", datapath);
211                 vine_data_path_destroy(datapath);
212                 return;
213         }
214
215         vine_dp_accepted_event *accepted_event =
216                 (vine_dp_accepted_event *)calloc(1, sizeof(vine_dp_accepted_event));
217         RET_IF(accepted_event == NULL, "Out of memory");
218         accepted_event->connected_dp = dp;
219
220         VINE_LOGD("Create a accepted_event[%p]", accepted_event);
221
222         vine_data_path_s *listen_dp = (vine_data_path_s *)dp->listen_dp;
223         VINE_LOGD("listen_dp[%p]", listen_dp);
224         if (listen_dp)
225                 vine_event_loop_add_event(listen_dp->event_queue, accepted_event,
226                         __invoke_accepted_user_cb, __free_accepted_event, listen_dp);
227 }
228
229 static void __invoke_opened_user_cb(void *event, void *user_data)
230 {
231         RET_IF(event == NULL, "event is null");
232
233         vine_dp_opened_event *opened_event = (vine_dp_opened_event *)event;
234         vine_data_path_s *dp = (vine_data_path_s *)user_data;
235
236         VINE_LOGD("user callback is invoked by event queue");
237
238         if (dp && dp->opened_cb)
239                 dp->opened_cb(dp, opened_event->result, opened_event->port, dp->opened_cb_data);
240 }
241 static void __opened_cb(int result, int port, void *user_data)
242 {
243         RET_IF(user_data == NULL, "dp is NULL");
244
245         vine_data_path_s *dp = (vine_data_path_s *)user_data;
246         vine_dp_opened_event *opened_event =
247                 (vine_dp_opened_event *)calloc(1, sizeof(vine_dp_opened_event));
248         opened_event->result = result;
249         opened_event->port = port;
250
251         vine_event_loop_add_event(dp->event_queue, opened_event,
252                 __invoke_opened_user_cb, free, dp);
253 }
254
255 static vine_address_family_e __convert_addr_family(vine_dp_addr_family_e addr_family)
256 {
257         switch (addr_family) {
258         case VINE_DP_IPV4_IPV6:
259                 return VINE_ADDRESS_FAMILY_DEFAULT;
260         case VINE_DP_IPV4:
261                 return VINE_ADDRESS_FAMILY_IPV4;
262         case VINE_DP_IPV6:
263                 return VINE_ADDRESS_FAMILY_IPV6;
264         }
265         return VINE_ADDRESS_FAMILY_DEFAULT;
266 }
267
268 static void __accepted_cb(vine_dp_addr_family_e addr_family, char *addr,
269         int port, void *plugin_data, void *user_data)
270 {
271         RET_IF(user_data == NULL, "listen_dp is NULL");
272
273         vine_data_path_s *listen_dp = (vine_data_path_s *)user_data;
274
275         VINE_LOGE("listen_dp[%p], security[%p]", listen_dp, listen_dp->security);
276         vine_data_path_s *connected_dp = _vine_data_path_create(__convert_addr_family(addr_family),
277                         addr, port, listen_dp->security, plugin_data, listen_dp->event_queue);
278         RET_IF(connected_dp == NULL, "Out of memory");
279
280         VINE_LOGD("Accepted dp[%p] addr[%s] port[%d] listen_dp[%p]", connected_dp, addr, port, user_data);
281         connected_dp->listen_dp = listen_dp;
282
283         VINE_LOGD("Start Authentication");
284         connected_dp->established = notify_accepted;
285         start_accepted_state(connected_dp, connected_dp->plugin_handle, connected_dp->state);
286 }
287
288 static void __invoke_connected_user_cb(void *event, void *user_data)
289 {
290         RET_IF(event == NULL, "event is null");
291
292         vine_dp_connected_event *connected_event = (vine_dp_connected_event *)event;
293         vine_data_path_s *dp = (vine_data_path_s *)user_data;
294
295         VINE_LOGD("user callback is invoked by event queue.");
296
297         if (dp && dp->connected_cb)
298                 dp->connected_cb(dp, connected_event->result, dp->connected_cb_data);
299 }
300
301 void notify_connected(vine_data_path_h datapath, int result)
302 {
303         VINE_LOGD("notify_connected dp[%p] result[%d]", datapath, result);
304
305         RET_IF(datapath == NULL, "dp is NULL");
306         vine_dp_connected_event *connected_event =
307                 (vine_dp_connected_event *)calloc(1, sizeof(vine_dp_connected_event));
308         RET_IF(connected_event == NULL, "Out of memory");
309
310         connected_event->result = result;
311         vine_data_path_s *dp = (vine_data_path_s *)datapath;
312         vine_event_loop_add_event(dp->event_queue, connected_event,
313                 __invoke_connected_user_cb, free, datapath);
314 }
315
316 static void __connected_cb(int result, void *user_data)
317 {
318         VINE_LOGD("Connected dp[%p] result[%d]", user_data, result);
319
320         RET_IF(user_data == NULL, "dp is NULL");
321
322         vine_data_path_s *dp = (vine_data_path_s *)user_data;
323         if (result < 0) {
324                 VINE_LOGE("Fail to connect");
325                 notify_connected(dp, result);
326                 return;
327         }
328
329         VINE_LOGD("Start Authentication");
330         dp->established = notify_connected;
331         start_connected_state(dp, dp->plugin_handle, dp->state);
332 }
333
334 static void __invoke_received_user_cb(void *event, void *user_data)
335 {
336         RET_IF(event == NULL, "Out of memory");
337
338         vine_dp_received_event *received_event = (vine_dp_received_event *)event;
339         vine_data_path_s *dp = (vine_data_path_s *)user_data;
340
341         VINE_LOGD("user callback is invoked by event queue.");
342
343         if (dp && dp->recv_cb) {
344                 // user can read the data in recv_cb().
345                 dp->recv_cb(dp, received_event->bytes, dp->recv_cb_data);
346         }
347 }
348
349 void notify_data_received(vine_data_path_h datapath, size_t bytes)
350 {
351         vine_dp_received_event *received_event =
352                 (vine_dp_received_event *)calloc(1, sizeof(vine_dp_received_event));
353         RET_IF(received_event == NULL, "Out of memory");
354
355         received_event->bytes = bytes;
356
357         VINE_LOGD("Create a received_event[%p] datapath[%p]", received_event, datapath);
358
359         vine_data_path_s *dp = (vine_data_path_s *)datapath;
360         if (dp)
361                 vine_event_loop_add_event(dp->event_queue, received_event,
362                         __invoke_received_user_cb, free, datapath);
363 }
364
365 static void __received_cb(size_t bytes, void *user_data)
366 {
367         RET_IF(user_data == NULL, "dp is NULL");
368
369         vine_data_path_s *dp = (vine_data_path_s *)user_data;
370         dp->state->received_cb(bytes);
371 }
372
373 static void __written_cb(int bytes, void *user_data)
374 {
375         VINE_LOGD("%d bytes are written through datapath[%p].", bytes, user_data);
376         vine_data_path_s *dp = (vine_data_path_s *)user_data;
377         dp->state->written_cb(bytes);
378 }
379
380 static void __invoke_terminated_user_cb(void *event, void *user_data)
381 {
382         RET_IF(user_data == NULL, "dp is NULL");
383
384         vine_data_path_s *dp = (vine_data_path_s *)user_data;
385
386         VINE_LOGD("user callback is invoked by event queue.");
387
388         start_default_state(dp, dp->plugin_handle, dp->state);
389         if (dp->terminated_cb)
390                 dp->terminated_cb(dp, dp->terminated_cb_data);
391 }
392
393 static void __terminated_cb(void *user_data)
394 {
395         vine_data_path_s *dp = (vine_data_path_s *)user_data;
396         if (dp)
397                 vine_event_loop_add_event(dp->event_queue, NULL,
398                         __invoke_terminated_user_cb, NULL, user_data);
399 }
400
401 static int _load_data_path_plugins(void)
402 {
403         void *handle = dlopen(DATA_PATH_PLUGIN_PATH, RTLD_LAZY | RTLD_NODELETE);
404         if (handle) {
405                 __init_plugin = (void (*)(vine_dp_plugin_fn *))dlsym(handle, "vine_data_path_plugin_init");
406                 dlclose(handle);
407                 VINE_LOGI("Loaded %s", DATA_PATH_PLUGIN_PATH);
408         } else {
409                 VINE_LOGE("%s doesn't exist", DATA_PATH_PLUGIN_PATH);
410                 return VINE_ERROR_OPERATION_FAILED;
411         }
412
413         return VINE_ERROR_NONE;
414 }
415
416 int vine_data_path_set_received_cb(
417                 vine_data_path_h datapath, vine_data_path_received_cb callback, void *user_data)
418 {
419         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
420         RET_VAL_IF(callback == NULL, VINE_ERROR_INVALID_PARAMETER, "callback is NULL");
421
422         vine_data_path_s *dp = (vine_data_path_s *)datapath;
423         dp->recv_cb = callback;
424         dp->recv_cb_data = user_data;
425
426         return VINE_ERROR_NONE;
427 }
428
429 int vine_data_path_unset_received_cb(vine_data_path_h datapath)
430 {
431         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
432
433         vine_data_path_s *dp = (vine_data_path_s *)datapath;
434         dp->recv_cb = NULL;
435         dp->recv_cb_data = NULL;
436
437         return VINE_ERROR_NONE;
438 }
439
440 int vine_data_path_write(vine_data_path_h datapath, unsigned char *buf, size_t len)
441 {
442         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
443         RET_VAL_IF(buf == NULL, VINE_ERROR_INVALID_PARAMETER, "buf is NULL");
444         RET_VAL_IF(len == 0, VINE_ERROR_INVALID_PARAMETER, "len cannot be 0");
445
446         vine_data_path_s *dp = (vine_data_path_s *)datapath;
447         return dp->state->write(buf, len);
448 }
449
450 int vine_data_path_read(vine_data_path_h datapath,
451                 unsigned char *buf, size_t buf_len, size_t *read_len)
452 {
453         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
454         RET_VAL_IF(buf == NULL, VINE_ERROR_INVALID_PARAMETER, "buf is NULL");
455         RET_VAL_IF(buf_len == 0, VINE_ERROR_INVALID_PARAMETER, "buf_len cannot be 0");
456         RET_VAL_IF(read_len == NULL, VINE_ERROR_INVALID_PARAMETER, "read_len is NULL");
457
458         vine_data_path_s *dp = (vine_data_path_s *)datapath;
459         return dp->state->read(buf, buf_len, read_len);
460 }
461
462 int vine_data_path_close(vine_data_path_h datapath)
463 {
464         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
465
466         vine_data_path_s *dp = (vine_data_path_s *)datapath;
467         g_dp_plugin_fn.close(dp->plugin_handle);
468
469         return VINE_ERROR_NONE;
470 }
471
472 static vine_data_path_s *_vine_data_path_create(vine_address_family_e addr_family,
473                 const char *addr, int port, vine_security_h security,
474                 void *plugin_data, vine_event_queue_h event_queue)
475 {
476         RET_VAL_IF(addr == NULL, NULL, "addr is NULL");
477
478         int ret = VINE_ERROR_NONE;
479         vine_data_path_s *dp = NULL;
480
481         dp = (vine_data_path_s *)calloc(1, sizeof(vine_data_path_s));
482         RET_VAL_IF(dp == NULL, NULL, "Out of memory");
483
484         dp->addr_family = addr_family;
485         dp->addr = STRDUP(addr);
486         if (dp->addr == NULL) {
487                 VINE_LOGE("Out of memory");
488                 free(dp);
489                 return NULL;
490         }
491         dp->port = port;
492         dp->recv_cb = NULL;
493         dp->recv_cb_data = NULL;
494         dp->event_queue = event_queue;
495         if (security != NULL) {
496                 ret = _vine_security_clone(&(dp->security), security);
497                 if (ret != VINE_ERROR_NONE) {
498                         VINE_LOGE("Fail to clone security %d", ret);
499                         free(dp->addr);
500                         free(dp);
501                         return NULL;
502                 }
503         }
504         else {
505                 dp->security = NULL;
506         }
507
508         ret = g_dp_plugin_fn.create(&dp->plugin_handle, plugin_data, dp);
509         if (ret != VINE_DATA_PATH_ERROR_NONE) {
510                 free(dp->addr);
511                 _vine_security_destroy(dp->security);
512                 dp->security = NULL;
513                 free(dp);
514                 return NULL;
515         }
516
517         dp->state = vine_get_default_state(dp, dp->plugin_handle);
518         VINE_LOGD("datapath[%p] is created.", dp);
519         return dp;
520 }
521
522 int vine_data_path_destroy(vine_data_path_h datapath)
523 {
524         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
525         vine_data_path_s *dp = (vine_data_path_s *)datapath;
526
527         g_dp_plugin_fn.destroy(dp->plugin_handle);
528         dp->plugin_handle = NULL;
529         free(dp->addr);
530         dp->addr = NULL;
531         _vine_security_destroy(dp->security);
532         dp->security = NULL;
533         dp->listen_dp = NULL;
534         delete dp->state;
535
536         VINE_LOGD("data_path[%p] is destroyed", datapath);
537         free(datapath);
538         return VINE_ERROR_NONE;
539 }
540
541 const char *vine_data_path_get_ip(vine_data_path_h datapath)
542 {
543         RET_VAL_IF(datapath == NULL, NULL, "datapath is NULL");
544         vine_data_path_s *dp = (vine_data_path_s *)datapath;
545         return (const char *)dp->addr;
546 }
547
548 vine_address_family_e vine_data_path_get_addr_family(vine_data_path_h datapath)
549 {
550         RET_VAL_IF(datapath == NULL, VINE_ADDRESS_FAMILY_DEFAULT, "datapath is NULL");
551         vine_data_path_s *dp = (vine_data_path_s *)datapath;
552         return dp->addr_family;
553 }
554
555 int vine_data_path_get_port(vine_data_path_h datapath)
556 {
557         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
558         vine_data_path_s *dp = (vine_data_path_s *)datapath;
559         return dp->port;
560 }
561
562 static void __set_state(vine_data_path_h datapath, VineDataPathState *state)
563 {
564         RET_IF(datapath == NULL, "datapath is NULL");
565
566         vine_data_path_s *dp = (vine_data_path_s *)datapath;
567         VINE_LOGD("Datapath[%p] state: %s --> %s",
568                 datapath, dp->state->str().c_str(), state->str().c_str());
569         dp->state = state;
570 }
571
572 static void __established(vine_data_path_h datapath, int result)
573 {
574         RET_IF(datapath == NULL, "datapath is NULL");
575
576         vine_data_path_s *dp = (vine_data_path_s *)datapath;
577         dp->established(dp, result);
578 }
579
580 static void __data_received(vine_data_path_h dp, size_t bytes)
581 {
582         notify_data_received(dp, bytes);
583 }
584
585 int vine_data_path_init(void)
586 {
587         int ret = _load_data_path_plugins();
588         RET_VAL_IF(ret != VINE_ERROR_NONE, ret, "Fail to load plugins");
589         __init_plugin(&g_dp_plugin_fn);
590
591         ret = g_dp_plugin_fn.init();
592         RET_VAL_IF(ret != VINE_DATA_PATH_ERROR_NONE,
593                         __convert_data_path_error_to_vine_error((vine_data_path_error)ret),
594                         "Filed to init dp-plugin");
595
596         g_dp_plugin_cbs.pollfd_cb = __pollfd_cb;
597         g_dp_plugin_cbs.opened_cb = __opened_cb;
598         g_dp_plugin_cbs.accepted_cb = __accepted_cb;
599         g_dp_plugin_cbs.connected_cb = __connected_cb;
600         g_dp_plugin_cbs.received_cb = __received_cb;
601         g_dp_plugin_cbs.written_cb = __written_cb;
602         g_dp_plugin_cbs.terminated_cb = __terminated_cb;
603         g_dp_plugin_fn.register_callbacks(g_dp_plugin_cbs);
604
605         vine_dp_state_set_state_changed_notifier(__set_state);
606         vine_dp_state_set_established_notifier(__established);
607         vine_dp_state_set_data_received_notifier(__data_received);
608         return VINE_ERROR_NONE;
609 }
610
611 int vine_data_path_deinit(void)
612 {
613         g_dp_plugin_fn.deinit();
614
615         return VINE_ERROR_NONE;
616 }
617
618 static vine_dp_tls_version_e __convert_tls_version(vine_security_tls_version_e version)
619 {
620         switch (version) {
621         case VINE_SECURITY_TLS_VERSION_DEFAULT:
622                 return VINE_DP_TLS_VERSION_DEFAULT;
623         case VINE_SECURITY_TLS_VERSION_1_0:
624                 return VINE_DP_TLS_VERSION_1_0;
625         case VINE_SECURITY_TLS_VERSION_1_1:
626                 return VINE_DP_TLS_VERSION_1_1;
627         case VINE_SECURITY_TLS_VERSION_1_2:
628                 return VINE_DP_TLS_VERSION_1_2;
629         case VINE_SECURITY_TLS_VERSION_1_3:
630                 return VINE_DP_TLS_VERSION_1_3;
631         default:
632                 return VINE_DP_TLS_VERSION_MAX;
633         }
634 }
635
636 static void _extract_security_info(vine_security_h src, vine_dp_ssl *dest)
637 {
638         RET_IF(src == NULL, "src is NULL");
639         RET_IF(dest == NULL, "dest is NULL");
640
641         vine_security_type_e type = VINE_SECURITY_TYPE_NONE;
642         vine_security_tls_version_e version = VINE_SECURITY_TLS_VERSION_DEFAULT;
643         int flags = 0;
644
645         _vine_security_get_type(src, &type);
646         dest->use_ssl = (type != VINE_SECURITY_TYPE_NONE) ? true : false;
647
648         if (!dest->use_ssl)
649                 return;
650
651         _vine_security_get_tls_version(src, &version);
652         dest->tls_version = __convert_tls_version(version);
653
654         _vine_security_get_verification_flags(src, &flags);
655         dest->vflags |= (flags & VINE_SECURITY_VERIFICATION_FLAG_ALLOW_SELF_SIGNED) ?
656                 VINE_DATA_PATH_V_FLAG_ALLOW_SS_CERTIFICATE : 0;
657         dest->vflags |= (flags & VINE_SECURITY_VERIFICATION_FLAG_SKIP_HOST_NAME_CHECK) ?
658                 VINE_DATA_PATH_V_FLAG_SKIP_CN_CHECK : 0;
659
660         _vine_security_get_ca_path(src, &dest->ca_path);
661         _vine_security_get_cert_path(src, &dest->cert_path);
662         _vine_security_get_private_key(src, &dest->key_path);
663 }
664
665 static void _destroy_security_info(vine_dp_ssl *dest)
666 {
667         RET_IF(dest == NULL, "dest is NULL");
668
669         free(dest->ca_path);
670         free(dest->cert_path);
671         free(dest->key_path);
672 }
673
674 int vine_data_path_open(vine_address_family_e addr_family, int port, const char *iface_name,
675                 int max_conn, vine_security_h security, const char *host_name,
676                 vine_data_path_opened_cb opened_cb, void *opened_cb_data,
677                 vine_data_path_accepted_cb accepted_cb, void *accepted_cb_data,
678                 vine_data_path_h *opened_datapath,
679                 vine_event_queue_h event_queue)
680 {
681         vine_dp_addr_family_e dp_addr_family;
682         int ret = __convert_address_family(addr_family, &dp_addr_family);
683         if (ret != VINE_ERROR_NONE) {
684                 VINE_LOGE("Cannot convert address family.");
685                 return ret;
686         }
687
688         vine_data_path_s *dp =
689                 _vine_data_path_create(addr_family, "", port, security, NULL, event_queue);
690         RET_VAL_IF(dp == NULL, VINE_ERROR_OUT_OF_MEMORY, "Out of memory");
691
692         vine_dp_ssl ssl = {false, VINE_DP_TLS_VERSION_DEFAULT, 0, NULL, NULL, NULL};
693         _extract_security_info(security, &ssl);
694
695         dp->opened_cb = opened_cb;
696         dp->opened_cb_data = opened_cb_data;
697         dp->accepted_cb = accepted_cb;
698         dp->accepted_cb_data = accepted_cb_data;
699
700         // optional
701         if (host_name) {
702                 ret = g_dp_plugin_fn.set_host_name(dp->plugin_handle, host_name);
703                 if (ret != VINE_DATA_PATH_ERROR_NONE) {
704                         vine_data_path_destroy(dp);
705                         return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
706                 }
707         }
708
709         ret = g_dp_plugin_fn.open(dp->plugin_handle, dp_addr_family, port, iface_name, max_conn, ssl);
710         _destroy_security_info(&ssl);
711
712         if (ret != VINE_DATA_PATH_ERROR_NONE) {
713                 vine_data_path_destroy(dp);
714                 return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
715         }
716
717         if (*opened_datapath) {
718                 VINE_LOGI("Destroy a stale datapath.");
719                 vine_data_path_destroy(*opened_datapath);
720         }
721         *opened_datapath = dp;
722
723         return VINE_ERROR_NONE;
724 }
725
726 int vine_data_path_connect(vine_address_family_e addr_family,
727                 const char *ip, int port, const char *iface_name,
728                 vine_security_h security, const char *host_name, const char *token,
729                 vine_data_path_connected_cb callback, void *user_data,
730                 vine_data_path_h *connected_datapath, vine_event_queue_h event_queue)
731 {
732         vine_data_path_s *dp =
733                 _vine_data_path_create(addr_family, ip, port, security, NULL, event_queue);
734         RET_VAL_IF(dp == NULL, VINE_ERROR_OUT_OF_MEMORY, "Out of memory");
735         RET_VAL_IF(connected_datapath == NULL,
736                         VINE_ERROR_INVALID_PARAMETER, "connected_datapath is NULL");
737
738         dp->connected_cb = callback;
739         dp->connected_cb_data = user_data;
740
741         vine_dp_ssl ssl = {false, VINE_DP_TLS_VERSION_DEFAULT, 0, NULL, NULL, NULL};
742         _extract_security_info(security, &ssl);
743
744         int ret;
745
746         // optional
747         if (host_name) {
748                 ret = g_dp_plugin_fn.set_host_name(dp->plugin_handle, host_name);
749                 if (ret != VINE_DATA_PATH_ERROR_NONE) {
750                         vine_data_path_destroy(dp);
751                         return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
752                 }
753         }
754
755         if (token) {
756                 ret = g_dp_plugin_fn.set_token(dp->plugin_handle, token);
757                 if (ret != VINE_DATA_PATH_ERROR_NONE) {
758                         vine_data_path_destroy(dp);
759                         _destroy_security_info(&ssl);
760                         return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
761                 }
762         }
763
764         ret = g_dp_plugin_fn.connect(dp->plugin_handle,
765                         addr_family == VINE_ADDRESS_FAMILY_IPV4 ? VINE_DP_IPV4 : VINE_DP_IPV6,
766                         ip, port, iface_name, ssl);
767         _destroy_security_info(&ssl);
768
769         if (*connected_datapath) {
770                 VINE_LOGI("Destroy a stale datapath.");
771                 vine_data_path_destroy(*connected_datapath);
772         }
773
774         *connected_datapath = dp;
775
776         return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
777 }
778
779 int vine_data_path_set_terminated_cb(vine_data_path_h datapath,
780                 vine_data_path_terminated_cb callback, void *user_data)
781 {
782         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
783         RET_VAL_IF(callback == NULL, VINE_ERROR_INVALID_PARAMETER, "callback is NULL");
784
785         vine_data_path_s *dp = (vine_data_path_s *)datapath;
786         dp->terminated_cb = callback;
787         dp->terminated_cb_data = user_data;
788
789         return VINE_ERROR_NONE;
790 }
791
792 int vine_data_path_get_token(vine_data_path_h datapath, char **token)
793 {
794         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
795         RET_VAL_IF(token == NULL, VINE_ERROR_INVALID_PARAMETER, "token is NULL");
796
797         vine_data_path_s *dp = (vine_data_path_s *)datapath;
798         int ret = g_dp_plugin_fn.get_token(dp->plugin_handle, token);
799         return __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
800 }
801
802 vine_security_h vine_data_path_get_security(vine_data_path_h datapath)
803 {
804         RET_VAL_IF(datapath == NULL, NULL, "datapath is NULL");
805
806         vine_data_path_s *dp = (vine_data_path_s *)datapath;
807         return dp->security;
808 }
809
810 int vine_data_path_get_local_address_info(vine_data_path_h datapath, int *address_family,
811                 char **ip, int *port)
812 {
813         RET_VAL_IF(datapath == NULL, VINE_ERROR_INVALID_PARAMETER, "datapath is NULL");
814         RET_VAL_IF(address_family == NULL, VINE_ERROR_INVALID_PARAMETER, "address_family is NULL");
815         RET_VAL_IF(ip == NULL, VINE_ERROR_INVALID_PARAMETER, "ip is NULL");
816         RET_VAL_IF(port == NULL, VINE_ERROR_INVALID_PARAMETER, "port is NULL");
817
818         vine_data_path_s *dp = (vine_data_path_s *)datapath;
819         vine_error_e error;
820         int addr_family, local_port;
821         char local_ip[VINE_MAX_IP_LEN + 1] = {0, };
822         int ret = g_dp_plugin_fn.get_local_address_info(dp->plugin_handle,
823                         &addr_family, local_ip, &local_port);
824
825         error = __convert_data_path_error_to_vine_error((vine_data_path_error)ret);
826         if (error != VINE_ERROR_NONE)
827                 return error;
828
829         *address_family = addr_family;
830         *port = local_port;
831         *ip = STRDUP(local_ip);
832
833         return VINE_ERROR_NONE;
834 }