3 #include "tool_config.h"
8 #include <sys/syscall.h>
9 #include <sys/timerfd.h>
17 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
21 #define RESET_COLOR "\e[m"
22 #define MAKE_RED "\e[31m"
23 #define MAKE_GREEN "\e[32m"
26 #define MAX_READ_LEN 1024
27 #define MAX_WRITE_LEN 300
31 static int epollfd = 0;
32 static FILE *log_file = NULL;
35 vine_session_h session;
36 vine_service_h service;
38 vine_security_h security;
42 vine_dp_type_e dp_type;
59 .dp_type = VINE_DP_TYPE_UNKNOWN,
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;
75 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
76 static GMainLoop *main_loop = NULL;
79 static vine_dp_type_e _convert_dp_type(dp_type_t type)
83 return VINE_DP_TYPE_CLIENT;
85 return VINE_DP_TYPE_SERVER;
87 return VINE_DP_TYPE_PUBSUB;
90 return VINE_DP_TYPE_UNKNOWN;
94 static vine_security_type_e _convert_sec_type(sec_type_t type)
98 return VINE_SECURITY_TYPE_NONE;
100 return VINE_SECURITY_TYPE_TLS;
101 case SEC_TYPE_PSK_OVER_TLS:
102 return VINE_SECURITY_TYPE_PSK_OVER_TLS;
104 return VINE_SECURITY_TYPE_NONE;
108 static vine_address_family_e _convert_addr_family(int family)
112 return VINE_ADDRESS_FAMILY_DEFAULT;
114 return VINE_ADDRESS_FAMILY_IPV4;
116 return VINE_ADDRESS_FAMILY_IPV6;
118 return VINE_ADDRESS_FAMILY_DEFAULT;
123 static void __print_received_data(unsigned char *buf, size_t len)
125 for (int i = 0; i < (int)len; i++)
126 printf("%c", buf[i]);
130 static void __received_cb(vine_dp_h dp, size_t received_len, void *user_data)
132 unsigned char buf[MAX_READ_LEN] = {0, };
135 printf("Message is received. %zd bytes.\n", received_len);
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);
143 static void __terminated_cb(vine_dp_h dp, void *user_data)
145 printf("peer[%p] is terminated.\n", dp);
146 _stop_message_timer(dp);
149 static void __opened_cb(vine_dp_h dp, vine_error_e result, void *user_data)
151 printf("DP %s.\n", result == VINE_ERROR_NONE ? "is opened" : "open failure");
152 if (result != VINE_ERROR_NONE)
155 vine_address_family_e addr_family;
160 if (vine_configs.dp_type == VINE_DP_TYPE_PUBSUB) {
161 vine_dp_get_id(dp, &id);
162 printf("\t> ID: %s\n", id);
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",
169 vine_dp_get_ip(dp, &addr_family, &ip);
170 printf("\t> local IP: %s, address family: %d \n", ip, addr_family);
174 vine_dp_set_received_cb(dp, __received_cb, NULL);
175 vine_dp_set_terminated_cb(dp, __terminated_cb, NULL);
177 if (result == VINE_ERROR_NONE
178 && vine_configs.dp_type == VINE_DP_TYPE_CLIENT
179 && (vine_configs.msg || vine_configs.file))
183 static void __accepted_cb(vine_dp_h dp, vine_dp_h accepted_dp, void *user_data)
185 vine_address_family_e addr_family;
189 vine_dp_get_remote_port(accepted_dp, &port);
190 printf("client is accepted.\n");
191 printf("\t> client port: %d\n", port);
193 vine_dp_get_ip(accepted_dp, &addr_family, &ip);
194 printf("\t> used local IP: %s, address family: %d\n", ip, addr_family);
197 vine_dp_set_received_cb(accepted_dp, __received_cb, NULL);
198 vine_dp_set_terminated_cb(accepted_dp, __terminated_cb, NULL);
200 if (vine_configs.msg || vine_configs.file)
201 send_message(accepted_dp);
204 static void __peer_joined_cb(vine_dp_h dp, const char *peer_id, void *user_data)
206 printf("pubsub peer(%s) is joined.\n", peer_id);
208 // if joined_peer is larger than 1,
209 // this means message timer has already runned.
210 if (joined_peer == 1)
214 static void __peer_left_cb(vine_dp_h dp, const char *peer_id, void *user_data)
216 printf("pubsub peer(%s) is left.\n", peer_id);
218 if (joined_peer == 0)
219 _stop_message_timer(dp);
222 static void __registered_cb(vine_session_h session,
223 const char *service_name, vine_error_e error, void *user_data)
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");
231 printf("registration failure.\n");
234 static bool __print_attr(const char *key, const char *value, void *user_data)
236 printf("\t > Attributes: %s=%s\n", key, value);
240 static void __ip_resolved_cb(vine_session_h session, vine_service_h service,
241 const char *ip, vine_address_family_e address_family,
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);
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);
264 static void __ble_service_discovered(vine_session_h session, vine_service_h service,
265 vine_service_state_e state, void *user_data)
267 printf("available[%d]\n", state);
268 printf("Service discovered.\n");
273 vine_service_get_type(service, &service_type);
274 vine_service_get_name(service, &service_name);
275 vine_service_get_mac(service, &mac);
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);
287 vine_session_stop_discovery(session);
290 static void __discovered_cb(vine_session_h session, vine_service_h service,
291 vine_service_state_e state, void *user_data)
293 if (vine_configs.with_ble) {
294 __ble_service_discovered(session, service, state, user_data);
298 printf("available[%d]\n", state);
300 vine_service_clone(service, &s);
302 vine_session_set_ip_resolved_cb(session, s,
303 _convert_addr_family(tool_config_get_address_family()),
304 __ip_resolved_cb, NULL);
307 static void _start_message_timer(vine_dp_h dp, int sec)
312 int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
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) {
326 timerfds.insert(std::make_pair(dp, timerfd));
327 struct epoll_event ev;
329 ev.data.ptr = (void *)dp;
330 epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &ev);
333 static void _stop_message_timer(vine_dp_h dp)
335 auto it = timerfds.find(dp);
336 if (it == timerfds.end())
339 int timerfd = it->second;
346 int expired = read(timerfd, &buf, sizeof(uint64_t));
347 if (expired != sizeof(uint64_t))
348 printf("expired[%d]. operation failed.\n", expired);
350 epoll_ctl(epollfd, EPOLL_CTL_DEL, timerfd, NULL);
355 static void _stop_message_timer_all()
357 for (auto &it : timerfds) {
365 static void _message_timer_handler(void *user_data)
367 vine_dp_h dp = (vine_dp_h) user_data;
368 _stop_message_timer(dp);
372 static int _send_message_from_file(vine_dp_h dp)
377 int ret = VINE_ERROR_NONE;
378 FILE *file = fopen(vine_configs.file, "r");
383 fseek(file, 0, SEEK_END);
386 if (size < 0 || size >= INT_MAX - 1) {
390 buf = (unsigned char *)calloc(sizeof(unsigned char), size);
392 fseek(file, 0, SEEK_SET);
393 count = fread(buf, sizeof(unsigned char), size, file);
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);
403 printf("Failed to send a message.\n");
414 static int _send_message(vine_dp_h dp)
416 size_t len = strlen(vine_configs.msg);
420 unsigned char *buf = (unsigned char *)calloc(len, sizeof(unsigned char));
421 memcpy(buf, vine_configs.msg, len);
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);
429 static int send_message(vine_dp_h dp)
431 int ret = VINE_ERROR_NONE;
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;
442 if(vine_configs.with_ble) {
443 if (vine_set_event_loop(VINE_EVENT_LOOP_EXTERNAL_GLIB) != VINE_ERROR_NONE)
447 int ret = vine_initialize();
448 if (ret != VINE_ERROR_NONE)
451 ret = vine_session_create(&vine_configs.session);
452 if (ret != VINE_ERROR_NONE)
455 if(vine_configs.with_ble)
456 vine_session_set_discovery_method(vine_configs.session, VINE_DISCOVERY_METHOD_BLE);
463 tool_config_deinit();
465 _stop_message_timer_all();
467 if (vine_configs.is_reg)
468 vine_session_unregister(vine_configs.session);
470 if (vine_configs.is_disc)
471 vine_session_stop_discovery(vine_configs.session);
473 if (vine_configs.is_dp)
474 vine_dp_close(vine_configs.dp);
476 if (vine_configs.security)
477 vine_security_destroy(vine_configs.security);
480 vine_dp_destroy(vine_configs.dp);
482 if (vine_configs.service)
483 vine_service_destroy(vine_configs.service);
485 if (vine_configs.session)
486 vine_session_destroy(vine_configs.session);
496 static void _logger(int log_level, const char *log)
499 if(clock_gettime(CLOCK_REALTIME, &ts) == -1 )
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));
507 fprintf(log_file, "%s %s\n", stamp, log);
510 printf("%s ", stamp);
519 printf(MAKE_RED "ERROR: ");
522 printf("%s" RESET_COLOR "\n", log);
525 static void debug_on()
527 if (!tool_config_get_verbose())
530 vine_set_log_level(VINE_LOG_ERROR | VINE_LOG_INFO | VINE_LOG_DEBUG);
532 const char *log_file_path = tool_config_get_log_file();
534 log_file = fopen(log_file_path, "w+");
536 vine_set_logger(_logger);
539 static void _set_register_info()
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);
548 static void _set_discovery_info()
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);
555 static void _set_dp_info(vine_dp_type_e type)
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());
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());
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);
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);
578 vine_dp_set_port(vine_configs.dp, tool_config_get_port());
581 if (type == VINE_DP_TYPE_SERVER)
582 vine_dp_set_accepted_cb(vine_configs.dp, __accepted_cb, NULL);
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);
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);
597 static void _set_security_info(vine_security_type_e type)
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
611 static void set_vine_configs()
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();
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;
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;
624 static void _event_handler(vine_session_h session)
626 vine_session_process_event(session);
629 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
630 static void _run_glib_event_loop()
632 main_loop = g_main_loop_new(NULL, FALSE);
634 g_main_loop_run(main_loop);
635 g_main_loop_unref(main_loop);
640 void stop_event_loop()
642 #ifdef USE_VINE_EVENT_LOOP_EXTERNAL_GLIB
644 g_main_loop_quit(main_loop);
649 static void _run_epoll_event_loop(vine_session_h session)
652 int ret = vine_session_get_event_fd(session, &fd);
653 if (ret != VINE_ERROR_NONE)
656 epollfd = epoll_create1(0);
658 printf("Fail to create epoll fd %d\n", errno);
662 struct epoll_event ev, events[MAX_EVENTS];
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);
670 while (!interrupt_flag) {
671 int n = epoll_wait(epollfd, events, MAX_EVENTS, 0);
673 printf("error: epoll_wait %d\n", errno);
677 for (int i = 0; i < n; ++i) {
678 if (events[i].data.ptr)
679 _message_timer_handler(events[i].data.ptr);
681 _event_handler(session);
687 static void run_event_loop(vine_session_h session)
690 if (vine_configs.with_ble)
691 _run_glib_event_loop();
694 _run_epoll_event_loop(session);
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);
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)
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)
731 if (vine_configs.is_dp) {
732 ret = vine_dp_open(vine_configs.dp, __opened_cb, NULL);
733 if (ret != VINE_ERROR_NONE)
737 run_event_loop(vine_configs.session);