Do not build unittest when ASAN is enabled
[platform/core/api/vine.git] / tool / tool_run.cpp
1 #include "tool_run.h"
2
3 #include "tool_config.h"
4
5 #include <vine.h>
6 #include <vine-log.h>
7 #include <sys/epoll.h>
8 #include <sys/syscall.h>
9 #include <sys/timerfd.h>
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <limits.h>
15 #include <map>
16
17 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
18 #include <glib.h>
19 #endif
20
21 #define RESET_COLOR "\e[m"
22 #define MAKE_RED "\e[31m"
23 #define MAKE_GREEN "\e[32m"
24
25 #define MAX_EVENTS 10
26 #define MAX_READ_LEN 1024
27 #define MAX_WRITE_LEN 300
28
29 int interrupt_flag;
30
31 static int epollfd = 0;
32 static FILE *log_file = NULL;
33
34 static struct {
35         vine_session_h session;
36         vine_service_h service;
37         vine_dp_h dp;
38         vine_security_h security;
39         const char *type;
40         const char *iface;
41         bool with_ble;
42         vine_dp_type_e dp_type;
43         int max_conn;
44         const char *msg;
45         const char *file;
46         int interval;
47         bool is_reg;
48         bool is_disc;
49         bool is_dp;
50         bool is_sec;
51 } vine_configs = {
52         .session = NULL,
53         .service = NULL,
54         .dp = NULL,
55         .security = NULL,
56         .type = NULL,
57         .iface = NULL,
58         .with_ble = false,
59         .dp_type = VINE_DP_TYPE_UNKNOWN,
60         .max_conn = 0,
61         .msg = NULL,
62         .file = NULL,
63         .interval = 0,
64         .is_reg = false,
65         .is_disc = false,
66         .is_dp = false,
67         .is_sec = false,
68 };
69
70 static std::map<vine_dp_h, int> timerfds;
71 static int send_message(vine_dp_h dp);
72 static void _stop_message_timer(vine_dp_h dp);
73 static int joined_peer = 0;
74
75 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
76 static GMainLoop *main_loop = NULL;
77 #endif
78
79 static vine_dp_type_e _convert_dp_type(dp_type_t type)
80 {
81         switch (type) {
82         case DP_TYPE_CLIENT:
83                 return VINE_DP_TYPE_CLIENT;
84         case DP_TYPE_SERVER:
85                 return VINE_DP_TYPE_SERVER;
86         case DP_TYPE_PUBSUB:
87                 return VINE_DP_TYPE_PUBSUB;
88         case DP_TYPE_UNKNOWN:
89         default:
90                 return VINE_DP_TYPE_UNKNOWN;
91         }
92 }
93
94 static vine_security_type_e _convert_sec_type(sec_type_t type)
95 {
96         switch (type) {
97         case SEC_TYPE_NONE:
98                 return VINE_SECURITY_TYPE_NONE;
99         case SEC_TYPE_TLS:
100                 return VINE_SECURITY_TYPE_TLS;
101         case SEC_TYPE_PSK_OVER_TLS:
102                 return VINE_SECURITY_TYPE_PSK_OVER_TLS;
103         default:
104                 return VINE_SECURITY_TYPE_NONE;
105         }
106 }
107
108 static vine_address_family_e _convert_addr_family(int family)
109 {
110         switch (family) {
111         case 0:
112                 return VINE_ADDRESS_FAMILY_DEFAULT;
113         case 4:
114                 return VINE_ADDRESS_FAMILY_IPV4;
115         case 6:
116                 return VINE_ADDRESS_FAMILY_IPV6;
117         default:
118                 return VINE_ADDRESS_FAMILY_DEFAULT;
119         }
120 }
121
122
123 static void __print_received_data(unsigned char *buf, size_t len)
124 {
125         for (int i = 0; i < (int)len; i++)
126                 printf("%c", buf[i]);
127         printf("\n");
128 }
129
130 static void __received_cb(vine_dp_h dp, size_t received_len, void *user_data)
131 {
132         unsigned char buf[MAX_READ_LEN] = {0, };
133         size_t bytes = 0;
134
135         printf("Message is received. %zd bytes.\n", received_len);
136         do {
137                 vine_dp_recv(dp, buf, MAX_READ_LEN, &bytes);
138                 __print_received_data(buf, bytes);
139                 received_len -= bytes;
140         } while (received_len > 0);
141 }
142
143 static void __terminated_cb(vine_dp_h dp, void *user_data)
144 {
145         printf("peer[%p] is terminated.\n", dp);
146         _stop_message_timer(dp);
147 }
148
149 static void __opened_cb(vine_dp_h dp, vine_error_e result, void *user_data)
150 {
151         printf("DP %s.\n", result == VINE_ERROR_NONE ? "is opened" : "open failure");
152         if (result != VINE_ERROR_NONE)
153                 return;
154
155         vine_address_family_e addr_family;
156         char *id = NULL;
157         char *ip = NULL;
158         int port = 0;
159
160         if (vine_configs.dp_type == VINE_DP_TYPE_PUBSUB) {
161                 vine_dp_get_id(dp, &id);
162                 printf("\t> ID: %s\n", id);
163         } else {
164                 vine_dp_get_port(dp, &port);
165                 printf("\t> %s port: %d\n",
166                                 vine_configs.dp_type == VINE_DP_TYPE_CLIENT ? "connected" : "listen",
167                                 port);
168
169                 vine_dp_get_ip(dp, &addr_family, &ip);
170                 printf("\t> local IP: %s, address family: %d \n", ip, addr_family);
171                 free(ip);
172         }
173
174         vine_dp_set_received_cb(dp, __received_cb, NULL);
175         vine_dp_set_terminated_cb(dp, __terminated_cb, NULL);
176
177         if (result == VINE_ERROR_NONE
178                         && vine_configs.dp_type == VINE_DP_TYPE_CLIENT
179                         && (vine_configs.msg || vine_configs.file))
180                 send_message(dp);
181 }
182
183 static void __accepted_cb(vine_dp_h dp, vine_dp_h accepted_dp, void *user_data)
184 {
185         vine_address_family_e addr_family;
186         int port = 0;
187         char *ip = NULL;
188
189         vine_dp_get_remote_port(accepted_dp, &port);
190         printf("client is accepted.\n");
191         printf("\t> client port: %d\n", port);
192
193         vine_dp_get_ip(accepted_dp, &addr_family, &ip);
194         printf("\t> used local IP: %s, address family: %d\n", ip, addr_family);
195         free(ip);
196
197         vine_dp_set_received_cb(accepted_dp, __received_cb, NULL);
198         vine_dp_set_terminated_cb(accepted_dp, __terminated_cb, NULL);
199
200         if (vine_configs.msg || vine_configs.file)
201                 send_message(accepted_dp);
202 }
203
204 static void __peer_joined_cb(vine_dp_h dp, const char *peer_id, void *user_data)
205 {
206         printf("pubsub peer(%s) is joined.\n", peer_id);
207         ++joined_peer;
208         // if joined_peer is larger than 1,
209         // this means message timer has already runned.
210         if (joined_peer == 1)
211                 send_message(dp);
212 }
213
214 static void __peer_left_cb(vine_dp_h dp, const char *peer_id, void *user_data)
215 {
216         printf("pubsub peer(%s) is left.\n", peer_id);
217         --joined_peer;
218         if (joined_peer == 0)
219                 _stop_message_timer(dp);
220 }
221
222 static void __registered_cb(vine_session_h session,
223                                 const char *service_name, vine_error_e error, void *user_data)
224 {
225         printf("Service[%s] ", service_name);
226         if (error == VINE_ERROR_NONE)
227                 printf("registered. \n");
228         else if (error == VINE_ERROR_SERVICE_DEREGISTERED)
229                 printf("deregistered by a name conflict. Service name will be renamed.\n");
230         else
231                 printf("registration failure.\n");
232 }
233
234 static bool __print_attr(const char *key, const char *value, void *user_data)
235 {
236         printf("\t   > Attributes: %s=%s\n", key, value);
237         return true;
238 }
239
240 static void __ip_resolved_cb(vine_session_h session, vine_service_h service,
241                 const char *ip, vine_address_family_e address_family,
242                 void *user_data)
243 {
244         char *service_type;
245         char *service_name;
246         int port;
247
248         printf("Service discovered.\n");
249         vine_service_get_type(service, &service_type);
250         vine_service_get_name(service, &service_name);
251         vine_service_get_port(service, &port);
252
253         printf("\t   > Service Type: %s\n", service_type);
254         printf("\t   > Service Name: %s\n", service_name);
255         printf("\t   > IP Address: %s\n", ip);
256         printf("\t   > Port: %d\n", port);
257         vine_service_foreach_attribute(service, __print_attr, NULL);
258         printf("\n");
259         fflush(stdout);
260         free(service_type);
261         free(service_name);
262 }
263
264 static void __ble_service_discovered(vine_session_h session, vine_service_h service,
265                                 vine_service_state_e state, void *user_data)
266 {
267         printf("available[%d]\n", state);
268         printf("Service discovered.\n");
269
270         char *service_type;
271         char *service_name;
272         char *mac;
273         vine_service_get_type(service, &service_type);
274         vine_service_get_name(service, &service_name);
275         vine_service_get_mac(service, &mac);
276
277         printf("\t   > Service Type: %s\n", service_type);
278         printf("\t   > Service Name: %s\n", service_name);
279         printf("\t   > MAC Address: %s\n", mac);
280         printf("\n");
281         fflush(stdout);
282
283         free(service_type);
284         free(service_name);
285         free(mac);
286
287         vine_session_stop_discovery(session);
288 }
289
290 static void __discovered_cb(vine_session_h session, vine_service_h service,
291                                 vine_service_state_e state, void *user_data)
292 {
293         if (vine_configs.with_ble) {
294                 __ble_service_discovered(session, service, state, user_data);
295                 return;
296         }
297
298         printf("available[%d]\n", state);
299         vine_service_h s;
300         vine_service_clone(service, &s);
301
302         vine_session_set_ip_resolved_cb(session, s,
303                         _convert_addr_family(tool_config_get_address_family()),
304                         __ip_resolved_cb, NULL);
305 }
306
307 static void _start_message_timer(vine_dp_h dp, int sec)
308 {
309         if (sec <= 0)
310                 return;
311
312         int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
313         if (timerfd == -1)
314                 return;
315
316         struct itimerspec value;
317         value.it_interval.tv_sec = sec;
318         value.it_interval.tv_nsec = 0;
319         value.it_value.tv_sec = sec;
320         value.it_value.tv_nsec = 0;
321         if (timerfd_settime(timerfd, 0, &value, NULL) != 0) {
322                 close(timerfd);
323                 return;
324         }
325
326         timerfds.insert(std::make_pair(dp, timerfd));
327         struct epoll_event ev;
328         ev.events = EPOLLIN;
329         ev.data.ptr = (void *)dp;
330         epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev);
331 }
332
333 static void _stop_message_timer(vine_dp_h dp)
334 {
335         auto it = timerfds.find(dp);
336         if (it == timerfds.end())
337                 return;
338
339         int timerfd = it->second;
340         if (timerfd <= 0) {
341                 timerfds.erase(it);
342                 return;
343         }
344
345         uint64_t buf;
346         int expired = read(timerfd, &buf, sizeof(uint64_t));
347         if (expired != sizeof(uint64_t))
348                 printf("expired[%d]. operation failed.\n", expired);
349
350         epoll_ctl(epollfd, EPOLL_CTL_DEL, timerfd, NULL);
351         close(timerfd);
352         timerfds.erase(it);
353 }
354
355 static void _stop_message_timer_all()
356 {
357         for (auto &it : timerfds) {
358                 if (it.second <= 0)
359                         continue;
360                 close(it.second);
361         }
362         timerfds.clear();
363 }
364
365 static void _message_timer_handler(void *user_data)
366 {
367         vine_dp_h dp = (vine_dp_h) user_data;
368         _stop_message_timer(dp);
369         send_message(dp);
370 }
371
372 static int _send_message_from_file(vine_dp_h dp)
373 {
374         unsigned char *buf;
375         long size;
376         size_t count;
377         int ret = VINE_ERROR_NONE;
378         FILE *file = fopen(vine_configs.file, "r");
379
380         if (file == NULL)
381                 return -1;
382
383         fseek(file, 0, SEEK_END);
384
385         size = ftell(file);
386         if (size < 0 || size >= INT_MAX - 1) {
387                 fclose(file);
388                 return -1;
389         }
390         buf = (unsigned char *)calloc(sizeof(unsigned char), size);
391
392         fseek(file, 0, SEEK_SET);
393         count = fread(buf, sizeof(unsigned char), size, file);
394         fclose(file);
395
396         int idx = 0;
397         while (count) {
398                 size_t len = count <= MAX_WRITE_LEN ? count : MAX_WRITE_LEN;
399                 ret = vine_dp_send(dp, buf + idx, len);
400                 if (ret == VINE_ERROR_NONE) {
401                         printf("Sent total %zd bytes.\n", len);
402                 } else {
403                         printf("Failed to send a message.\n");
404                         break;
405                 }
406                 count -= len;
407                 idx += len;
408         }
409         free(buf);
410
411         return ret;
412 }
413
414 static int _send_message(vine_dp_h dp)
415 {
416         size_t len = strlen(vine_configs.msg);
417         if (len == 0)
418                 return -1;
419
420         unsigned char *buf = (unsigned char *)calloc(len, sizeof(unsigned char));
421         memcpy(buf, vine_configs.msg, len);
422
423         int ret = vine_dp_send(dp, buf, len);
424         printf("%s to send a message.\n", ret == VINE_ERROR_NONE ? "Succeeded" : "Failed");
425         _start_message_timer(dp, vine_configs.interval);
426         return ret;
427 }
428
429 static int send_message(vine_dp_h dp)
430 {
431         int ret = VINE_ERROR_NONE;
432
433         if (vine_configs.file)
434                 ret = _send_message_from_file(dp);
435         else if (vine_configs.msg)
436                 ret = _send_message(dp);
437         return ret != VINE_ERROR_NONE ? -1 : 0;
438 }
439
440 static int init()
441 {
442         if(vine_configs.with_ble) {
443                 if (vine_set_event_loop(VINE_EVENT_LOOP_EXTERNAL_GLIB) != VINE_ERROR_NONE)
444                         return -1;
445         }
446
447         int ret = vine_initialize();
448         if (ret != VINE_ERROR_NONE)
449                 return -1;
450
451         ret = vine_session_create(&vine_configs.session);
452         if (ret != VINE_ERROR_NONE)
453                 return -1;
454
455         if(vine_configs.with_ble)
456                 vine_session_set_discovery_method(vine_configs.session, VINE_DISCOVERY_METHOD_BLE);
457
458         return 0;
459 }
460
461 static void deinit()
462 {
463         tool_config_deinit();
464
465         _stop_message_timer_all();
466
467         if (vine_configs.is_reg)
468                 vine_session_unregister(vine_configs.session);
469
470         if (vine_configs.is_disc)
471                 vine_session_stop_discovery(vine_configs.session);
472
473         if (vine_configs.is_dp)
474                 vine_dp_close(vine_configs.dp);
475
476         if (vine_configs.security)
477                 vine_security_destroy(vine_configs.security);
478
479         if (vine_configs.dp)
480                 vine_dp_destroy(vine_configs.dp);
481
482         if (vine_configs.service)
483                 vine_service_destroy(vine_configs.service);
484
485         if (vine_configs.session)
486                 vine_session_destroy(vine_configs.session);
487
488         vine_deinitialize();
489
490         if (log_file) {
491                 fclose(log_file);
492                 log_file = NULL;
493         }
494 }
495
496 static void _logger(int log_level, const char *log)
497 {
498         struct timespec ts;
499         if(clock_gettime(CLOCK_REALTIME, &ts) == -1 )
500                 return;
501
502         char stamp[58] = {0, };
503         snprintf(stamp, 57, "[%ld.%03ld][T%5u]",
504                         ts.tv_sec, ts.tv_nsec / 1000000, (unsigned int)syscall(__NR_gettid));
505
506         if (log_file) {
507                 fprintf(log_file, "%s %s\n", stamp, log);
508                 return;
509         }
510         printf("%s ", stamp);
511         switch (log_level) {
512         case VINE_LOG_DEBUG:
513                 printf("DEBUG: ");
514                 break;
515         case VINE_LOG_INFO:
516                 printf("INFO: ");
517                 break;
518         case VINE_LOG_ERROR:
519                 printf(MAKE_RED "ERROR: ");
520                 break;
521         }
522         printf("%s" RESET_COLOR "\n", log);
523 }
524
525 static void debug_on()
526 {
527         if (!tool_config_get_verbose())
528                 return;
529
530         vine_set_log_level(VINE_LOG_ERROR | VINE_LOG_INFO | VINE_LOG_DEBUG);
531
532         const char *log_file_path = tool_config_get_log_file();
533         if (log_file_path) {
534                 log_file = fopen(log_file_path, "w+");
535         }
536         vine_set_logger(_logger);
537 }
538
539 static void _set_register_info()
540 {
541         vine_service_create(&vine_configs.service);
542         vine_service_set_name(vine_configs.service, tool_config_get_service_name());
543         vine_service_set_type(vine_configs.service, tool_config_get_service_type());
544         vine_service_set_port(vine_configs.service, tool_config_get_port());
545         vine_session_set_registered_cb(vine_configs.session, __registered_cb, NULL);
546 }
547
548 static void _set_discovery_info()
549 {
550         vine_configs.type = tool_config_get_service_type();
551         vine_configs.iface = tool_config_get_iface_name();
552         vine_session_set_discovered_cb(vine_configs.session, __discovered_cb, NULL);
553 }
554
555 static void _set_dp_info(vine_dp_type_e type)
556 {
557         vine_dp_create(vine_configs.session, type, &vine_configs.dp);
558         vine_address_family_e addr_family = _convert_addr_family(tool_config_get_address_family());
559         vine_dp_set_address_family(vine_configs.dp, addr_family);
560         vine_dp_set_max_connections(vine_configs.dp, tool_config_get_max_conn());
561
562         if (vine_configs.with_ble) {
563                 vine_dp_set_method(vine_configs.dp, VINE_DP_METHOD_BLE_GATT);
564                 if (type == VINE_DP_TYPE_CLIENT) {
565                         vine_service_create(&vine_configs.service);
566                         vine_service_set_type(vine_configs.service, tool_config_get_service_type());
567                 }
568                 vine_dp_set_remote_address(vine_configs.dp, tool_config_get_remote_address());
569                 vine_dp_set_service(vine_configs.dp, vine_configs.service);
570         }
571
572         if (type == VINE_DP_TYPE_CLIENT) {
573                 vine_dp_set_remote_port(vine_configs.dp, tool_config_get_port());
574                 vine_dp_set_remote_ip(vine_configs.dp, addr_family,
575                                 tool_config_get_remote_address());
576                 vine_dp_set_received_cb(vine_configs.dp, __received_cb, NULL);
577         } else {
578                 vine_dp_set_port(vine_configs.dp, tool_config_get_port());
579         }
580
581         if (type == VINE_DP_TYPE_SERVER)
582                 vine_dp_set_accepted_cb(vine_configs.dp, __accepted_cb, NULL);
583
584         if (type == VINE_DP_TYPE_PUBSUB) {
585                 vine_dp_set_topic(vine_configs.dp, tool_config_get_topic());
586                 vine_dp_set_peer_joined_cb(vine_configs.dp, __peer_joined_cb, NULL);
587                 vine_dp_set_peer_left_cb(vine_configs.dp, __peer_left_cb, NULL);
588         }
589
590         vine_dp_set_iface_name(vine_configs.dp, tool_config_get_iface_name());
591         vine_configs.msg = tool_config_get_message();
592         vine_configs.file = tool_config_get_file();
593         vine_configs.interval = tool_config_get_interval();
594         vine_dp_set_security(vine_configs.dp, vine_configs.security);
595 }
596
597 static void _set_security_info(vine_security_type_e type)
598 {
599         vine_security_create(&vine_configs.security);
600         vine_security_set_type(vine_configs.security, type);
601         vine_security_set_ca_path(vine_configs.security, tool_config_get_cacert());
602         vine_security_set_cert_path(vine_configs.security, tool_config_get_cert());
603         vine_security_set_private_key(vine_configs.security, tool_config_get_private_key());
604         vine_security_set_psk(vine_configs.security, tool_config_get_psk());
605         vine_security_set_tls_version(vine_configs.security, VINE_SECURITY_TLS_VERSION_1_3);
606         vine_security_set_verification_flags(vine_configs.security,
607                         VINE_SECURITY_VERIFICATION_FLAG_ALLOW_SELF_SIGNED
608                         | VINE_SECURITY_VERIFICATION_FLAG_SKIP_HOST_NAME_CHECK); // for local test
609 }
610
611 static void set_vine_configs()
612 {
613         vine_configs.with_ble = tool_config_get_with_ble();
614         vine_configs.is_reg = tool_config_get_register();
615         vine_configs.is_disc = tool_config_get_discovery();
616
617         vine_security_type_e sec_type = _convert_sec_type(tool_config_get_security_type());
618         vine_configs.is_sec = sec_type != VINE_SECURITY_TYPE_NONE ? true : false;
619
620         vine_configs.dp_type = _convert_dp_type(tool_config_get_dp_type());
621         vine_configs.is_dp = vine_configs.dp_type != VINE_DP_TYPE_UNKNOWN ? true : false;
622 }
623
624 static void _event_handler(vine_session_h session)
625 {
626         vine_session_process_event(session);
627 }
628
629 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
630 static void _run_glib_event_loop()
631 {
632         main_loop = g_main_loop_new(NULL, FALSE);
633
634         g_main_loop_run(main_loop);
635         g_main_loop_unref(main_loop);
636 }
637
638 #endif
639
640 void stop_event_loop()
641 {
642 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
643         if (main_loop)
644                 g_main_loop_quit(main_loop);
645 #endif
646         interrupt_flag = 1;
647 }
648
649 static void _run_epoll_event_loop(vine_session_h session)
650 {
651         int fd;
652         int ret = vine_session_get_event_fd(session, &fd);
653         if (ret != VINE_ERROR_NONE)
654                 return;
655
656         epollfd = epoll_create1(0);
657         if (epollfd == -1) {
658                 printf("Fail to create epoll fd %d\n", errno);
659                 exit(1);
660         }
661
662         struct epoll_event ev, events[MAX_EVENTS];
663         ev.events = EPOLLIN;
664         ev.data.ptr = NULL;
665         if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
666                 printf("Fail to add an epoll event for fd %d: %d\n", fd, errno);
667                 exit(1);
668         }
669
670         while (!interrupt_flag) {
671                 int n = epoll_wait(epollfd, events, MAX_EVENTS, 0);
672                 if (n == -1) {
673                         printf("error: epoll_wait %d\n", errno);
674                         exit(1);
675                 }
676
677                 for (int i = 0; i < n; ++i) {
678                         if (events[i].data.ptr)
679                                 _message_timer_handler(events[i].data.ptr);
680                         else
681                                 _event_handler(session);
682                 }
683         }
684         close(epollfd);
685 }
686
687 static void run_event_loop(vine_session_h session)
688 {
689 #ifdef BT_SUPPORT
690         if (vine_configs.with_ble)
691                 _run_glib_event_loop();
692         else
693 #endif
694                 _run_epoll_event_loop(session);
695 }
696
697 int tool_run()
698 {
699         int ret = 0;
700
701         debug_on();
702
703         set_vine_configs();
704
705         if (init() < 0)
706                 goto DONE;
707
708         if (vine_configs.is_reg)
709                 _set_register_info();
710         if (vine_configs.is_disc)
711                 _set_discovery_info();
712         if (vine_configs.is_sec)
713                 _set_security_info(_convert_sec_type(tool_config_get_security_type()));
714         if (vine_configs.is_dp)
715                 _set_dp_info(vine_configs.dp_type);
716
717         if (vine_configs.is_reg) {
718                 ret = vine_session_register(vine_configs.session,
719                                 vine_configs.service, vine_configs.iface);
720                 if (ret != VINE_ERROR_NONE)
721                         goto DONE;
722         }
723
724         if (vine_configs.is_disc) {
725                 ret = vine_session_start_discovery(vine_configs.session,
726                                 vine_configs.type, vine_configs.iface);
727                 if (ret != VINE_ERROR_NONE)
728                         goto DONE;
729         }
730
731         if (vine_configs.is_dp) {
732                 ret = vine_dp_open(vine_configs.dp, __opened_cb, NULL);
733                 if (ret != VINE_ERROR_NONE)
734                         goto DONE;
735         }
736
737         run_event_loop(vine_configs.session);
738
739 DONE:
740         deinit();
741         return ret;
742 }