RPi Locator and Display Services
gssdpDC.c File Reference
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <gio/gio.h>
#include <libgssdp/gssdp.h>
#include <glib-unix.h>
#include <gio/gnetworking.h>
#include <ifaddrs.h>
+ Include dependency graph for gssdpDC.c:

Go to the source code of this file.

Data Structures

struct  _ipBroadcastArray
 
struct  _signalData
 
struct  _registryData
 
struct  _gssdpRegistryData
 
struct  _controlData
 

Macros

#define PACKAGE_VERSION   "0.9.0"
 
#define PACKAGE_NAME   "gssdpDC"
 
#define PACKAGE_DESCRIPTION   "Send Message to Raspberry Pi's on the network."
 
#define G_OPTION_FLAG_NONE   0
 
#define UDP_DISPLAY_COMM_PORT   48029
 
#define UDP_BROADCAST_PORT   48028
 
#define UDP_REGULAR_PORT   48027
 
#define UDP_CLIENTS_PORT   48026
 
#define MS_TEN_MINUTES   600000
 
#define MSG_DELAY_INTERVAL   10
 
#define SZ_TIMESTAMP_BUFF   32
 
#define SZ_PARAMS_BUFF   64
 
#define SZ_RMTADDR_BUFF   256
 
#define SZ_MESSAGE_BUFF   512
 
#define SZ_RESPONSE_BUFF   256
 
#define SZ_CHAR_LABEL   48
 
#define SZ_INFO_BUFF   256
 
#define SZ_CHAR_BUFF   128
 
#define SZ_LINE_BUFF   512
 
#define SZ_COMM_BUFF   256
 
#define SKN_UDP_ANY_PORT   0
 
#define ARY_MAX_INTF   8
 
#define PLATFORM_ERROR   -1
 

Typedefs

typedef struct _ipBroadcastArray IPBroadcastArray
 
typedef struct _ipBroadcastArrayPIPBroadcastArray
 
typedef struct _signalData USignalData
 
typedef struct _signalDataPUSignalData
 
typedef struct _registryData RegData
 
typedef struct _registryDataPRegData
 
typedef struct _registryData ** PPRegData
 
typedef struct _gssdpRegistryData GSSDPRegData
 
typedef struct _gssdpRegistryDataPGSSDPRegData
 
typedef struct _controlData ControlData
 
typedef struct _controlDataPControlData
 

Functions

gboolean skn_gssdp_browse (PControlData pctrl)
 
static void cb_gssdp_resource_available (GSSDPResourceBrowser *resource_browser, const char *usn, GList *locations, PControlData pctrl)
 
gchar * skn_get_timestamp ()
 
gint udp_registry_find_by_name (PGSSDPRegData pr, gchar *pch_name)
 
gchar * skn_gio_condition_to_string (GIOCondition condition)
 
gboolean udp_initialize_message_send (PControlData pctrl)
 
static gboolean cb_unix_signal_handler (PUSignalData psig)
 
static gboolean cb_udp_comm_request_handler (PControlData pctrl)
 
static gboolean cb_udp_comm_response_handler (GSocket *gSock, GIOCondition condition, PControlData pctrl)
 
static gboolean cb_udp_registry_select_handler (PControlData pctrl)
 
PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address (char *intf, char *ipv4)
 
gint skn_get_broadcast_ip_array (PIPBroadcastArray paB)
 
gint skn_get_default_interface_name (char *pchDefaultInterfaceName)
 
gchar * skn_strip (gchar *alpha)
 
PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address (gchar *intf, gchar *ipv4)
 
int main (int argc, char **argv)
 

Macro Definition Documentation

#define ARY_MAX_INTF   8

Definition at line 63 of file gssdpDC.c.

Referenced by skn_get_broadcast_ip_array().

#define G_OPTION_FLAG_NONE   0

Definition at line 39 of file gssdpDC.c.

Referenced by main().

#define MS_TEN_MINUTES   600000

Definition at line 47 of file gssdpDC.c.

#define MSG_DELAY_INTERVAL   10

Definition at line 48 of file gssdpDC.c.

Referenced by main().

#define PACKAGE_DESCRIPTION   "Send Message to Raspberry Pi's on the network."

Definition at line 25 of file gssdpDC.c.

#define PACKAGE_NAME   "gssdpDC"

Definition at line 22 of file gssdpDC.c.

#define PACKAGE_VERSION   "0.9.0"

gssdpDC.c IOT/RaspberryPi message display client gcc -v pkg-config --cflags --libs glib-2.0 gio-2.0 -O3 -Wall -o gssdpDC gssdpDC.c

Program Flow:

  1. Initialize -> parse_options
  2. gssdp_browser -> loop ->
  1. udp_timeout -> loop -> find_display_service_in_registry -> intialize_message_sender
  2. upd_socket -> loop -> receive_message -> log_to__console
  1. unix_signal -> loop -> close_loop
  2. Cleanup -> exit

Definition at line 19 of file gssdpDC.c.

#define PLATFORM_ERROR   -1
#define SKN_UDP_ANY_PORT   0

Definition at line 62 of file gssdpDC.c.

Referenced by udp_initialize_message_send().

#define SZ_CHAR_BUFF   128
#define SZ_CHAR_LABEL   48

Definition at line 56 of file gssdpDC.c.

#define SZ_COMM_BUFF   256

Definition at line 60 of file gssdpDC.c.

#define SZ_INFO_BUFF   256

Definition at line 57 of file gssdpDC.c.

Referenced by skn_get_default_interface_name().

#define SZ_LINE_BUFF   512

Definition at line 59 of file gssdpDC.c.

#define SZ_MESSAGE_BUFF   512

Definition at line 53 of file gssdpDC.c.

#define SZ_PARAMS_BUFF   64

Definition at line 51 of file gssdpDC.c.

#define SZ_RESPONSE_BUFF   256

Definition at line 54 of file gssdpDC.c.

#define SZ_RMTADDR_BUFF   256

Definition at line 52 of file gssdpDC.c.

#define SZ_TIMESTAMP_BUFF   32

Definition at line 50 of file gssdpDC.c.

#define UDP_BROADCAST_PORT   48028

Definition at line 44 of file gssdpDC.c.

#define UDP_CLIENTS_PORT   48026

Definition at line 46 of file gssdpDC.c.

#define UDP_DISPLAY_COMM_PORT   48029

Definition at line 43 of file gssdpDC.c.

#define UDP_REGULAR_PORT   48027

Definition at line 45 of file gssdpDC.c.

Typedef Documentation

typedef struct _controlData ControlData
typedef struct _controlData * PControlData
typedef struct _registryData ** PPRegData
typedef struct _registryData * PRegData
typedef struct _signalData * PUSignalData
typedef struct _registryData RegData
typedef struct _signalData USignalData

Function Documentation

static void cb_gssdp_resource_available ( GSSDPResourceBrowser *  resource_browser,
const char *  usn,
GList *  locations,
PControlData  pctrl 
)
static

Definition at line 529 of file gssdpDC.c.

References _gssdpRegistryData::ch_location, _gssdpRegistryData::ch_status, _gssdpRegistryData::ch_timestamp, _gssdpRegistryData::ch_urn, _controlData::glRegistry, and skn_get_timestamp().

Referenced by skn_gssdp_browse().

529  {
530  PGSSDPRegData msg = NULL;
531  gchar *stamp = skn_get_timestamp();
532  gchar *converted = NULL;
533 
534  g_warn_if_fail(NULL != pctrl);
535 
536  msg = g_new0(GSSDPRegData, 1);
537 
538  g_utf8_strncpy(msg->ch_timestamp, stamp, sizeof(msg->ch_timestamp));
539  g_free(stamp);
540 
541  /* Convert to UTF8 */
542  converted = g_convert (usn, g_utf8_strlen(usn, -1), "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
543  if (NULL != converted) {
544  g_utf8_strncpy(msg->ch_urn, converted, sizeof(msg->ch_urn));
545  g_free(converted);
546  } else {
547  g_utf8_strncpy(msg->ch_urn, usn, sizeof(msg->ch_urn));
548  }
549 
550  converted = g_convert (locations->data, g_utf8_strlen(locations->data, -1), "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
551  if (NULL != converted) {
552  g_utf8_strncpy(msg->ch_location, converted, sizeof(msg->ch_location));
553  g_free(converted);
554  } else {
555  g_utf8_strncpy(msg->ch_location, locations->data, sizeof(msg->ch_location));
556  }
557 
558  g_utf8_strncpy(msg->ch_status, "Available", sizeof(msg->ch_status));
559 
560  g_print("[%s]GSSDP %s, %s, %s\n", msg->ch_timestamp, msg->ch_urn, msg->ch_location, msg->ch_status);
561 
562  pctrl->glRegistry = g_list_prepend(pctrl->glRegistry, msg);
563 }
gchar ch_timestamp[SZ_TIMESTAMP_BUFF]
Definition: gssdpDC.c:92
gchar ch_status[SZ_PARAMS_BUFF]
Definition: gssdpDC.c:95
gchar * skn_get_timestamp()
Definition: gssdpDC.c:300
gchar ch_urn[SZ_RMTADDR_BUFF]
Definition: gssdpDC.c:93
GList * glRegistry
Definition: cmdDC.c:101
gchar ch_location[SZ_RMTADDR_BUFF]
Definition: gssdpDC.c:94

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static gboolean cb_udp_comm_request_handler ( PControlData  pctrl)
static

Definition at line 401 of file gssdpDC.c.

References _controlData::ch_display_service_name, _controlData::ch_message, _controlData::gErrorCount, _controlData::gsDSAddr, _controlData::gSock, and _controlData::loop.

Referenced by udp_initialize_message_send().

401  {
402  GError *error = NULL;
403 
404  if ( NULL == pctrl) { /* SHUTDOWN THE MAIN LOOP */
405  g_message("DisplayClient::cb_udp_comm_request_handler(error) Invalid Pointer");
406  return ( G_SOURCE_REMOVE );
407  }
408 
409  g_socket_send_to (pctrl->gSock, pctrl->gsDSAddr, pctrl->ch_message, strlen(pctrl->ch_message), NULL, &error);
410  if (error != NULL) { // gss_send = Number of bytes written (which may be less than size ), or -1 on error
411  g_error("g_socket_send_to() => %s", error->message);
412  g_clear_error(&error);
413  pctrl->gErrorCount += 1;
414  if(pctrl->gErrorCount > 10) {
415  g_message("DisplayClient::cb_udp_comm_request_handler(error) Display Service @ %s, Not Responding!", pctrl->ch_display_service_name);
416  g_main_loop_quit(pctrl->loop);
417  return ( G_SOURCE_REMOVE );
418  } else {
419  return (G_SOURCE_CONTINUE);
420  }
421  }
422 
423  g_print("%s\n", pctrl->ch_message); // Todo not needed
424 
425  return (G_SOURCE_CONTINUE);
426 }
gchar ch_message[SZ_MESSAGE_BUFF]
Definition: cmdDC.c:111
GSocket * gSock
Definition: cmdDC.c:96
GSocketAddress * gsDSAddr
Definition: cmdDC.c:98
GMainLoop * loop
Definition: cmdDC.c:91
guint gErrorCount
Definition: cmdDC.c:105
gchar ch_display_service_name[SZ_RMTADDR_BUFF]
Definition: cmdDC.c:110

+ Here is the caller graph for this function:

static gboolean cb_udp_comm_response_handler ( GSocket *  gSock,
GIOCondition  condition,
PControlData  pctrl 
)
static

Definition at line 337 of file gssdpDC.c.

References _controlData::ch_request, _controlData::ch_response, _controlData::gErrorCount, _controlData::loop, _controlData::oneShot, _controlData::resolver, and skn_get_timestamp().

Referenced by udp_initialize_message_send().

337  {
338  GError *error = NULL;
339  gssize gss_receive = 0;
340  gchar *stamp = skn_get_timestamp();
341  gchar * rmtHost = NULL;
342  GSocketAddress *gsRmtAddr = NULL;
343  GInetAddress *gsAddr = NULL;
344  gchar *converted = NULL;
345 
346  if ( NULL == pctrl) { /* SHUTDOWN THE MAIN LOOP */
347  g_message("DisplayClient::cb_udp_comm_response_handler(error) Invalid Pointer");
348  return ( G_SOURCE_REMOVE );
349  }
350 
351  gss_receive = g_socket_receive_from(gSock, &gsRmtAddr, pctrl->ch_request, sizeof(pctrl->ch_request), NULL, &error);
352  if (error != NULL) { // gss_receive = Number of bytes read, or 0 if the connection was closed by the peer, or -1 on error
353  g_error("g_socket_receive() => %s", error->message);
354  g_clear_error(&error);
355  }
356  if (gss_receive > 0 ) {
357  pctrl->ch_request[gss_receive] = 0;
358  if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) ) {
359  gsAddr = g_inet_socket_address_get_address( G_INET_SOCKET_ADDRESS(gsRmtAddr) );
360  if ( G_IS_INET_ADDRESS(gsAddr) ) {
361  g_object_ref(gsAddr);
362  rmtHost = g_resolver_lookup_by_address (pctrl->resolver, gsAddr, NULL, NULL);
363  if (NULL == rmtHost) {
364  rmtHost = g_inet_address_to_string ( gsAddr);
365  }
366  }
367  }
368 
369  /*
370  * Convert to UTF8 */
371  converted = g_convert (pctrl->ch_request, gss_receive, "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
372  if (NULL != converted) {
373  g_utf8_strncpy(pctrl->ch_request, converted, sizeof(pctrl->ch_request));
374  g_free(converted);
375  }
376 
377  g_snprintf(pctrl->ch_response, sizeof(pctrl->ch_response), "[%s]RESPONSE From=%s, Msg=%s", stamp, rmtHost, pctrl->ch_request);
378  pctrl->gErrorCount = 0; // reset send errors
379  } else {
380  g_snprintf(pctrl->ch_response, sizeof(pctrl->ch_response), "%s", "Error: Input not Usable!");
381  }
382 
383  g_print("%s\n", pctrl->ch_response);
384  g_free(stamp);
385 
386  if ( G_IS_INET_ADDRESS(gsAddr) )
387  g_object_unref(gsAddr);
388 
389  if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
390  g_object_unref(gsRmtAddr);
391 
392  if (pctrl->oneShot) {
393  g_main_loop_quit(pctrl->loop);
394  return ( G_SOURCE_REMOVE );
395  } else {
396  return (G_SOURCE_CONTINUE);
397  }
398 
399 }
gchar ch_request[SZ_MESSAGE_BUFF]
Definition: cmdDC.c:112
gchar ch_response[SZ_RESPONSE_BUFF]
Definition: cmdDC.c:113
gboolean oneShot
Definition: gssdpDC.c:117
gchar * skn_get_timestamp()
Definition: gssdpDC.c:300
GMainLoop * loop
Definition: cmdDC.c:91
guint gErrorCount
Definition: cmdDC.c:105
GResolver * resolver
Definition: cmdDC.c:100

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static gboolean cb_udp_registry_select_handler ( PControlData  pctrl)
static

Definition at line 473 of file gssdpDC.c.

References _controlData::ch_display_service_name, _registryData::ch_ip, _gssdpRegistryData::ch_location, _registryData::ch_name, _registryData::ch_port, _gssdpRegistryData::ch_urn, FALSE, _controlData::glRegistry, _controlData::gMsgDelay, _controlData::gReady, _controlData::gRegistryQueries, _controlData::gsDSAddr, _controlData::resource_browser, TRUE, udp_initialize_message_send(), and udp_registry_find_by_name().

Referenced by main().

473  {
474  GList *registry = NULL;
475  PGSSDPRegData preg = NULL;
476  GInetAddress *anyAddr = NULL;
477  gchar **parts = NULL;
478  RegData msg;
479 
480  g_return_val_if_fail((NULL != pctrl), G_SOURCE_REMOVE);
481 
482  /*
483  * Find in Registry the selected service name */
484  if (g_list_length(pctrl->glRegistry) < 1) {
485  pctrl->gRegistryQueries++;
486 
487  if ((pctrl->gRegistryQueries % 15) == 0) { // every 30 seconds redo query
488  g_print("[GSSDP] Looking for [%s] in Rpi Registry every 30 seconds. StandBy...\n", pctrl->ch_display_service_name);
489  gssdp_resource_browser_set_active(pctrl->resource_browser, TRUE);
490  }
491 
492  return (G_SOURCE_CONTINUE);
493  }
494 
495  if ( NULL == (registry = g_list_find_custom (pctrl->glRegistry, pctrl->ch_display_service_name, (GCompareFunc)udp_registry_find_by_name)) ) {
496  g_list_free_full(pctrl->glRegistry, (GDestroyNotify)g_free);
497  pctrl->glRegistry = NULL;
498  return (G_SOURCE_CONTINUE);
499  }
500 
501  preg = registry->data; // now extract ip and port
502  /* Display Service Address */
503 
504  parts = g_strsplit (preg->ch_location, ":",-1);
505  g_utf8_strncpy(msg.ch_name, pctrl->ch_display_service_name, sizeof(msg.ch_name));
506  g_utf8_strncpy(msg.ch_ip, &parts[1][2], sizeof(msg.ch_ip));
507  g_utf8_strncpy(msg.ch_port, parts[2], sizeof(msg.ch_port));
508  g_strfreev(parts);
509 
510  anyAddr = g_inet_address_new_from_string(msg.ch_ip); // g_object_unref(dIP) when done
511  if (NULL == anyAddr) {
512  g_error("g_inet_address_new_from_string() Failed => %s, %s", preg->ch_location, preg->ch_location); // "udp://%s:%d"
513  return(G_SOURCE_CONTINUE);
514  }
515  pctrl->gsDSAddr = g_inet_socket_address_new(anyAddr, g_ascii_strtoll(msg.ch_port, NULL, 10));
516  g_object_unref(anyAddr);
517 
518  pctrl->gReady = udp_initialize_message_send(pctrl);
519 
520  if (pctrl->gReady) {
521  g_print("[GSSDP] FOUND %s on %s, sending your message in %d seconds.\n\n", preg->ch_urn, preg->ch_location, pctrl->gMsgDelay);
522  gssdp_resource_browser_set_active(pctrl->resource_browser, FALSE);
523  return (G_SOURCE_REMOVE);
524  } else {
525  return (G_SOURCE_CONTINUE);
526  }
527 }
GSSDPResourceBrowser * resource_browser
Definition: gssdpDC.c:108
gchar ch_ip[SZ_PARAMS_BUFF]
Definition: cmdDC.c:85
#define FALSE
gchar ch_port[SZ_PARAMS_BUFF]
Definition: cmdDC.c:86
#define TRUE
GSocketAddress * gsDSAddr
Definition: cmdDC.c:98
gboolean udp_initialize_message_send(PControlData pctrl)
Definition: gssdpDC.c:428
gchar ch_name[SZ_RMTADDR_BUFF]
Definition: cmdDC.c:84
gchar ch_urn[SZ_RMTADDR_BUFF]
Definition: gssdpDC.c:93
GList * glRegistry
Definition: cmdDC.c:101
gboolean gReady
Definition: cmdDC.c:107
guint gRegistryQueries
Definition: cmdDC.c:103
gchar ch_location[SZ_RMTADDR_BUFF]
Definition: gssdpDC.c:94
gint udp_registry_find_by_name(PGSSDPRegData pr, gchar *pch_name)
Definition: gssdpDC.c:465
guint gMsgDelay
Definition: cmdDC.c:106
gchar ch_display_service_name[SZ_RMTADDR_BUFF]
Definition: cmdDC.c:110

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static gboolean cb_unix_signal_handler ( PUSignalData  psig)
static

Definition at line 586 of file gssdpDC.c.

References _signalData::loop, and _signalData::signalName.

Referenced by main().

586  {
587  g_message("DisplayClient::cb_unix_signal_handler() %s Unix Signal Received => Shutdown Initiated!\n", psig->signalName);
588  g_main_loop_quit(psig->loop);
589  return ( G_SOURCE_REMOVE );
590 }
gchar * signalName
Definition: cmdDC.c:78
GMainLoop * loop
Definition: cmdDC.c:77

+ Here is the caller graph for this function:

int main ( int  argc,
char **  argv 
)

Definition at line 592 of file gssdpDC.c.

References cb_udp_registry_select_handler(), cb_unix_signal_handler(), _controlData::ch_display_service_name, _controlData::ch_intfName, _controlData::ch_message, _controlData::ch_this_ip, FALSE, G_OPTION_FLAG_NONE, _controlData::gCommSource, _controlData::gErrorCount, _controlData::glRegistry, _controlData::gMsgDelay, _controlData::gReady, _controlData::gRegCount, _controlData::gRegistryQueries, _controlData::gsAddr, _controlData::gsDSAddr, _controlData::gSock, _controlData::gssdp_rgroup_client, _signalData::loop, _controlData::loop, MSG_DELAY_INTERVAL, _controlData::oneShot, _controlData::paB, _controlData::pch_search, _controlData::resolver, _controlData::resource_browser, _controlData::sigHup, _controlData::sigInt, _signalData::signalName, _controlData::sigTerm, skn_get_default_interface_name_and_ipv4_address(), skn_gssdp_browse(), and TRUE.

592  {
593 
594  ControlData cData;
595  GError *error = NULL;
596  gchar * pch_display_service_name = NULL;
597  gchar * pch_message = NULL;
598 
599  GOptionContext *gOptions = NULL;
600  GOptionEntry pgmOptions[] = {
601  {"display_service_name", 'a', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &pch_display_service_name, "DisplayService Name", "GtkDisplayService"},
602  {"display_message", 'm', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &pch_message, "Message to send to DisplayService", "single-quoted-string"},
603  {"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"},
604  {"search-key", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &cData.pch_search, "GSSDP Search Key.", "[urn:rpilocator | ssdp:all]"},
605  {NULL}
606  };
607 
608  cData.gMsgDelay = 0;
609  cData.gErrorCount = 0;
610  cData.gRegCount = 0;
611  cData.gRegistryQueries = 0;
612  cData.gReady = FALSE;
613  cData.oneShot = FALSE;
614 
615  cData.pch_search = NULL;
616  cData.glRegistry = NULL;
617  cData.sigTerm.signalName = "SIGTERM";
618  cData.sigInt.signalName = "SIGINT";
619  cData.sigHup.signalName = "SIGHUP";
620  cData.gErrorCount = 0;
621  cData.resolver = g_resolver_get_default();
622 
623  gOptions = g_option_context_new ("UDP message display client for IOT.");
624  g_option_context_add_main_entries (gOptions, pgmOptions, NULL);
625  g_option_context_parse (gOptions, &argc, &argv, &error);
626  if (error != NULL) {
627  g_error("g_option_context_parse() => %s", error->message);
628  g_clear_error(&error);
629  exit(EXIT_FAILURE);
630  }
631  g_option_context_free(gOptions);
632 
633  if (NULL == pch_message) {
634  g_utf8_strncpy(cData.ch_message, "GTK-+3.0 Rocks with GLIB-2.0 on any platform! (gssdpDC)", sizeof(cData.ch_message));
635  } else {
636  g_utf8_strncpy(cData.ch_message, pch_message, sizeof(cData.ch_message));
637  g_free(pch_message);
638  }
639  if (NULL == pch_display_service_name) {
640  g_utf8_strncpy(cData.ch_display_service_name, "GtkDisplayService", sizeof(cData.ch_display_service_name));
641  } else {
642  g_utf8_strncpy(cData.ch_display_service_name, pch_display_service_name, sizeof(cData.ch_display_service_name));
643  g_free(pch_display_service_name);
644  }
645  if (0 == cData.gMsgDelay) {
647  cData.oneShot = TRUE; // if no delay is given, send message once and quit.
648  }
649  if (NULL == cData.pch_search) {
650  cData.pch_search = "urn:rpilocator";
651  }
652 
653 
654  cData.paB = NULL;
655  cData.paB = skn_get_default_interface_name_and_ipv4_address((char *)&cData.ch_intfName, (char *)&cData.ch_this_ip);
656  if (NULL == cData.paB) {
657  g_error("skn_skn_get_default_interface_name_and_ipv4_address() => Unable to discover network interface or non-available.");
658  exit(EXIT_FAILURE);
659  }
660 
661  cData.sigHup.loop = cData.sigTerm.loop = cData.sigInt.loop = cData.loop = g_main_loop_new(NULL, FALSE);
662 
663  /*
664  * Handle ctrl-break and kill signals cleanly */
665  g_unix_signal_add (SIGINT, (GSourceFunc) cb_unix_signal_handler, &cData.sigInt); // SIGINT signal (Ctrl+C)
666  g_unix_signal_add (SIGHUP, (GSourceFunc) cb_unix_signal_handler, &cData.sigHup);
667  g_unix_signal_add (SIGTERM,(GSourceFunc) cb_unix_signal_handler, &cData.sigTerm);
668 
669  if ( skn_gssdp_browse(&cData) ) {
670  /*
671  * Setup 2secTimer to find display_service before starting rest */
672  g_timeout_add (2000, (GSourceFunc)cb_udp_registry_select_handler, &cData);
673 
674  g_print("[GSSDP] Looking for [%s] in Rpi Registry. StandBy...\n", cData.ch_display_service_name);
675 
676  g_main_loop_run(cData.loop);
677 
678  gssdp_resource_browser_set_active(cData.resource_browser, FALSE);
679  }
680 
681  g_main_loop_unref(cData.loop);
682 
683  if (cData.gReady) {
684  g_source_unref(cData.gCommSource);
685  g_object_unref(cData.gSock);
686  g_object_unref(cData.gsDSAddr);
687  g_object_unref(cData.gsAddr);
688  }
689  g_object_unref (cData.resource_browser);
690  g_object_unref (cData.gssdp_rgroup_client);
691 
692  g_free(cData.paB);
693  g_list_free_full(cData.glRegistry, (GDestroyNotify)g_free);
694 
695  g_message("gssdpDC: normal shutdown...");
696 
697  exit(EXIT_SUCCESS);
698 }
USignalData sigHup
Definition: cmdDC.c:94
GSSDPResourceBrowser * resource_browser
Definition: gssdpDC.c:108
static gboolean cb_udp_registry_select_handler(PControlData pctrl)
Definition: gssdpDC.c:473
static gboolean cb_unix_signal_handler(PUSignalData psig)
Definition: gssdpDC.c:586
gchar ch_message[SZ_MESSAGE_BUFF]
Definition: cmdDC.c:111
USignalData sigTerm
Definition: cmdDC.c:92
guint gRegCount
Definition: cmdDC.c:104
#define FALSE
#define G_OPTION_FLAG_NONE
Definition: gssdpDC.c:39
gboolean oneShot
Definition: gssdpDC.c:117
PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address(char *intf, char *ipv4)
GSocketAddress * gsAddr
Definition: cmdDC.c:99
#define TRUE
GSocket * gSock
Definition: cmdDC.c:96
GSocketAddress * gsDSAddr
Definition: cmdDC.c:98
GMainLoop * loop
Definition: cmdDC.c:91
guint gErrorCount
Definition: cmdDC.c:105
gchar * signalName
Definition: cmdDC.c:78
gchar ch_this_ip[SZ_RMTADDR_BUFF]
Definition: cmdDC.c:109
PIPBroadcastArray paB
Definition: cmdDC.c:102
GList * glRegistry
Definition: cmdDC.c:101
USignalData sigInt
Definition: cmdDC.c:93
gboolean gReady
Definition: cmdDC.c:107
#define MSG_DELAY_INTERVAL
Definition: gssdpDC.c:48
guint gRegistryQueries
Definition: cmdDC.c:103
GMainLoop * loop
Definition: cmdDC.c:77
guint gMsgDelay
Definition: cmdDC.c:106
GResolver * resolver
Definition: cmdDC.c:100
gchar * pch_search
Definition: gssdpDC.c:118
gboolean skn_gssdp_browse(PControlData pctrl)
Definition: gssdpDC.c:568
GSSDPClient * gssdp_rgroup_client
Definition: gssdpDC.c:107
gchar ch_intfName[SZ_RMTADDR_BUFF]
Definition: cmdDC.c:108
gchar ch_display_service_name[SZ_RMTADDR_BUFF]
Definition: cmdDC.c:110
GSource * gCommSource
Definition: cmdDC.c:95

+ Here is the call graph for this function:

gint skn_get_broadcast_ip_array ( PIPBroadcastArray  paB)

Collect IP and Broadcast Addresses for this machine

  • Affects the PIPBroadcastArray
  • Return -1 on error, or count of interfaces
  • contains this ipAddress in paB->ipAddrStr[paB->defaultIndex]

Definition at line 196 of file gssdpDC.c.

References ARY_MAX_INTF, _ipBroadcastArray::broadAddrStr, _ipBroadcastArray::cbName, _ipBroadcastArray::chDefaultIntfName, _ipBroadcastArray::count, _ipBroadcastArray::defaultIndex, _ipBroadcastArray::ifNameStr, _ipBroadcastArray::ipAddrStr, _ipBroadcastArray::maskAddrStr, PLATFORM_ERROR, skn_get_default_interface_name(), and SZ_CHAR_BUFF.

Referenced by skn_get_default_interface_name_and_ipv4_address().

196  {
197  struct ifaddrs * ifap;
198  struct ifaddrs * p;
199  gint rc = 0;
200 
201  memset(paB, 0, sizeof(IPBroadcastArray));
202  paB->count = 0;
203  paB->defaultIndex = 0;
204  strcpy(paB->cbName, "IPBroadcastArray");
205 
207  if (rc == EXIT_FAILURE) { // Alternate method for Mac: 'route -n -A inet'
208  g_warning("[GSSDP] No Default Network Interfaces Found!.");
209  paB->chDefaultIntfName[0] = 0;
210  }
211  rc = getifaddrs(&ifap);
212  if (rc != 0) {
213  g_warning("[GSSDP] No Network Interfaces Found at All ! %d:%d:%s", rc, errno, strerror(errno) );
214  return (PLATFORM_ERROR);
215  }
216  p = ifap;
217 
218  while (p && (paB->count < ARY_MAX_INTF)) {
219  if (p->ifa_addr != NULL && p->ifa_addr->sa_family == AF_INET && ((p->ifa_flags & IFF_BROADCAST) > 0)) {
220 
221  inet_ntop(p->ifa_addr->sa_family, &((struct sockaddr_in *) p->ifa_addr)->sin_addr, paB->ipAddrStr[paB->count], (SZ_CHAR_BUFF - 1));
222  inet_ntop(p->ifa_addr->sa_family, &((struct sockaddr_in *) p->ifa_netmask)->sin_addr, paB->maskAddrStr[paB->count], (SZ_CHAR_BUFF - 1));
223  inet_ntop(p->ifa_addr->sa_family, &((struct sockaddr_in *) p->ifa_broadaddr)->sin_addr, paB->broadAddrStr[paB->count], (SZ_CHAR_BUFF - 1));
224 
225  strncpy(paB->ifNameStr[paB->count], p->ifa_name, (SZ_CHAR_BUFF -1));
226 
227  /* Take match as the default */
228  if (strcmp(paB->chDefaultIntfName, p->ifa_name) == 0) {
229  paB->defaultIndex = paB->count;
230  }
231 
232  paB->count++;
233  }
234  p = p->ifa_next;
235  } // end while
236  freeifaddrs(ifap);
237 
238  return (paB->count);
239 }
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:68
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:69
gint skn_get_default_interface_name(char *pchDefaultInterfaceName)
Definition: gssdpDC.c:257
char maskAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:70
#define PLATFORM_ERROR
Definition: gssdpDC.c:64
char cbName[SZ_CHAR_BUFF]
Definition: cmdDC.c:66
#define SZ_CHAR_BUFF
Definition: gssdpDC.c:58
#define ARY_MAX_INTF
Definition: gssdpDC.c:63
int defaultIndex
Definition: cmdDC.c:72
char chDefaultIntfName[SZ_CHAR_BUFF]
Definition: cmdDC.c:67
char broadAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:71

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

gint skn_get_default_interface_name ( char *  pchDefaultInterfaceName)

Retrieves default internet interface name into param

  • absolute best way to do this, but not supported on Darwin(i.e OSX) return EXIT_SUCCESS or EXIT_FAILURE

[jscott OSX]$ route -n get 0.0.0.0 route to: default destination: default mask: default gateway: 10.21.1.254 interface: en3 flags: <UP,GATEWAY,DONE,STATIC,PRCLONING> recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire 0 0 0 0 0 0 1500 0

Definition at line 257 of file gssdpDC.c.

References skn_strip(), and SZ_INFO_BUFF.

Referenced by skn_get_broadcast_ip_array().

257  {
258  FILE *f_route;
259  char line[SZ_INFO_BUFF], *dRoute = NULL, *iName = NULL;
260 
261  f_route = fopen("/proc/net/route", "r");
262  if (f_route != NULL) {
263  while (fgets(line, SZ_INFO_BUFF - 1, f_route)) {
264  iName = strtok(line, "\t");
265  dRoute = strtok(NULL, "\t");
266 
267  if (iName != NULL && dRoute != NULL) {
268  if (strcmp(dRoute, "00000000") == 0) {
269  strncpy(pchDefaultInterfaceName, iName, (SZ_INFO_BUFF - 1));
270  break;
271  }
272  }
273  }
274  fclose(f_route);
275 
276  return (EXIT_SUCCESS);
277  }
278  g_print("[GSSDP] Opening ProcFs for RouteInfo Failed: %d:%s, Alternate method will be attempted.\n", errno, strerror(errno));
279 
280  f_route = popen("route -n get 0.0.0.0", "r"); // for linux 'route -n -A inet', with interface at line_word[7]
281  if (f_route != NULL) {
282  while (fgets(line, SZ_INFO_BUFF - 1, f_route)) {
283  dRoute = strtok(line, ":");
284  iName = strtok(NULL, "\n");
285  if (strcmp(skn_strip(dRoute), "interface") == 0) {
286  strncpy(pchDefaultInterfaceName, skn_strip(iName), (SZ_INFO_BUFF - 1));
287  break;
288  }
289  }
290  fclose(f_route);
291 
292  return (EXIT_SUCCESS);
293  } else {
294  g_warning("[GSSDP] Alternate method to get RouteInfo Failed: %d:%s", errno, strerror(errno));
295  return (EXIT_FAILURE);
296  }
297 
298 }
gchar * skn_strip(gchar *alpha)
Definition: gssdpDC.c:150
#define SZ_INFO_BUFF
Definition: gssdpDC.c:57

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address ( char *  intf,
char *  ipv4 
)

Referenced by main().

+ Here is the caller graph for this function:

PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address ( gchar *  intf,
gchar *  ipv4 
)

Definition at line 176 of file gssdpDC.c.

References _ipBroadcastArray::chDefaultIntfName, _ipBroadcastArray::defaultIndex, _ipBroadcastArray::ipAddrStr, PLATFORM_ERROR, skn_get_broadcast_ip_array(), and SZ_CHAR_BUFF.

176  {
177  PIPBroadcastArray paB = g_new0(IPBroadcastArray, 1);
178 
180  g_utf8_strncpy(intf, paB->chDefaultIntfName, SZ_CHAR_BUFF);
181  g_utf8_strncpy(ipv4, paB->ipAddrStr[paB->defaultIndex], SZ_CHAR_BUFF);
182  } else {
183  g_warning("[GSSDP] InterfaceName and Address: unable to access information.");
184  return(NULL);
185  }
186  return (paB);
187 }
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:69
#define PLATFORM_ERROR
Definition: gssdpDC.c:64
#define SZ_CHAR_BUFF
Definition: gssdpDC.c:58
int defaultIndex
Definition: cmdDC.c:72
char chDefaultIntfName[SZ_CHAR_BUFF]
Definition: cmdDC.c:67
gint skn_get_broadcast_ip_array(PIPBroadcastArray paB)
Definition: gssdpDC.c:196

+ Here is the call graph for this function:

gchar* skn_get_timestamp ( )

Definition at line 300 of file gssdpDC.c.

Referenced by cb_gssdp_resource_available(), and cb_udp_comm_response_handler().

300  {
301  GDateTime *stamp = g_date_time_new_now_local();
302  gchar *response = g_date_time_format(stamp,"%F.%T");
303 
304  return(response);
305 }

+ Here is the caller graph for this function:

gchar* skn_gio_condition_to_string ( GIOCondition  condition)

Definition at line 307 of file gssdpDC.c.

307  {
308  gchar *value = NULL;
309 
310  switch(condition) {
311  case G_IO_IN:
312  value = "There is data to read.";
313  break;
314  case G_IO_OUT:
315  value = "Data can be written (without blocking).";
316  break;
317  case G_IO_PRI:
318  value = "There is urgent data to read.";
319  break;
320  case G_IO_ERR:
321  value = "Error condition.";
322  break;
323  case G_IO_HUP:
324  value = "Hung up (the connection has been broken, usually for pipes and sockets).";
325  break;
326  case G_IO_NVAL:
327  value = "Invalid request. The file descriptor is not open.";
328  break;
329  default:
330  value = "Unknown GIOCondition!";
331  }
332 
333  return (value);
334 }
gboolean skn_gssdp_browse ( PControlData  pctrl)

Setup a monitor for the registry page

Definition at line 568 of file gssdpDC.c.

References cb_gssdp_resource_available(), FALSE, _controlData::gssdp_rgroup_client, _controlData::pch_search, _controlData::resource_browser, and TRUE.

Referenced by main().

568  {
569  GError *error = NULL;
570 
571  pctrl->gssdp_rgroup_client = gssdp_client_new(NULL, NULL, &error);
572  if (error) {
573  g_printerr ("Error creating the GSSDP gssdp_client for resource_browser: %s\n", error->message);
574  g_error_free (error);
575  return(FALSE);
576  }
577 
578  pctrl->resource_browser = gssdp_resource_browser_new (pctrl->gssdp_rgroup_client, pctrl->pch_search); // GSSDP_ALL_RESOURCES);
579  g_signal_connect (pctrl->resource_browser, "resource-available", G_CALLBACK (cb_gssdp_resource_available), pctrl);
580 
581  gssdp_resource_browser_set_active(pctrl->resource_browser, TRUE);
582 
583  return (TRUE);
584 }
GSSDPResourceBrowser * resource_browser
Definition: gssdpDC.c:108
#define FALSE
#define TRUE
static void cb_gssdp_resource_available(GSSDPResourceBrowser *resource_browser, const char *usn, GList *locations, PControlData pctrl)
Definition: gssdpDC.c:529
gchar * pch_search
Definition: gssdpDC.c:118
GSSDPClient * gssdp_rgroup_client
Definition: gssdpDC.c:107

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

gchar* skn_strip ( gchar *  alpha)

Remove Trailing and Leading Blanks

  • caution: pointers from argv are readonly and segfault on 'alpha[end] = 0'

Definition at line 150 of file gssdpDC.c.

Referenced by skn_get_default_interface_name().

150  {
151  if (alpha == NULL || strlen(alpha) < 1)
152  return(alpha);
153 
154  int len = strlen(alpha);
155  int end = len - 1;
156  int start = 0;
157 
158  // use isgraph() or !isspace() vs isalnum() to allow ['|' ';' '%']
159  while ( !g_unichar_isgraph(alpha[end]) && end > 0 ) { // remove trailing non-alphanumeric chars
160  alpha[end--] = 0;
161  }
162 
163  len = strlen(alpha);
164  while ( !g_unichar_isalnum(alpha[start]) && start < len ) { // find first non-alpha stricter
165  start++;
166  }
167  if (start < len && start > 0) { // move in place
168  end = len - start;
169  memmove(&alpha[0], &alpha[start], end);
170  alpha[end] = 0;
171  }
172 
173  return(alpha);
174 }

+ Here is the caller graph for this function:

gboolean udp_initialize_message_send ( PControlData  pctrl)

Definition at line 428 of file gssdpDC.c.

References cb_udp_comm_request_handler(), cb_udp_comm_response_handler(), FALSE, _controlData::gCommSource, _controlData::gMsgDelay, _controlData::gsAddr, _controlData::gSock, SKN_UDP_ANY_PORT, and TRUE.

Referenced by cb_udp_registry_select_handler().

428  {
429  GError *error = NULL;
430  GInetAddress *anyAddr = NULL;
431 
432  g_return_val_if_fail((NULL != pctrl), G_SOURCE_REMOVE);
433 
434  pctrl->gSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
435  if (error != NULL) {
436  g_error("g_socket_new() => %s", error->message);
437  g_clear_error(&error);
438  return(FALSE);
439  }
440 
441  anyAddr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
442  pctrl->gsAddr = g_inet_socket_address_new(anyAddr, SKN_UDP_ANY_PORT);
443  g_object_unref(anyAddr);
444 
445  g_socket_bind(pctrl->gSock, pctrl->gsAddr, TRUE, &error);
446  if (error != NULL) {
447  g_error("g_socket_bind() => %s", error->message);
448  g_clear_error(&error);
449  exit(FALSE);
450  }
451 
452  pctrl->gCommSource = g_socket_create_source (pctrl->gSock, G_IO_IN, NULL);
453  g_source_set_callback (pctrl->gCommSource, (GSourceFunc) cb_udp_comm_response_handler, pctrl, NULL); // its really a GSocketSourceFunc
454  g_source_attach (pctrl->gCommSource, NULL);
455 
456  /*
457  * Setup Timer to drive repeated Message to Display Service */
458  g_timeout_add ((pctrl->gMsgDelay * 1000), (GSourceFunc)cb_udp_comm_request_handler, pctrl);
459 
460 
461  return (TRUE);
462 }
static gboolean cb_udp_comm_response_handler(GSocket *gSock, GIOCondition condition, PControlData pctrl)
Definition: gssdpDC.c:337
static gboolean cb_udp_comm_request_handler(PControlData pctrl)
Definition: gssdpDC.c:401
#define FALSE
GSocketAddress * gsAddr
Definition: cmdDC.c:99
#define TRUE
GSocket * gSock
Definition: cmdDC.c:96
#define SKN_UDP_ANY_PORT
Definition: gssdpDC.c:62
guint gMsgDelay
Definition: cmdDC.c:106
GSource * gCommSource
Definition: cmdDC.c:95

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

gint udp_registry_find_by_name ( PGSSDPRegData  pr,
gchar *  pch_name 
)

Definition at line 465 of file gssdpDC.c.

References _gssdpRegistryData::ch_urn.

Referenced by cb_udp_registry_select_handler().

465  {
466  gint result = -1;
467  if (NULL != g_strrstr(pr->ch_urn, pch_name)) {
468  result = 0;
469  }
470  return( result );
471 }
gchar ch_urn[SZ_RMTADDR_BUFF]
Definition: gssdpDC.c:93

+ Here is the caller graph for this function: