19 #ifndef PACKAGE_VERSION 20 #define PACKAGE_VERSION "0.9.0" 23 #define PACKAGE_NAME "cmdDS" 25 #ifndef PACKAGE_DESCRIPTION 26 #define PACKAGE_DESCRIPTION "Display Messages from other 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 41 #define UDP_COMM_PORT 48029 42 #define UDP_BROADCAST_PORT 48028 43 #define UDP_REGULAR_PORT 48027 44 #define MS_TEN_MINUTES 600000 46 #define SZ_TIMESTAMP_BUFF 32 47 #define SZ_PARAMS_BUFF 64 48 #define SZ_RMTADDR_BUFF 256 49 #define SZ_MESSAGE_BUFF 512 50 #define SZ_RESPONSE_BUFF 256 52 #define SZ_CHAR_LABEL 48 53 #define SZ_INFO_BUFF 256 54 #define SZ_CHAR_BUFF 128 55 #define SZ_LINE_BUFF 512 56 #define SZ_COMM_BUFF 256 58 #define SKN_UDP_ANY_PORT 0 59 #define ARY_MAX_INTF 8 60 #define PLATFORM_ERROR -1 125 if (alpha == NULL || strlen(alpha) < 1)
128 int len = strlen(alpha);
133 while ( !g_unichar_isgraph(alpha[end]) && end > 0 ) {
138 while ( !g_unichar_isalnum(alpha[start]) && start < len ) {
141 if (start < len && start > 0) {
143 memmove(&alpha[0], &alpha[start], end);
157 g_warning(
"[REGISTRY] InterfaceName and Address: unable to access information.");
171 struct ifaddrs * ifap;
178 strcpy(paB->
cbName,
"IPBroadcastArray");
181 if (rc == EXIT_FAILURE) {
182 g_warning(
"[REGISTRY] No Default Network Interfaces Found!.");
185 rc = getifaddrs(&ifap);
187 g_warning(
"[REGISTRY] No Network Interfaces Found at All ! %d:%d:%s", rc, errno, strerror(errno) );
193 if (p->ifa_addr != NULL && p->ifa_addr->sa_family == AF_INET && ((p->ifa_flags & IFF_BROADCAST) > 0)) {
195 inet_ntop(p->ifa_addr->sa_family, &((
struct sockaddr_in *) p->ifa_addr)->sin_addr, paB->
ipAddrStr[paB->
count], (
SZ_CHAR_BUFF - 1));
196 inet_ntop(p->ifa_addr->sa_family, &((
struct sockaddr_in *) p->ifa_netmask)->sin_addr, paB->
maskAddrStr[paB->
count], (
SZ_CHAR_BUFF - 1));
235 f_route = fopen(
"/proc/net/route",
"r");
236 if (f_route != NULL) {
238 iName = strtok(line,
"\t");
239 dRoute = strtok(NULL,
"\t");
241 if (iName != NULL && dRoute != NULL) {
242 if (strcmp(dRoute,
"00000000") == 0) {
243 strncpy(pchDefaultInterfaceName, iName, (
SZ_INFO_BUFF - 1));
250 return (EXIT_SUCCESS);
252 g_print(
"[REGISTRY] Opening ProcFs for RouteInfo Failed: %d:%s, Alternate method will be attempted.", errno, strerror(errno));
254 f_route = popen(
"route -n get 0.0.0.0",
"r");
255 if (f_route != NULL) {
257 dRoute = strtok(line,
":");
258 iName = strtok(NULL,
"\n");
259 if (strcmp(
skn_strip(dRoute),
"interface") == 0) {
266 return (EXIT_SUCCESS);
268 g_warning(
"[REGISTRY] Alternate method to get RouteInfo Failed: %d:%s", errno, strerror(errno));
269 return (EXIT_FAILURE);
283 struct sockaddr_in remaddr;
284 socklen_t addrlen =
sizeof(remaddr);
285 gchar *request =
"urn:rpilocator - Rpi Where Are You?";
287 gint i_socket = g_socket_get_fd(gSock);
291 for (vIndex = 0; vIndex < paB->
count; vIndex++) {
292 memset(&remaddr, 0,
sizeof(remaddr));
293 remaddr.sin_family = AF_INET;
294 remaddr.sin_addr.s_addr = inet_addr(paB->
broadAddrStr[vIndex]);
297 if (sendto(i_socket, request, strlen(request), 0, (
struct sockaddr *) &remaddr, addrlen) < 0) {
298 g_warning(
"SendTo() Timed out; Failure code=%d, etext=%s", errno, strerror(errno));
308 g_message(
"DisplayService::cb_unix_signal_handler() %s Unix Signal Received => Shutdown Initiated!\n", psig->
signalName);
309 g_main_loop_quit(psig->
loop);
310 return ( G_SOURCE_REMOVE );
313 GDateTime *stamp = g_date_time_new_now_local();
314 gchar *response = g_date_time_format(stamp,
"%F.%T");
331 gboolean final_rc =
FALSE;
332 gchar ** lines = NULL;
333 gchar *current_line = NULL;
334 gchar ** entries = NULL;
335 gchar *current_entry = NULL;
336 gchar ** key_value = NULL;
338 PRegData preg = NULL;
345 if (g_utf8_strchr(response, -1,
'|') == NULL) {
349 lines = g_strsplit_set(response,
"|;%", -1);
350 if ((NULL == lines) || (g_strv_length(lines) < 1)) {
354 a_count = g_strv_length(lines);
355 msgs = g_new0(PRegData, a_count);
356 for(o_index = 0; o_index < a_count; o_index += 1) {
357 msgs[o_index] = g_new0(
RegData, 1);
358 memmove(msgs[o_index], msg,
sizeof(
RegData));
362 current_line = lines[h_index];
363 while ((NULL != current_line) && (h_index < a_count)) {
364 if(g_utf8_strlen(current_line, -1) < 1) {
365 current_line = lines[++h_index];
370 entries = g_strsplit_set(current_line,
",", -1);
371 current_entry = entries[v_index];
372 e_count = g_strv_length(entries);
373 preg = msgs[o_index];
376 while((NULL != current_entry) && (v_index < e_count)) {
377 if(g_utf8_strlen(current_entry, -1) < 1) {
378 current_entry = entries[++v_index];
384 key_value = g_strsplit_set(current_entry,
"=", -1);
385 if((key_value != NULL) && (g_strv_length(key_value) > 0)) {
386 if(g_strrstr(key_value[0],
"a") != NULL) {
387 final_rc = rc =
TRUE;
390 if(g_strrstr(key_value[0],
"i") != NULL) {
391 final_rc = rc =
TRUE;
394 if(g_strrstr(key_value[0],
"o") != NULL) {
395 final_rc = rc =
TRUE;
399 g_strfreev(key_value);
400 current_entry = entries[++v_index];
403 if (rc && (g_utf8_strlen(preg->
ch_ip, -1) > 6)) {
409 current_line = lines[h_index];
414 while(o_index < a_count) {
415 g_free(msgs[o_index]);
416 msgs[o_index++] = NULL;
420 while(o_index < a_count) {
421 g_free(msgs[o_index]);
422 msgs[o_index++] = NULL;
430 GError *error = NULL;
431 GSocketAddress *gsRmtAddr = NULL;
432 GInetAddress *gsAddr = NULL;
433 gchar * rmtHost = NULL;
435 gssize gss_receive = 0;
437 if ((condition & G_IO_HUP) || (condition & G_IO_ERR) || (condition & G_IO_NVAL)) {
439 g_main_loop_quit(pctrl->
loop);
440 return ( G_SOURCE_REMOVE );
442 if (condition != G_IO_IN) {
444 return (G_SOURCE_CONTINUE);
450 gss_receive = g_socket_receive_from (gSock, &gsRmtAddr, pctrl->
ch_read,
sizeof(pctrl->
ch_read), NULL, &error);
452 g_error(
"g_socket_receive_from() => %s", error->message);
453 g_clear_error(&error);
454 return (G_SOURCE_CONTINUE);
456 if (gss_receive > 0 ) {
457 if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) ) {
458 gsAddr = g_inet_socket_address_get_address( G_INET_SOCKET_ADDRESS(gsRmtAddr) );
459 if ( G_IS_INET_ADDRESS(gsAddr) ) {
460 g_object_ref(gsAddr);
461 rmtHost = g_resolver_lookup_by_address (pctrl->
resolver, gsAddr, NULL, NULL);
462 if (NULL == rmtHost) {
463 rmtHost = g_inet_address_to_string ( gsAddr);
467 pctrl->
ch_read[gss_receive] = 0;
478 g_error(
"g_socket_send_to() => %s", error->message);
479 g_clear_error(&error);
485 if ( G_IS_INET_ADDRESS(gsAddr) )
486 g_object_unref(gsAddr);
488 if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
489 g_object_unref(gsRmtAddr);
492 return (G_SOURCE_CONTINUE);
496 GError *error = NULL;
497 GSocketAddress *gsRmtAddr = NULL;
498 GInetAddress *gsAddr = NULL;
499 PRegData message = NULL;
502 gchar * rmtHost = NULL;
503 gssize gss_receive = 0;
507 gchar *converted = NULL;
509 if ((condition & G_IO_HUP) || (condition & G_IO_ERR) || (condition & G_IO_NVAL)) {
510 g_message(
"DisplayService::cb_udp_broadcast_response_handler(error) Operational Error / Shutdown Signaled => %s\n",
skn_gio_condition_to_string(condition));
511 g_main_loop_quit(pctrl->
loop);
512 return ( G_SOURCE_REMOVE );
514 if (condition != G_IO_IN) {
516 return (G_SOURCE_CONTINUE);
527 gss_receive = g_socket_receive_from (gSock, &gsRmtAddr, message->
ch_message,
sizeof(message->
ch_message), NULL, &error);
529 g_error(
"g_socket_receive_from() => %s", error->message);
530 g_clear_error(&error);
533 return (G_SOURCE_CONTINUE);
535 if (gss_receive > 0 ) {
536 if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) ) {
537 gsAddr = g_inet_socket_address_get_address( G_INET_SOCKET_ADDRESS(gsRmtAddr) );
538 if ( G_IS_INET_ADDRESS(gsAddr) ) {
539 g_object_ref(gsAddr);
540 rmtHost = g_resolver_lookup_by_address (pctrl->
resolver, gsAddr, NULL, NULL);
541 if (NULL == rmtHost) {
542 rmtHost = g_inet_address_to_string ( gsAddr);
550 converted = g_convert (message->
ch_message, gss_receive,
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
551 if (NULL != converted) {
557 g_utf8_strncpy(message->
ch_from, rmtHost,
sizeof(message->
ch_from));
564 while ( msg != NULL ) {
577 g_snprintf(response,
sizeof(response),
578 "name=rpi_locator_service,ip=%s,port=48028|name=%s,ip=%s,port=%d|",
582 g_socket_send_to (gSock, gsRmtAddr, response, strlen(response), NULL, &error);
584 g_error(
"g_socket_send_to() => %s", error->message);
586 g_clear_error(&error);
593 if ( G_IS_INET_ADDRESS(gsAddr) )
594 g_object_unref(gsAddr);
596 if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
597 g_object_unref(gsRmtAddr);
599 return (G_SOURCE_CONTINUE);
608 value =
"There is data to read.";
611 value =
"Data can be written (without blocking).";
614 value =
"There is urgent data to read.";
617 value =
"Error condition.";
620 value =
"Hung up (the connection has been broken, usually for pipes and sockets).";
623 value =
"Invalid request. The file descriptor is not open.";
626 value =
"Unknown GIOCondition!";
632 int main(
int argc,
char **argv) {
634 GError *error = NULL;
635 GSocket *gSock = NULL;
636 GSocketAddress *gsAddr = NULL;
637 GInetAddress *anyAddr = NULL;
638 GSource * gSource = NULL;
639 GSocketAddress *gbAddr = NULL;
640 GSource * gBroadSource = NULL;
643 PIPBroadcastArray paB = NULL;
651 GOptionContext *gOptions = NULL;
652 GOptionEntry pgmOptions[] = {
654 {
"udp_port_number",
'p',
G_OPTION_FLAG_NONE, G_OPTION_ARG_INT, &gUDPPort,
"UDP Port Number to listen on.",
"port number defaults to 48029"},
660 gOptions = g_option_context_new (
"UDP message display service for IOT.");
661 g_option_context_add_main_entries (gOptions, pgmOptions, NULL);
663 g_option_context_parse (gOptions, &argc, &argv, &error);
665 g_error(
"g_option_context_parse() => %s", error->message);
666 g_clear_error(&error);
669 g_option_context_free(gOptions);
683 g_error(
"skn_skn_get_default_interface_name_and_ipv4_address() => Unable to discover network interface or non-available.");
692 cData.
resolver = g_resolver_get_default();
694 gSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
696 g_error(
"g_socket_new() => %s", error->message);
697 g_clear_error(&error);
701 anyAddr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
702 gsAddr = g_inet_socket_address_new(anyAddr, gUDPPort);
704 g_socket_bind(gSock, gsAddr,
TRUE, &error);
706 g_error(
"g_socket_bind() => %s", error->message);
707 g_clear_error(&error);
713 cData.
gbSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
715 g_error(
"g_socket_new(broadcast) => %s", error->message);
716 g_clear_error(&error);
722 g_object_unref(anyAddr);
724 g_socket_bind(cData.
gbSock, gbAddr,
TRUE, &error);
726 g_error(
"g_socket_bind() => %s", error->message);
727 g_clear_error(&error);
733 gSource = g_socket_create_source (gSock, G_IO_IN, NULL);
735 cData.
gSourceId = gSourceId = g_source_attach (gSource, NULL);
737 gBroadSource = g_socket_create_source(cData.
gbSock, G_IO_IN, NULL);
738 g_source_ref(gBroadSource);
740 g_source_attach (gBroadSource, NULL);
745 g_unix_signal_add (SIGHUP, (GSourceFunc) cb_unix_signal_handler, &sigHup);
746 g_unix_signal_add (SIGTERM,(GSourceFunc) cb_unix_signal_handler, &sigTerm);
752 g_message(
"cmdDS: Ready to do Good, on %s:%s:%d...\n", cData.
ch_intfName, cData.
ch_this_ip, gUDPPort);
754 g_main_loop_run(cData.
loop);
757 g_main_loop_unref(cData.
loop);
759 g_source_unref(gBroadSource);
760 g_source_unref(gSource);
761 g_object_unref(cData.
gbSock);
762 g_object_unref(gSock);
763 g_object_unref(gbAddr);
764 g_object_unref(gsAddr);
767 g_message(
"cmdDS: normal shutdown...");
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gchar ch_request[SZ_MESSAGE_BUFF]
struct _signalData USignalData
char maskAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gchar ch_ip[SZ_PARAMS_BUFF]
gchar ch_response[SZ_RESPONSE_BUFF]
gchar ch_message[SZ_MESSAGE_BUFF]
struct _signalData * PUSignalData
char cbName[SZ_CHAR_BUFF]
static gboolean cb_udp_request_handler(GSocket *socket, GIOCondition condition, PControlData pctrl)
struct _ipBroadcastArray * PIPBroadcastArray
gchar ch_port[SZ_PARAMS_BUFF]
#define UDP_BROADCAST_PORT
static gboolean cb_unix_signal_handler(PUSignalData psig)
gchar * skn_gio_condition_to_string(GIOCondition condition)
gint skn_get_default_interface_name(char *pchDefaultInterfaceName)
gboolean skn_udp_network_broadcast_all_interfaces(GSocket *gSock, PIPBroadcastArray pab)
struct _ipBroadcastArray IPBroadcastArray
struct _registryData RegData
struct _controlData * PControlData
#define G_OPTION_FLAG_NONE
gchar ch_name[SZ_RMTADDR_BUFF]
struct _registryData ** PPRegData
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 * skn_get_timestamp()
gchar ch_timestamp[SZ_TIMESTAMP_BUFF]
char broadAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gchar * skn_strip(gchar *alpha)
int main(int argc, char **argv)
PPRegData udp_registry_response_parser(PRegData msg, gchar *response)
gchar ch_intfName[SZ_RMTADDR_BUFF]
gchar ch_read[SZ_MESSAGE_BUFF]