18 #ifndef PACKAGE_VERSION 19 #define PACKAGE_VERSION "0.9.0" 22 #define PACKAGE_NAME "gssdpDC" 24 #ifndef PACKAGE_DESCRIPTION 25 #define PACKAGE_DESCRIPTION "Send Message to Raspberry Pi's on the network." 33 #include <libgssdp/gssdp.h> 34 #include <glib-unix.h> 35 #include <gio/gnetworking.h> 38 #ifndef G_OPTION_FLAG_NONE 39 #define G_OPTION_FLAG_NONE 0 43 #define UDP_DISPLAY_COMM_PORT 48029 44 #define UDP_BROADCAST_PORT 48028 45 #define UDP_REGULAR_PORT 48027 46 #define UDP_CLIENTS_PORT 48026 47 #define MS_TEN_MINUTES 600000 48 #define MSG_DELAY_INTERVAL 10 50 #define SZ_TIMESTAMP_BUFF 32 51 #define SZ_PARAMS_BUFF 64 52 #define SZ_RMTADDR_BUFF 256 53 #define SZ_MESSAGE_BUFF 512 54 #define SZ_RESPONSE_BUFF 256 56 #define SZ_CHAR_LABEL 48 57 #define SZ_INFO_BUFF 256 58 #define SZ_CHAR_BUFF 128 59 #define SZ_LINE_BUFF 512 60 #define SZ_COMM_BUFF 256 62 #define SKN_UDP_ANY_PORT 0 63 #define ARY_MAX_INTF 8 64 #define PLATFORM_ERROR -1 103 GSource *gCommSource;
105 GSocketAddress *gsDSAddr;
106 GSocketAddress *gsAddr;
111 PIPBroadcastArray paB;
112 guint gRegistryQueries;
129 static void cb_gssdp_resource_available(GSSDPResourceBrowser *resource_browser,
const char *usn, GList *locations, PControlData pctrl);
151 if (alpha == NULL || strlen(alpha) < 1)
154 int len = strlen(alpha);
159 while ( !g_unichar_isgraph(alpha[end]) && end > 0 ) {
164 while ( !g_unichar_isalnum(alpha[start]) && start < len ) {
167 if (start < len && start > 0) {
169 memmove(&alpha[0], &alpha[start], end);
183 g_warning(
"[GSSDP] InterfaceName and Address: unable to access information.");
197 struct ifaddrs * ifap;
204 strcpy(paB->
cbName,
"IPBroadcastArray");
207 if (rc == EXIT_FAILURE) {
208 g_warning(
"[GSSDP] No Default Network Interfaces Found!.");
211 rc = getifaddrs(&ifap);
213 g_warning(
"[GSSDP] No Network Interfaces Found at All ! %d:%d:%s", rc, errno, strerror(errno) );
219 if (p->ifa_addr != NULL && p->ifa_addr->sa_family == AF_INET && ((p->ifa_flags & IFF_BROADCAST) > 0)) {
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));
261 f_route = fopen(
"/proc/net/route",
"r");
262 if (f_route != NULL) {
264 iName = strtok(line,
"\t");
265 dRoute = strtok(NULL,
"\t");
267 if (iName != NULL && dRoute != NULL) {
268 if (strcmp(dRoute,
"00000000") == 0) {
269 strncpy(pchDefaultInterfaceName, iName, (
SZ_INFO_BUFF - 1));
276 return (EXIT_SUCCESS);
278 g_print(
"[GSSDP] Opening ProcFs for RouteInfo Failed: %d:%s, Alternate method will be attempted.\n", errno, strerror(errno));
280 f_route = popen(
"route -n get 0.0.0.0",
"r");
281 if (f_route != NULL) {
283 dRoute = strtok(line,
":");
284 iName = strtok(NULL,
"\n");
285 if (strcmp(
skn_strip(dRoute),
"interface") == 0) {
292 return (EXIT_SUCCESS);
294 g_warning(
"[GSSDP] Alternate method to get RouteInfo Failed: %d:%s", errno, strerror(errno));
295 return (EXIT_FAILURE);
301 GDateTime *stamp = g_date_time_new_now_local();
302 gchar *response = g_date_time_format(stamp,
"%F.%T");
312 value =
"There is data to read.";
315 value =
"Data can be written (without blocking).";
318 value =
"There is urgent data to read.";
321 value =
"Error condition.";
324 value =
"Hung up (the connection has been broken, usually for pipes and sockets).";
327 value =
"Invalid request. The file descriptor is not open.";
330 value =
"Unknown GIOCondition!";
338 GError *error = NULL;
339 gssize gss_receive = 0;
341 gchar * rmtHost = NULL;
342 GSocketAddress *gsRmtAddr = NULL;
343 GInetAddress *gsAddr = NULL;
344 gchar *converted = NULL;
346 if ( NULL == pctrl) {
347 g_message(
"DisplayClient::cb_udp_comm_response_handler(error) Invalid Pointer");
348 return ( G_SOURCE_REMOVE );
351 gss_receive = g_socket_receive_from(gSock, &gsRmtAddr, pctrl->
ch_request,
sizeof(pctrl->
ch_request), NULL, &error);
353 g_error(
"g_socket_receive() => %s", error->message);
354 g_clear_error(&error);
356 if (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);
371 converted = g_convert (pctrl->
ch_request, gss_receive,
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
372 if (NULL != converted) {
386 if ( G_IS_INET_ADDRESS(gsAddr) )
387 g_object_unref(gsAddr);
389 if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
390 g_object_unref(gsRmtAddr);
393 g_main_loop_quit(pctrl->
loop);
394 return ( G_SOURCE_REMOVE );
396 return (G_SOURCE_CONTINUE);
402 GError *error = NULL;
404 if ( NULL == pctrl) {
405 g_message(
"DisplayClient::cb_udp_comm_request_handler(error) Invalid Pointer");
406 return ( G_SOURCE_REMOVE );
411 g_error(
"g_socket_send_to() => %s", error->message);
412 g_clear_error(&error);
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 );
419 return (G_SOURCE_CONTINUE);
425 return (G_SOURCE_CONTINUE);
429 GError *error = NULL;
430 GInetAddress *anyAddr = NULL;
432 g_return_val_if_fail((NULL != pctrl), G_SOURCE_REMOVE);
434 pctrl->
gSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
436 g_error(
"g_socket_new() => %s", error->message);
437 g_clear_error(&error);
441 anyAddr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
443 g_object_unref(anyAddr);
447 g_error(
"g_socket_bind() => %s", error->message);
448 g_clear_error(&error);
467 if (NULL != g_strrstr(pr->
ch_urn, pch_name)) {
474 GList *registry = NULL;
475 PGSSDPRegData preg = NULL;
476 GInetAddress *anyAddr = NULL;
477 gchar **parts = NULL;
480 g_return_val_if_fail((NULL != pctrl), G_SOURCE_REMOVE);
488 g_print(
"[GSSDP] Looking for [%s] in Rpi Registry every 30 seconds. StandBy...\n", pctrl->
ch_display_service_name);
492 return (G_SOURCE_CONTINUE);
496 g_list_free_full(pctrl->
glRegistry, (GDestroyNotify)g_free);
498 return (G_SOURCE_CONTINUE);
501 preg = registry->data;
506 g_utf8_strncpy(msg.
ch_ip, &parts[1][2],
sizeof(msg.
ch_ip));
510 anyAddr = g_inet_address_new_from_string(msg.
ch_ip);
511 if (NULL == anyAddr) {
513 return(G_SOURCE_CONTINUE);
515 pctrl->
gsDSAddr = g_inet_socket_address_new(anyAddr, g_ascii_strtoll(msg.
ch_port, NULL, 10));
516 g_object_unref(anyAddr);
521 g_print(
"[GSSDP] FOUND %s on %s, sending your message in %d seconds.\n\n", preg->
ch_urn, preg->
ch_location, pctrl->
gMsgDelay);
523 return (G_SOURCE_REMOVE);
525 return (G_SOURCE_CONTINUE);
530 PGSSDPRegData msg = NULL;
532 gchar *converted = NULL;
534 g_warn_if_fail(NULL != pctrl);
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));
550 converted = g_convert (locations->data, g_utf8_strlen(locations->data, -1),
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
551 if (NULL != converted) {
569 GError *error = NULL;
573 g_printerr (
"Error creating the GSSDP gssdp_client for resource_browser: %s\n", error->message);
574 g_error_free (error);
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 );
592 int main(
int argc,
char **argv) {
595 GError *error = NULL;
596 gchar * pch_display_service_name = NULL;
597 gchar * pch_message = NULL;
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"},
621 cData.
resolver = g_resolver_get_default();
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);
627 g_error(
"g_option_context_parse() => %s", error->message);
628 g_clear_error(&error);
631 g_option_context_free(gOptions);
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));
639 if (NULL == pch_display_service_name) {
643 g_free(pch_display_service_name);
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.");
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);
676 g_main_loop_run(cData.
loop);
681 g_main_loop_unref(cData.
loop);
685 g_object_unref(cData.
gSock);
687 g_object_unref(cData.
gsAddr);
693 g_list_free_full(cData.
glRegistry, (GDestroyNotify)g_free);
695 g_message(
"gssdpDC: normal shutdown...");
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
static gboolean cb_udp_comm_response_handler(GSocket *gSock, GIOCondition condition, PControlData pctrl)
GSSDPResourceBrowser * resource_browser
static gboolean cb_udp_registry_select_handler(PControlData pctrl)
struct _controlData ControlData
static gboolean cb_unix_signal_handler(PUSignalData psig)
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
struct _ipBroadcastArray * PIPBroadcastArray
struct _registryData RegData
gchar ch_request[SZ_MESSAGE_BUFF]
gchar * skn_strip(gchar *alpha)
gint skn_get_default_interface_name(char *pchDefaultInterfaceName)
struct _ipBroadcastArray IPBroadcastArray
char maskAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gchar ch_ip[SZ_PARAMS_BUFF]
static gboolean cb_udp_comm_request_handler(PControlData pctrl)
struct _gssdpRegistryData * PGSSDPRegData
gchar ch_message[SZ_MESSAGE_BUFF]
gchar ch_response[SZ_RESPONSE_BUFF]
gchar ch_timestamp[SZ_TIMESTAMP_BUFF]
char cbName[SZ_CHAR_BUFF]
#define SZ_TIMESTAMP_BUFF
#define G_OPTION_FLAG_NONE
PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address(char *intf, char *ipv4)
gchar ch_port[SZ_PARAMS_BUFF]
struct _gssdpRegistryData GSSDPRegData
gchar ch_status[SZ_PARAMS_BUFF]
gchar * skn_get_timestamp()
GSocketAddress * gsDSAddr
struct _controlData * PControlData
static void cb_gssdp_resource_available(GSSDPResourceBrowser *resource_browser, const char *usn, GList *locations, PControlData pctrl)
gboolean udp_initialize_message_send(PControlData pctrl)
struct _signalData * PUSignalData
gchar ch_name[SZ_RMTADDR_BUFF]
gchar ch_urn[SZ_RMTADDR_BUFF]
struct _registryData * PRegData
gchar ch_this_ip[SZ_RMTADDR_BUFF]
char chDefaultIntfName[SZ_CHAR_BUFF]
gchar * skn_gio_condition_to_string(GIOCondition condition)
struct _signalData USignalData
int main(int argc, char **argv)
#define MSG_DELAY_INTERVAL
gchar ch_location[SZ_RMTADDR_BUFF]
gint skn_get_broadcast_ip_array(PIPBroadcastArray paB)
char broadAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gint udp_registry_find_by_name(PGSSDPRegData pr, gchar *pch_name)
struct _registryData ** PPRegData
gboolean skn_gssdp_browse(PControlData pctrl)
GSSDPClient * gssdp_rgroup_client
gchar ch_intfName[SZ_RMTADDR_BUFF]
gchar ch_display_service_name[SZ_RMTADDR_BUFF]