18 #ifndef PACKAGE_VERSION 19 #define PACKAGE_VERSION "0.9.0" 22 #define PACKAGE_NAME "cmdDC" 24 #ifndef PACKAGE_DESCRIPTION 25 #define PACKAGE_DESCRIPTION "Send Message to Raspberry Pi's on the network." 33 #include <glib-unix.h> 34 #include <gio/gnetworking.h> 37 #ifndef G_OPTION_FLAG_NONE 38 #define G_OPTION_FLAG_NONE 0 42 #define UDP_DISPLAY_COMM_PORT 48029 43 #define UDP_BROADCAST_PORT 48028 44 #define UDP_REGULAR_PORT 48027 45 #define UDP_CLIENTS_PORT 48026 46 #define MS_TEN_MINUTES 600000 47 #define MSG_DELAY_INTERVAL 10 49 #define SZ_TIMESTAMP_BUFF 32 50 #define SZ_PARAMS_BUFF 64 51 #define SZ_RMTADDR_BUFF 256 52 #define SZ_MESSAGE_BUFF 512 53 #define SZ_RESPONSE_BUFF 256 55 #define SZ_CHAR_LABEL 48 56 #define SZ_INFO_BUFF 256 57 #define SZ_CHAR_BUFF 128 58 #define SZ_LINE_BUFF 512 59 #define SZ_COMM_BUFF 256 61 #define SKN_UDP_ANY_PORT 0 62 #define ARY_MAX_INTF 8 63 #define PLATFORM_ERROR -1 140 if (alpha == NULL || strlen(alpha) < 1)
143 int len = strlen(alpha);
148 while ( !g_unichar_isgraph(alpha[end]) && end > 0 ) {
153 while ( !g_unichar_isalnum(alpha[start]) && start < len ) {
156 if (start < len && start > 0) {
158 memmove(&alpha[0], &alpha[start], end);
172 g_warning(
"[REGISTRY] InterfaceName and Address: unable to access information.");
186 struct ifaddrs * ifap;
193 strcpy(paB->
cbName,
"IPBroadcastArray");
196 if (rc == EXIT_FAILURE) {
197 g_warning(
"[REGISTRY] No Default Network Interfaces Found!.");
200 rc = getifaddrs(&ifap);
202 g_warning(
"[REGISTRY] No Network Interfaces Found at All ! %d:%d:%s", rc, errno, strerror(errno) );
208 if (p->ifa_addr != NULL && p->ifa_addr->sa_family == AF_INET && ((p->ifa_flags & IFF_BROADCAST) > 0)) {
210 inet_ntop(p->ifa_addr->sa_family, &((
struct sockaddr_in *) p->ifa_addr)->sin_addr, paB->
ipAddrStr[paB->
count], (
SZ_CHAR_BUFF - 1));
211 inet_ntop(p->ifa_addr->sa_family, &((
struct sockaddr_in *) p->ifa_netmask)->sin_addr, paB->
maskAddrStr[paB->
count], (
SZ_CHAR_BUFF - 1));
250 f_route = fopen(
"/proc/net/route",
"r");
251 if (f_route != NULL) {
253 iName = strtok(line,
"\t");
254 dRoute = strtok(NULL,
"\t");
256 if (iName != NULL && dRoute != NULL) {
257 if (strcmp(dRoute,
"00000000") == 0) {
258 strncpy(pchDefaultInterfaceName, iName, (
SZ_INFO_BUFF - 1));
265 return (EXIT_SUCCESS);
267 g_print(
"[REGISTRY] Opening ProcFs for RouteInfo Failed: %d:%s, Alternate method will be attempted.\n", errno, strerror(errno));
269 f_route = popen(
"route -n get 0.0.0.0",
"r");
270 if (f_route != NULL) {
272 dRoute = strtok(line,
":");
273 iName = strtok(NULL,
"\n");
274 if (strcmp(
skn_strip(dRoute),
"interface") == 0) {
281 return (EXIT_SUCCESS);
283 g_warning(
"[REGISTRY] Alternate method to get RouteInfo Failed: %d:%s", errno, strerror(errno));
284 return (EXIT_FAILURE);
298 struct sockaddr_in remaddr;
299 socklen_t addrlen =
sizeof(remaddr);
300 gchar *request =
"urn:rpilocator - Rpi Where Are You?";
302 gint i_socket = g_socket_get_fd(gSock);
307 for (vIndex = 0; vIndex < paB->
count; vIndex++) {
308 memset(&remaddr, 0,
sizeof(remaddr));
309 remaddr.sin_family = AF_INET;
310 remaddr.sin_addr.s_addr = inet_addr(paB->
broadAddrStr[vIndex]);
313 if (sendto(i_socket, request, strlen(request), 0, (
struct sockaddr *) &remaddr, addrlen) < 0) {
314 g_warning(
"SendTo() Timed out; Failure code=%d, etext=%s", errno, strerror(errno));
324 GDateTime *stamp = g_date_time_new_now_local();
325 gchar *response = g_date_time_format(stamp,
"%F.%T");
335 value =
"There is data to read.";
338 value =
"Data can be written (without blocking).";
341 value =
"There is urgent data to read.";
344 value =
"Error condition.";
347 value =
"Hung up (the connection has been broken, usually for pipes and sockets).";
350 value =
"Invalid request. The file descriptor is not open.";
353 value =
"Unknown GIOCondition!";
370 gboolean final_rc =
FALSE;
371 gchar ** lines = NULL;
372 gchar *current_line = NULL;
373 gchar ** entries = NULL;
374 gchar *current_entry = NULL;
375 gchar ** key_value = NULL;
377 PRegData preg = NULL;
384 if (g_utf8_strchr(response, -1,
'|') == NULL) {
388 lines = g_strsplit_set(response,
"|;%", -1);
389 if ((NULL == lines) || (g_strv_length(lines) < 1)) {
393 a_count = g_strv_length(lines);
394 msgs = g_new0(PRegData, a_count);
395 for(o_index = 0; o_index < a_count; o_index += 1) {
396 msgs[o_index] = g_new0(
RegData, 1);
397 memmove(msgs[o_index], msg,
sizeof(
RegData));
401 current_line = lines[h_index];
402 while ((NULL != current_line) && (h_index < a_count)) {
403 if(g_utf8_strlen(current_line, -1) < 1) {
404 current_line = lines[++h_index];
409 entries = g_strsplit_set(current_line,
",", -1);
410 current_entry = entries[v_index];
411 e_count = g_strv_length(entries);
412 preg = msgs[o_index];
415 while((NULL != current_entry) && (v_index < e_count)) {
416 if(g_utf8_strlen(current_entry, -1) < 1) {
417 current_entry = entries[++v_index];
423 key_value = g_strsplit_set(current_entry,
"=", -1);
424 if((key_value != NULL) && (g_strv_length(key_value) > 0)) {
425 if(g_strrstr(key_value[0],
"a") != NULL) {
426 final_rc = rc =
TRUE;
429 if(g_strrstr(key_value[0],
"i") != NULL) {
430 final_rc = rc =
TRUE;
433 if(g_strrstr(key_value[0],
"o") != NULL) {
434 final_rc = rc =
TRUE;
438 g_strfreev(key_value);
439 current_entry = entries[++v_index];
442 if (rc && (g_utf8_strlen(preg->
ch_ip, -1) > 6)) {
448 current_line = lines[h_index];
453 while(o_index < a_count) {
454 g_free(msgs[o_index]);
455 msgs[o_index++] = NULL;
459 while(o_index < a_count) {
460 g_free(msgs[o_index]);
461 msgs[o_index++] = NULL;
469 GError *error = NULL;
470 gssize gss_receive = 0;
472 gchar * rmtHost = NULL;
473 GSocketAddress *gsRmtAddr = NULL;
474 GInetAddress *gsAddr = NULL;
475 gchar *converted = NULL;
477 if ( NULL == pctrl) {
478 g_message(
"DisplayClient::cb_udp_comm_response_handler(error) Invalid Pointer");
479 return ( G_SOURCE_REMOVE );
482 gss_receive = g_socket_receive_from(gSock, &gsRmtAddr, pctrl->
ch_request,
sizeof(pctrl->
ch_request), NULL, &error);
484 g_error(
"g_socket_receive() => %s", error->message);
485 g_clear_error(&error);
487 if (gss_receive > 0 ) {
489 if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) ) {
490 gsAddr = g_inet_socket_address_get_address( G_INET_SOCKET_ADDRESS(gsRmtAddr) );
491 if ( G_IS_INET_ADDRESS(gsAddr) ) {
492 g_object_ref(gsAddr);
493 rmtHost = g_resolver_lookup_by_address (pctrl->
resolver, gsAddr, NULL, NULL);
494 if (NULL == rmtHost) {
495 rmtHost = g_inet_address_to_string ( gsAddr);
502 converted = g_convert (pctrl->
ch_request, gss_receive,
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
503 if (NULL != converted) {
517 if ( G_IS_INET_ADDRESS(gsAddr) )
518 g_object_unref(gsAddr);
520 if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
521 g_object_unref(gsRmtAddr);
523 return (G_SOURCE_CONTINUE);
527 GError *error = NULL;
529 if ( NULL == pctrl) {
530 g_message(
"DisplayClient::cb_udp_comm_request_handler(error) Invalid Pointer");
531 return ( G_SOURCE_REMOVE );
545 g_error(
"g_socket_send_to() => %s", error->message);
546 g_clear_error(&error);
549 g_message(
"DisplayClient::cb_udp_comm_request_handler(error) Display Service @ %s, Not Responding!", pctrl->
ch_display_service_name);
550 g_main_loop_quit(pctrl->
loop);
551 return ( G_SOURCE_REMOVE );
553 return (G_SOURCE_CONTINUE);
559 return (G_SOURCE_CONTINUE);
563 GError *error = NULL;
564 GSocketAddress *gsRmtAddr = NULL;
565 GInetAddress *gsAddr = NULL;
566 PRegData message = NULL;
569 gchar * rmtHost = NULL;
570 gssize gss_receive = 0;
573 gchar *converted = NULL;
576 if ((condition & G_IO_HUP) || (condition & G_IO_ERR) || (condition & G_IO_NVAL)) {
577 g_message(
"DisplayService::cb_udp_broadcast_response_handler(error) Operational Error / Shutdown Signaled => %s\n",
skn_gio_condition_to_string(condition));
578 g_main_loop_quit(pctrl->
loop);
579 return ( G_SOURCE_REMOVE );
581 if (condition != G_IO_IN) {
583 return (G_SOURCE_CONTINUE);
594 gss_receive = g_socket_receive_from (gSock, &gsRmtAddr, message->
pch_message,
sizeof(message->
pch_message), NULL, &error);
596 g_error(
"g_socket_receive_from() => %s", error->message);
597 g_clear_error(&error);
600 return (G_SOURCE_CONTINUE);
602 if (gss_receive > 0 ) {
603 if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) ) {
604 gsAddr = g_inet_socket_address_get_address( G_INET_SOCKET_ADDRESS(gsRmtAddr) );
605 if ( G_IS_INET_ADDRESS(gsAddr) ) {
606 g_object_ref(gsAddr);
607 rmtHost = g_resolver_lookup_by_address (pctrl->
resolver, gsAddr, NULL, NULL);
608 if (NULL == rmtHost) {
609 rmtHost = g_inet_address_to_string ( gsAddr);
617 converted = g_convert (message->
pch_message, gss_receive,
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
618 if (NULL != converted) {
624 g_utf8_strncpy(message->
ch_from, rmtHost,
sizeof(message->
ch_from));
631 while ( msg != NULL ) {
648 if ( G_IS_INET_ADDRESS(gsAddr) )
649 g_object_unref(gsAddr);
651 if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
652 g_object_unref(gsRmtAddr);
654 return (G_SOURCE_CONTINUE);
658 GError *error = NULL;
659 GInetAddress *anyAddr = NULL;
661 g_return_val_if_fail((NULL != pctrl), G_SOURCE_REMOVE);
663 pctrl->
gSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
665 g_error(
"g_socket_new() => %s", error->message);
666 g_clear_error(&error);
670 anyAddr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
672 g_object_unref(anyAddr);
676 g_error(
"g_socket_bind() => %s", error->message);
677 g_clear_error(&error);
695 return( g_strcmp0(pr->
ch_name, pch_name) );
699 GList *registry = NULL;
700 PRegData preg = NULL;
701 GInetAddress *anyAddr = NULL;
703 g_return_val_if_fail((NULL != pctrl), G_SOURCE_REMOVE);
711 g_print(
"[REGISTRY] Looking for [%s] in Rpi Registry every 30 seconds. StandBy...\n", pctrl->
ch_display_service_name);
715 return (G_SOURCE_CONTINUE);
719 return (G_SOURCE_CONTINUE);
722 preg = registry->data;
725 anyAddr = g_inet_address_new_from_string(preg->
ch_ip);
726 if (NULL == anyAddr) {
727 g_error(
"g_inet_address_new_from_string() Failed => %s, %s", preg->
ch_name, preg->
ch_ip);
728 return(G_SOURCE_CONTINUE);
730 pctrl->
gsDSAddr = g_inet_socket_address_new(anyAddr, g_ascii_strtoll(preg->
ch_port, NULL, 10));
731 g_object_unref(anyAddr);
736 g_print(
"[REGISTRY] FOUND %s on ip %s:%s, sending your message %d seconds.\n\n", preg->
ch_name, preg->
ch_ip, preg->
ch_port, pctrl->
gMsgDelay);
737 return (G_SOURCE_REMOVE);
739 return (G_SOURCE_CONTINUE);
744 g_message(
"DisplayClient::cb_unix_signal_handler() %s Unix Signal Received => Shutdown Initiated!\n", psig->
signalName);
745 g_main_loop_quit(psig->
loop);
746 return ( G_SOURCE_REMOVE );
749 int main(
int argc,
char **argv) {
752 GSource * gBroadSource = NULL;
753 GError *error = NULL;
755 GSocketAddress *gsAddr = NULL;
756 GInetAddress *anyAddr = NULL;
758 gchar * pch_display_service_name = NULL;
759 gchar * pch_message = NULL;
772 cData.
resolver = g_resolver_get_default();
774 GOptionContext *gOptions = NULL;
775 GOptionEntry pgmOptions[] = {
776 {
"display_service_name",
'a',
G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &pch_display_service_name,
"DisplayService Name",
"gtk_display_service"},
777 {
"display_message",
'm',
G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &pch_message,
"Message to send to DisplayService",
"single-quoted-string"},
778 {
"message_interval_delay",
'n',
G_OPTION_FLAG_NONE, G_OPTION_ARG_INT, &cData.
gMsgDelay,
"Send one message every Interval.",
"[1 to 300] seconds, default no-repeat"},
782 gOptions = g_option_context_new (
"UDP message display client for IOT.");
783 g_option_context_add_main_entries (gOptions, pgmOptions, NULL);
784 g_option_context_parse (gOptions, &argc, &argv, &error);
786 g_error(
"g_option_context_parse() => %s", error->message);
787 g_clear_error(&error);
790 g_option_context_free(gOptions);
792 if (NULL == pch_message) {
793 g_utf8_strncpy(cData.
ch_message,
"GTK-+3.0 Rocks with GLIB-2.0 on any platform! (cldc)",
sizeof(cData.
ch_message));
798 if (NULL == pch_display_service_name) {
802 g_free(pch_display_service_name);
810 if (NULL == cData.
paB) {
811 g_error(
"skn_skn_get_default_interface_name_and_ipv4_address() => Unable to discover network interface or non-available.");
819 cData.
gBroadcastSocket = gSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
821 g_error(
"g_socket_new(broadcast) => %s", error->message);
822 g_clear_error(&error);
825 g_socket_set_broadcast(gSock,
TRUE);
827 anyAddr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
829 g_object_unref(anyAddr);
831 g_socket_bind(gSock, gsAddr,
TRUE, &error);
833 g_error(
"g_socket_bind() => %s", error->message);
834 g_clear_error(&error);
838 gBroadSource = g_socket_create_source(gSock, G_IO_IN, NULL);
839 g_source_ref(gBroadSource);
841 g_source_attach (gBroadSource, NULL);
846 g_unix_signal_add (SIGHUP, (GSourceFunc) cb_unix_signal_handler, &cData.
sigHup);
847 g_unix_signal_add (SIGTERM,(GSourceFunc) cb_unix_signal_handler, &cData.
sigTerm);
858 g_main_loop_run(cData.
loop);
861 g_main_loop_unref(cData.
loop);
863 g_source_unref(gBroadSource);
864 g_object_unref(gSock);
865 g_object_unref(gsAddr);
869 g_object_unref(cData.
gSock);
871 g_object_unref(cData.
gsAddr);
875 g_list_free_full(cData.
glRegistry, (GDestroyNotify)g_free);
877 g_message(
"cmdDC: normal shutdown...");
gchar * skn_gio_condition_to_string(GIOCondition condition)
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gchar ch_request[SZ_MESSAGE_BUFF]
gchar * skn_strip(gchar *alpha)
char maskAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
struct _signalData USignalData
gchar ch_ip[SZ_PARAMS_BUFF]
gchar ch_message[SZ_MESSAGE_BUFF]
gchar ch_response[SZ_RESPONSE_BUFF]
GSocket * gBroadcastSocket
static gboolean cb_udp_registry_select_handler(PControlData pctrl)
struct _signalData * PUSignalData
char cbName[SZ_CHAR_BUFF]
struct _ipBroadcastArray * PIPBroadcastArray
gchar ch_port[SZ_PARAMS_BUFF]
#define UDP_BROADCAST_PORT
static gboolean cb_unix_signal_handler(PUSignalData psig)
gchar * skn_get_timestamp()
gint skn_get_default_interface_name(char *pchDefaultInterfaceName)
struct _ipBroadcastArray IPBroadcastArray
gboolean skn_udp_network_broadcast_all_interfaces(GSocket *gSock, PIPBroadcastArray pab)
struct _registryData RegData
struct _controlData * PControlData
GSocketAddress * gsDSAddr
#define G_OPTION_FLAG_NONE
gchar pch_message[SZ_MESSAGE_BUFF]
static gboolean cb_udp_comm_request_handler(PControlData pctrl)
gchar ch_name[SZ_RMTADDR_BUFF]
#define MSG_DELAY_INTERVAL
struct _registryData ** PPRegData
static gboolean cb_udp_comm_response_handler(GSocket *gSock, GIOCondition condition, PControlData pctrl)
gchar ch_this_ip[SZ_RMTADDR_BUFF]
char chDefaultIntfName[SZ_CHAR_BUFF]
static gboolean cb_udp_broadcast_response_handler(GSocket *gSock, GIOCondition condition, PControlData pctrl)
PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address(char *intf, char *ipv4)
struct _registryData * PRegData
struct _controlData ControlData
gchar ch_from[SZ_RMTADDR_BUFF]
gint skn_get_broadcast_ip_array(PIPBroadcastArray paB)
#define SZ_TIMESTAMP_BUFF
gchar ch_timestamp[SZ_TIMESTAMP_BUFF]
gboolean udp_initialize_message_send(PControlData pctrl)
char broadAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
int main(int argc, char **argv)
PPRegData udp_registry_response_parser(PRegData msg, gchar *response)
gint udp_registry_find_by_name(PRegData pr, gchar *pch_name)
gchar ch_intfName[SZ_RMTADDR_BUFF]
gchar ch_display_service_name[SZ_RMTADDR_BUFF]