25 #ifndef PACKAGE_VERSION 26 #define PACKAGE_VERSION "0.9.0" 29 #define PACKAGE_NAME "gtkDS" 31 #ifndef PACKAGE_DESCRIPTION 32 #define PACKAGE_DESCRIPTION "Display Messages from other Raspberry Pi's on the network." 38 #include <libgssdp/gssdp.h> 40 #include <glib-unix.h> 41 #include <gio/gnetworking.h> 44 #ifndef G_OPTION_FLAG_NONE 45 #define G_OPTION_FLAG_NONE 0 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 UDP_COMM_PORT 48029 56 #define UDP_BROADCAST_PORT 48028 57 #define UDP_REGULAR_PORT 48027 58 #define MS_TEN_MINUTES 600000 60 #define SKN_SMALL_DISPLAY_MODE_ON 1 61 #define SKN_SMALL_DISPLAY_MODE_OFF 0 63 #define MAX_MESSAGES_VIEWABLE 64 65 #define SZ_CHAR_LABEL 48 66 #define SZ_INFO_BUFF 256 67 #define SZ_CHAR_BUFF 128 68 #define SZ_LINE_BUFF 512 69 #define SZ_COMM_BUFF 256 71 #define SKN_UDP_ANY_PORT 0 72 #define ARY_MAX_INTF 8 73 #define PLATFORM_ERROR -1 117 guint gBroadSourceId;
126 GSSDPClient *gssdp_rgroup_client;
128 GSSDPResourceBrowser *resource_browser;
138 PIPBroadcastArray paB;
143 gchar *pch_service_name;
189 GtkWidget *
ui_page_layout(GtkWidget *parent, PControlData pctrl);
201 static void cb_gssdp_resource_available(GSSDPResourceBrowser *resource_browser,
const char *usn, GList *locations, PControlData pctrl);
238 return (g_async_queue_length (message_queue_source->
queue) > 0);
247 message = g_async_queue_try_pop (message_queue_source->
queue);
269 return (func(message, user_data));
274 g_async_queue_unref (message_queue_source->
queue);
278 GClosure *closure = user_data;
279 GValue param_value = G_VALUE_INIT;
280 GValue result_value = G_VALUE_INIT;
286 g_value_init (&result_value, G_TYPE_BOOLEAN);
287 g_value_init (¶m_value, G_TYPE_POINTER);
288 g_value_set_pointer (¶m_value, message);
290 g_closure_invoke (closure, &result_value, 1, ¶m_value, NULL);
291 retval = g_value_get_boolean (&result_value);
293 g_value_unset (¶m_value);
294 g_value_unset (&result_value);
330 g_return_val_if_fail (queue != NULL, NULL);
331 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
337 g_source_set_name (source,
"MessageQueueSource");
339 message_queue_source->
queue = g_async_queue_ref (queue);
343 if (cancellable != NULL)
345 GSource *cancellable_source;
347 cancellable_source = g_cancellable_source_new (cancellable);
348 g_source_set_dummy_callback (cancellable_source);
349 g_source_add_child_source (source, cancellable_source);
350 g_source_unref (cancellable_source);
364 g_warning(
"[REGISTRY] InterfaceName and Address: unable to access information.");
378 struct ifaddrs * ifap;
385 strcpy(paB->
cbName,
"IPBroadcastArray");
388 if (rc == EXIT_FAILURE) {
389 g_warning(
"[REGISTRY] No Default Network Interfaces Found!.");
392 rc = getifaddrs(&ifap);
394 g_warning(
"[REGISTRY] No Network Interfaces Found at All ! %d:%d:%s", rc, errno, strerror(errno) );
400 if (p->ifa_addr != NULL && p->ifa_addr->sa_family == AF_INET && ((p->ifa_flags & IFF_BROADCAST) > 0)) {
402 inet_ntop(p->ifa_addr->sa_family, &((
struct sockaddr_in *) p->ifa_addr)->sin_addr, paB->
ipAddrStr[paB->
count], (
SZ_CHAR_BUFF - 1));
403 inet_ntop(p->ifa_addr->sa_family, &((
struct sockaddr_in *) p->ifa_netmask)->sin_addr, paB->
maskAddrStr[paB->
count], (
SZ_CHAR_BUFF - 1));
442 f_route = fopen(
"/proc/net/route",
"r");
443 if (f_route != NULL) {
445 iName = strtok(line,
"\t");
446 dRoute = strtok(NULL,
"\t");
448 if (iName != NULL && dRoute != NULL) {
449 if (strcmp(dRoute,
"00000000") == 0) {
450 strncpy(pchDefaultInterfaceName, iName, (
SZ_INFO_BUFF - 1));
457 return (EXIT_SUCCESS);
459 g_warning(
"[REGISTRY] Opening ProcFs for RouteInfo Failed: %d:%s, Alternate method will be attempted.", errno, strerror(errno));
461 f_route = popen(
"route -n get 0.0.0.0",
"r");
462 if (f_route != NULL) {
464 dRoute = strtok(line,
":");
465 iName = strtok(NULL,
"\n");
466 if (strcmp(
skn_strip(dRoute),
"interface") == 0) {
473 return (EXIT_SUCCESS);
475 g_warning(
"[REGISTRY] Alternate method to get RouteInfo Failed: %d:%s", errno, strerror(errno));
476 return (EXIT_FAILURE);
490 struct sockaddr_in remaddr;
491 socklen_t addrlen =
sizeof(remaddr);
492 gchar *request =
"urn:rpilocator - Rpi Where Are You?";
494 gint i_socket = g_socket_get_fd(gSock);
498 for (vIndex = 0; vIndex < paB->
count; vIndex++) {
499 memset(&remaddr, 0,
sizeof(remaddr));
500 remaddr.sin_family = AF_INET;
501 remaddr.sin_addr.s_addr = inet_addr(paB->
broadAddrStr[vIndex]);
504 if (sendto(i_socket, request, strlen(request), 0, (
struct sockaddr *) &remaddr, addrlen) < 0) {
505 g_warning(
"SendTo() Timed out; Failure code=%d, etext=%s", errno, strerror(errno));
516 GDateTime *stamp = g_date_time_new_now_local();
517 gchar *response = g_date_time_format(stamp,
"%F.%T");
529 g_snprintf(ch_status_message,
sizeof(ch_status_message),
"Messages=%d, GSSDP entries=%d, RpiLocator entries=%d", pctrl->
gMsgCount, pctrl->
gGSSDPRegCount, pctrl->
gRegCount);
536 g_message(
"gtkDS::cb_unix_signal_handler() %s Unix Signal Received => Shutdown Initiated!\n", psig->
signalName);
537 g_main_loop_quit(psig->
loop);
538 return ( G_SOURCE_REMOVE );
542 g_return_val_if_fail((NULL != pctrl), G_SOURCE_CONTINUE);
547 return ( G_SOURCE_CONTINUE );
551 GError *error = NULL;
552 GSocketAddress *gsRmtAddr = NULL;
553 GInetAddress *gsAddr = NULL;
554 PRegData message = NULL;
557 gchar * rmtHost = NULL;
558 gssize gss_receive = 0;
562 gchar *converted = NULL;
564 if ((condition & G_IO_HUP) || (condition & G_IO_ERR) || (condition & G_IO_NVAL)) {
565 g_message(
"gtkDS::cb_udp_broadcast_response_handler(error) Operational Error / Shutdown Signaled => %s\n",
skn_gio_condition_to_string(condition));
566 g_main_loop_quit(pctrl->
loop);
567 return ( G_SOURCE_REMOVE );
569 if (condition != G_IO_IN) {
571 return (G_SOURCE_CONTINUE);
582 gss_receive = g_socket_receive_from (gSock, &gsRmtAddr, message->
ch_message,
sizeof(message->
ch_message), NULL, &error);
584 g_error(
"g_socket_receive_from() => %s", error->message);
585 g_clear_error(&error);
588 return (G_SOURCE_CONTINUE);
590 if (gss_receive > 0 ) {
591 if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) ) {
592 gsAddr = g_inet_socket_address_get_address( G_INET_SOCKET_ADDRESS(gsRmtAddr) );
593 if ( G_IS_INET_ADDRESS(gsAddr) ) {
594 g_object_ref(gsAddr);
595 rmtHost = g_resolver_lookup_by_address (pctrl->
resolver, gsAddr, NULL, NULL);
596 if (NULL == rmtHost) {
597 rmtHost = g_inet_address_to_string ( gsAddr);
605 converted = g_convert (message->
ch_message, gss_receive,
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
606 if (NULL != converted) {
612 g_utf8_strncpy(message->
ch_from, rmtHost,
sizeof(message->
ch_from));
619 while ( msg != NULL ) {
631 g_snprintf(response,
sizeof(response),
632 "name=rpi_locator_service,ip=%s,port=48028|name=%s,ip=%s,port=%d|",
637 g_print(
"[REGISTRY] Responding to Query: %s\n", response);
639 g_socket_send_to (gSock, gsRmtAddr, response, strlen(response), NULL, &error);
641 g_error(
"g_socket_send_to() => %s", error->message);
643 g_clear_error(&error);
650 if ( G_IS_INET_ADDRESS(gsAddr) )
651 g_object_unref(gsAddr);
653 if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
654 g_object_unref(gsRmtAddr);
656 return (G_SOURCE_CONTINUE);
660 GError *error = NULL;
661 GSocketAddress *gsRmtAddr = NULL;
662 GInetAddress *gsAddr = NULL;
663 PMsgData message = NULL;
664 gchar * rmtHost = NULL;
665 gssize gss_receive = 0;
669 if ((condition & G_IO_HUP) || (condition & G_IO_ERR) || (condition & G_IO_NVAL)) {
670 g_message(
"gtkDS::cb_udp_comm_request_handler(error) Operational Error / Shutdown Signaled => %s\n",
skn_gio_condition_to_string(condition));
671 g_main_loop_quit(pctrl->
loop);
672 return ( G_SOURCE_REMOVE );
674 if (condition != G_IO_IN) {
676 return (G_SOURCE_CONTINUE);
689 gss_receive = g_socket_receive_from (gSock, &gsRmtAddr, message->
ch_message,
sizeof(message->
ch_message), NULL, &error);
691 g_error(
"g_socket_receive_from() => %s", error->message);
692 g_clear_error(&error);
694 return (G_SOURCE_CONTINUE);
696 if (gss_receive > 0 ) {
697 if (G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) ) {
698 gsAddr = g_inet_socket_address_get_address( G_INET_SOCKET_ADDRESS(gsRmtAddr) );
699 if ( G_IS_INET_ADDRESS(gsAddr) ) {
700 g_object_ref(gsAddr);
701 rmtHost = g_resolver_lookup_by_address (pctrl->
resolver, gsAddr, NULL, NULL);
702 if (NULL == rmtHost) {
703 rmtHost = g_inet_address_to_string ( gsAddr);
709 g_snprintf(response,
sizeof(response),
"%d %s", 202,
"Accepted");
712 g_snprintf(response,
sizeof(response),
"%d %s", 406,
"Not Acceptable");
717 g_socket_send_to (gSock, gsRmtAddr, response, strlen(response), NULL, &error);
719 g_error(
"g_socket_send_to() => %s", error->message);
721 g_clear_error(&error);
723 if ( G_IS_INET_ADDRESS(gsAddr) )
724 g_object_unref(gsAddr);
726 if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
727 g_object_unref(gsRmtAddr);
729 return (G_SOURCE_CONTINUE);
734 stamp = g_convert (message->
ch_message, gss_receive,
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
739 g_error(
"g_convert(udp_comm_request) => %s", error->message);
740 g_clear_error(&error);
744 if ( G_IS_INET_ADDRESS(gsAddr) )
745 g_object_unref(gsAddr);
747 if ( G_IS_INET_SOCKET_ADDRESS(gsRmtAddr) )
748 g_object_unref(gsRmtAddr);
750 return (G_SOURCE_CONTINUE);
756 g_return_val_if_fail((NULL != msg) && (NULL != pctrl), G_SOURCE_CONTINUE);
766 return(G_SOURCE_CONTINUE);
772 g_return_val_if_fail((NULL != msg) && (NULL != pctrl), G_SOURCE_CONTINUE);
782 return(G_SOURCE_CONTINUE);
788 g_return_val_if_fail((NULL != msg) && (NULL != pctrl), G_SOURCE_CONTINUE);
798 return(G_SOURCE_CONTINUE);
806 value =
"There is data to read.";
809 value =
"Data can be written (without blocking).";
812 value =
"There is urgent data to read.";
815 value =
"Error condition.";
818 value =
"Hung up (the connection has been broken, usually for pipes and sockets).";
821 value =
"Invalid request. The file descriptor is not open.";
824 value =
"Unknown GIOCondition!";
835 if (alpha == NULL || strlen(alpha) < 1)
838 int len = strlen(alpha);
843 while ( !g_unichar_isgraph(alpha[end]) && end > 0 ) {
848 while ( !g_unichar_isalnum(alpha[start]) && start < len ) {
851 if (start < len && start > 0) {
853 memmove(&alpha[0], &alpha[start], end);
872 gboolean final_rc =
FALSE;
873 gchar ** lines = NULL;
874 gchar *current_line = NULL;
875 gchar ** entries = NULL;
876 gchar *current_entry = NULL;
877 gchar ** key_value = NULL;
879 PRegData preg = NULL;
886 if (g_utf8_strchr(response, -1,
'|') == NULL) {
890 lines = g_strsplit_set(response,
"|;%", -1);
891 if ((NULL == lines) || (g_strv_length(lines) < 1)) {
895 a_count = g_strv_length(lines);
896 msgs = g_new0(PRegData, a_count);
897 for(o_index = 0; o_index < a_count; o_index += 1) {
898 msgs[o_index] = g_new0(
RegData, 1);
899 memmove(msgs[o_index], msg,
sizeof(
RegData));
903 current_line = lines[h_index];
904 while ((NULL != current_line) && (h_index < a_count)) {
905 if(g_utf8_strlen(current_line, -1) < 1) {
906 current_line = lines[++h_index];
911 entries = g_strsplit_set(current_line,
",", -1);
912 current_entry = entries[v_index];
913 e_count = g_strv_length(entries);
914 preg = msgs[o_index];
917 while((NULL != current_entry) && (v_index < e_count)) {
918 if(g_utf8_strlen(current_entry, -1) < 1) {
919 current_entry = entries[++v_index];
925 key_value = g_strsplit_set(current_entry,
"=", -1);
926 if((key_value != NULL) && (g_strv_length(key_value) > 0)) {
927 if(g_strrstr(key_value[0],
"a") != NULL) {
928 final_rc = rc =
TRUE;
931 if(g_strrstr(key_value[0],
"i") != NULL) {
932 final_rc = rc =
TRUE;
935 if(g_strrstr(key_value[0],
"o") != NULL) {
936 final_rc = rc =
TRUE;
940 g_strfreev(key_value);
941 current_entry = entries[++v_index];
944 if (rc && (g_utf8_strlen(preg->
ch_ip, -1) > 6)) {
950 current_line = lines[h_index];
955 while(o_index < a_count) {
956 g_free(msgs[o_index]);
957 msgs[o_index++] = NULL;
961 while(o_index < a_count) {
962 g_free(msgs[o_index]);
963 msgs[o_index++] = NULL;
971 GtkWidget *scrolled = NULL;
972 GtkTreeView *treeview = NULL;
973 GtkListStore *store = NULL;
974 GtkCellRenderer *renderer = NULL;
975 GtkTreeViewColumn *column = NULL;
978 gtk_box_pack_start (GTK_BOX (parent), gtk_label_new (
"Device Messages from the local Internet of Things (IOT).") ,
FALSE,
FALSE, 6);
982 scrolled = gtk_scrolled_window_new (NULL, NULL);
983 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
984 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled),GTK_SHADOW_ETCHED_OUT);
985 gtk_box_pack_start (GTK_BOX (parent), scrolled,
TRUE,
TRUE, 0);
989 store = gtk_list_store_new (
MSG_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
991 treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model (GTK_TREE_MODEL(store)));
992 gtk_tree_view_set_grid_lines(treeview, GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
995 renderer = gtk_cell_renderer_text_new ();
996 column = gtk_tree_view_column_new_with_attributes (
"Timestamp", renderer,
"text",
MSGS_COLUMN_TIMESTAMP, NULL);
998 gtk_tree_view_column_set_resizable(column,
TRUE);
999 gtk_tree_view_append_column(treeview, column);
1002 renderer = gtk_cell_renderer_text_new ();
1003 column = gtk_tree_view_column_new_with_attributes (
"Sent By", renderer,
"text",
COLUMN_NODE, NULL);
1004 gtk_tree_view_column_set_sort_column_id (column,
COLUMN_NODE);
1005 gtk_tree_view_column_set_resizable(column,
TRUE);
1006 gtk_tree_view_append_column (treeview, column);
1009 renderer = gtk_cell_renderer_text_new ();
1010 column = gtk_tree_view_column_new_with_attributes (
"Message", renderer,
"text",
COLUMN_MESSAGES, NULL);
1012 gtk_tree_view_column_set_resizable(column,
TRUE);
1013 gtk_tree_view_column_set_expand(column,
TRUE);
1014 gtk_tree_view_append_column (treeview, column);
1016 g_object_unref (store);
1018 gtk_tree_view_set_search_column(treeview,
COLUMN_NODE);
1019 gtk_tree_view_set_enable_search(treeview,
TRUE);
1021 gtk_container_add (GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
1023 gtk_widget_show_all(parent);
1024 gtk_tree_view_columns_autosize(treeview);
1026 return (GTK_WIDGET(treeview));
1030 GtkWidget *scrolled = NULL;
1031 GtkTreeView *treeview = NULL;
1032 GtkListStore *store = NULL;
1033 GtkCellRenderer *renderer = NULL;
1034 GtkTreeViewColumn *column = NULL;
1038 gtk_box_pack_start (GTK_BOX (parent), gtk_label_new (
"Raspberry Pi Network Services Registry.") ,
FALSE,
FALSE, 6);
1043 scrolled = gtk_scrolled_window_new (NULL, NULL);
1044 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1045 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled),GTK_SHADOW_ETCHED_OUT);
1046 gtk_box_pack_start (GTK_BOX (parent), scrolled,
TRUE,
TRUE, 0);
1050 store = gtk_list_store_new (
REG_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1052 treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model (GTK_TREE_MODEL(store)));
1053 gtk_tree_view_set_grid_lines(treeview, GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
1056 renderer = gtk_cell_renderer_text_new ();
1057 column = gtk_tree_view_column_new_with_attributes (
"Timestamp", renderer,
"text",
UDP_COLUMN_TIMESTAMP, NULL);
1058 gtk_tree_view_column_set_resizable(column,
TRUE);
1060 gtk_tree_view_append_column(treeview, column);
1063 renderer = gtk_cell_renderer_text_new ();
1064 column = gtk_tree_view_column_new_with_attributes (
"Reported By", renderer,
"text",
COLUMN_FROM, NULL);
1065 gtk_tree_view_column_set_sort_column_id (column,
COLUMN_FROM);
1066 gtk_tree_view_column_set_resizable(column,
TRUE);
1067 gtk_tree_view_append_column(treeview, column);
1070 renderer = gtk_cell_renderer_text_new ();
1071 column = gtk_tree_view_column_new_with_attributes (
"Service Name", renderer,
"text",
COLUMN_NAME, NULL);
1072 gtk_tree_view_column_set_sort_column_id (column,
COLUMN_NAME);
1073 gtk_tree_view_column_set_resizable(column,
TRUE);
1074 gtk_tree_view_append_column(treeview, column);
1077 renderer = gtk_cell_renderer_text_new ();
1078 column = gtk_tree_view_column_new_with_attributes (
"IP Address", renderer,
"text",
COLUMN_IP, NULL);
1079 gtk_tree_view_column_set_sort_column_id (column,
COLUMN_IP);
1080 gtk_tree_view_column_set_resizable(column,
TRUE);
1081 gtk_tree_view_append_column (treeview, column);
1084 renderer = gtk_cell_renderer_text_new ();
1085 column = gtk_tree_view_column_new_with_attributes (
"UDP Port", renderer,
"text",
COLUMN_PORT, NULL);
1086 gtk_tree_view_column_set_sort_column_id (column,
COLUMN_PORT);
1087 gtk_tree_view_column_set_resizable(column,
TRUE);
1088 gtk_tree_view_append_column (treeview, column);
1090 g_object_unref (store);
1092 gtk_tree_view_set_enable_search(treeview,
TRUE);
1093 gtk_tree_view_set_search_column (treeview,
COLUMN_NAME);
1095 gtk_container_add (GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
1097 gtk_widget_show_all(parent);
1099 gtk_tree_view_columns_autosize(treeview);
1101 return (GTK_WIDGET(treeview));
1105 GtkWidget *scrolled = NULL;
1106 GtkTreeView *treeview = NULL;
1107 GtkListStore *store = NULL;
1108 GtkCellRenderer *renderer = NULL;
1109 GtkTreeViewColumn *column = NULL;
1112 gtk_box_pack_start (GTK_BOX (parent), gtk_label_new (
"GSSDP Network Services Registry.") ,
FALSE,
FALSE, 6);
1117 scrolled = gtk_scrolled_window_new (NULL, NULL);
1118 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1119 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW (scrolled),GTK_SHADOW_ETCHED_OUT);
1120 gtk_box_pack_start (GTK_BOX (parent), scrolled,
TRUE,
TRUE, 0);
1124 store = gtk_list_store_new (
GSSDP_NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
1126 treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model (GTK_TREE_MODEL(store)));
1127 gtk_tree_view_set_grid_lines(treeview, GTK_TREE_VIEW_GRID_LINES_HORIZONTAL);
1130 renderer = gtk_cell_renderer_text_new ();
1131 column = gtk_tree_view_column_new_with_attributes (
"Timestamp", renderer,
"text",
GSSDP_COLUMN_TIMESTAMP, NULL);
1132 gtk_tree_view_column_set_resizable(column,
TRUE);
1134 gtk_tree_view_append_column(treeview, column);
1137 renderer = gtk_cell_renderer_text_new ();
1138 column = gtk_tree_view_column_new_with_attributes (
"GSSDP URN", renderer,
"text",
COLUMN_URN, NULL);
1139 gtk_tree_view_column_set_resizable(column,
TRUE);
1140 gtk_tree_view_column_set_sort_column_id (column,
COLUMN_URN);
1141 gtk_tree_view_append_column(treeview, column);
1144 renderer = gtk_cell_renderer_text_new ();
1145 column = gtk_tree_view_column_new_with_attributes (
"GSSDP Location", renderer,
"text",
COLUMN_LOCATION, NULL);
1146 gtk_tree_view_column_set_expand(column,
TRUE);
1147 gtk_tree_view_column_set_resizable(column,
TRUE);
1149 gtk_tree_view_append_column (treeview, column);
1152 renderer = gtk_cell_renderer_text_new ();
1153 column = gtk_tree_view_column_new_with_attributes (
"GSSDP Status", renderer,
"text",
COLUMN_STATUS, NULL);
1154 gtk_tree_view_column_set_resizable(column,
TRUE);
1155 gtk_tree_view_column_set_sort_column_id (column,
COLUMN_STATUS);
1156 gtk_tree_view_append_column (treeview, column);
1158 g_object_unref (store);
1160 gtk_tree_view_set_enable_search(treeview,
TRUE);
1161 gtk_tree_view_set_search_column (treeview,
COLUMN_URN);
1163 gtk_container_add (GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
1165 gtk_widget_show_all(parent);
1167 gtk_tree_view_columns_autosize(treeview);
1169 return (GTK_WIDGET(treeview));
1173 gboolean result =
TRUE;
1174 GtkListStore *store = GTK_LIST_STORE( gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)) );
1184 num_rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
1186 if ( (num_rows > 8) && (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, (num_rows -1))) ) {
1187 gtk_tree_model_unref_node(GTK_TREE_MODEL(store), &iter);
1188 gtk_list_store_remove(store, &iter);
1196 gboolean result =
TRUE;
1197 GtkListStore *store = GTK_LIST_STORE( gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)) );
1209 num_rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
1211 if ( (num_rows > 8) && (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, (num_rows -1))) ) {
1212 gtk_tree_model_unref_node(GTK_TREE_MODEL(store), &iter);
1213 gtk_list_store_remove(store, &iter);
1221 gboolean result =
TRUE;
1222 GtkListStore *store = GTK_LIST_STORE( gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)) );
1233 num_rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL);
1235 if ( (num_rows > 8) && (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter, NULL, (num_rows -1))) ) {
1236 gtk_tree_model_unref_node(GTK_TREE_MODEL(store), &iter);
1237 gtk_list_store_remove(store, &iter);
1245 GtkWidget *grid = NULL;
1246 GtkWidget *switcher = NULL;
1247 GtkWidget *stack = NULL;
1248 GtkWidget *pg1Box = NULL;
1249 GtkWidget *pg2Box = NULL;
1250 GtkWidget *pg3Box = NULL;
1253 grid = gtk_grid_new();
1255 switcher = gtk_stack_switcher_new();
1256 gtk_widget_set_hexpand (switcher,
TRUE);
1257 gtk_widget_set_halign (switcher, GTK_ALIGN_CENTER);
1258 gtk_grid_attach (GTK_GRID (grid), switcher, 0, 0, 1, 1);
1260 stack = gtk_stack_new();
1261 gtk_widget_set_hexpand (stack,
TRUE);
1262 gtk_widget_set_vexpand(stack,
TRUE);
1263 gtk_stack_set_homogeneous( GTK_STACK(stack),
TRUE);
1264 gtk_stack_set_transition_type( GTK_STACK(stack), GTK_STACK_TRANSITION_TYPE_CROSSFADE);
1265 gtk_stack_set_transition_duration( GTK_STACK(stack), 400);
1266 gtk_grid_attach (GTK_GRID (grid), stack, 0, 1, 1, 1);
1268 pg1Box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1270 gtk_stack_add_titled ( GTK_STACK(stack), GTK_WIDGET(pg1Box),
"messages",
"Messages");
1271 pg2Box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1273 gtk_stack_add_titled ( GTK_STACK(stack), GTK_WIDGET(pg2Box),
"udp_registry",
"Rpi Registry");
1274 pg3Box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1276 gtk_stack_add_titled ( GTK_STACK(stack), GTK_WIDGET(pg3Box),
"gssdp_registry",
"GSSDP Registry");
1278 gtk_stack_switcher_set_stack (GTK_STACK_SWITCHER(switcher), GTK_STACK(stack));
1279 gtk_stack_set_visible_child (GTK_STACK(stack), GTK_WIDGET(pg1Box));
1283 gtk_grid_attach (GTK_GRID (grid), pctrl->
statusBar, 0, 3, 1, 1);
1288 gtk_container_add (GTK_CONTAINER(parent), grid);
1290 gtk_widget_show_all(grid);
1298 g_message(
"gtkDS::cb_gtk_shutdown() %s Destroy Signal Received => Shutdown Initiated!\n", psig->
signalName);
1299 g_main_loop_quit(psig->
loop);
1304 PGSSDPRegData msg = NULL;
1306 gchar *converted = NULL;
1308 g_warn_if_fail(NULL != pctrl);
1316 converted = g_convert (usn, g_utf8_strlen(usn, -1),
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
1317 if (NULL != converted) {
1318 g_utf8_strncpy(msg->
ch_urn, converted,
sizeof(msg->
ch_urn));
1324 converted = g_convert (locations->data, g_utf8_strlen(locations->data, -1),
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
1325 if (NULL != converted) {
1338 PGSSDPRegData msg = NULL;
1340 gchar *converted = NULL;
1342 g_warn_if_fail(NULL != pctrl);
1350 converted = g_convert (usn, g_utf8_strlen(usn, -1),
"UTF-8",
"ISO-8859-1", NULL, NULL, NULL);
1351 if (NULL != converted) {
1352 g_utf8_strncpy(msg->
ch_urn, converted,
sizeof(msg->
ch_urn));
1365 GError *error = NULL;
1371 g_printerr (
"Error creating the GSSDP gssdp_client for resource_group: %s\n", error->message);
1372 g_error_free (error);
1378 g_snprintf(ch_buffer,
sizeof(ch_buffer),
"http://%s/", pctrl->
ch_this_ip );
1379 gssdp_resource_group_add_resource_simple
1382 "uuid:80e6e2b7-fa4a-4d06-820a-406d5ecbbe51::upnp:rootdevice",
1385 g_snprintf(ch_buffer,
sizeof(ch_buffer),
"udp://%s:%d", pctrl->
ch_this_ip, udp_port );
1386 gssdp_resource_group_add_resource_simple
1389 "uuid:21798cdc-d875-42b9-bb52-8043e6396301::urn:schemas-upnp-org:service:GtkDisplayService:1",
1414 GError *error = NULL;
1415 GMainLoop *loop = NULL;
1416 GSocket *gSock = NULL;
1417 GSocketAddress *gsAddr = NULL;
1418 GSource * gCommSource = NULL;
1419 GSocketAddress *gbAddr = NULL;
1420 GSource * gBroadSource = NULL;
1421 GSource * gMsgSource = NULL;
1422 GSource * gRegSource = NULL;
1423 GSource * gGSSDPRegSource = NULL;
1425 PIPBroadcastArray paB = NULL;
1426 GInetAddress *anyAddr = NULL;
1431 GtkWidget *window = NULL;
1433 GOptionContext *gOptions = NULL;
1434 GOptionEntry pgmOptions[] = {
1436 {
"udp_port_number",
'p',
G_OPTION_FLAG_NONE, G_OPTION_ARG_INT, &gUDPPort,
"UDP Port Number to listen on. default=48029",
"48029"},
1437 {
"small",
's',
G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &cData.
gSmall,
"Small Screen mode, reduced status and titles.", NULL},
1445 gOptions = g_option_context_new (
"UDP message display service for IOT.");
1446 g_option_context_add_group (gOptions, (GOptionGroup *) gtk_get_option_group(
TRUE) );
1447 g_option_context_add_main_entries (gOptions, pgmOptions, NULL);
1449 g_option_context_parse (gOptions, &argc, &argv, &error);
1450 if (error != NULL) {
1451 g_error(
"g_option_context_parse() => %s", error->message);
1452 g_clear_error(&error);
1455 g_option_context_free(gOptions);
1457 if (gUDPPort == 0) {
1471 g_error(
"skn_skn_get_default_interface_name_and_ipv4_address() => Unable to discover network interface or non-available.");
1480 cData.
resolver = g_resolver_get_default();
1492 g_source_ref(gMsgSource);
1494 cData.
gMsgSourceId = g_source_attach (gMsgSource, NULL);
1497 g_source_ref(gRegSource);
1499 cData.
gRegSourceId = g_source_attach (gRegSource, NULL);
1502 g_source_ref(gGSSDPRegSource);
1508 gSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
1509 if (error != NULL) {
1510 g_error(
"g_socket_new() => %s", error->message);
1511 g_clear_error(&error);
1515 anyAddr = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
1516 gsAddr = g_inet_socket_address_new(anyAddr, gUDPPort);
1518 g_socket_bind(gSock, gsAddr,
TRUE, &error);
1519 if (error != NULL) {
1520 g_error(
"g_socket_bind() => %s", error->message);
1521 g_clear_error(&error);
1525 gCommSource = g_socket_create_source (gSock, G_IO_IN, NULL);
1526 g_source_ref(gCommSource);
1532 cData.
gbSock = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &error);
1533 if (error != NULL) {
1534 g_error(
"g_socket_new(broadcast) => %s", error->message);
1535 g_clear_error(&error);
1541 g_object_unref(anyAddr);
1543 g_socket_bind(cData.
gbSock, gbAddr,
TRUE, &error);
1544 if (error != NULL) {
1545 g_error(
"g_socket_bind() => %s", error->message);
1546 g_clear_error(&error);
1550 gBroadSource = g_socket_create_source(cData.
gbSock, G_IO_IN, NULL);
1551 g_source_ref(gBroadSource);
1560 g_unix_signal_add (SIGTERM,(GSourceFunc) cb_unix_signal_handler, &sigTerm);
1561 g_unix_signal_add (SIGHUP, (GSourceFunc) cb_unix_signal_handler, &sigHup);
1565 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1566 gtk_window_set_title (GTK_WINDOW (window),
"Gtk Display Service");
1567 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1568 gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
1569 g_signal_connect(G_OBJECT(window),
"destroy", G_CALLBACK(
cb_gtk_shutdown), &winDestroy);
1575 gtk_widget_show_all(GTK_WIDGET(window));
1581 g_message(
"gtkDS: Ready to do Good, on %s:%s:%d...\n", cData.
ch_intfName, cData.
ch_this_ip, gUDPPort);
1583 g_main_loop_run(loop);
1589 g_source_unref(gCommSource);
1590 g_source_unref(gBroadSource);
1591 g_source_unref(gRegSource);
1592 g_source_unref(gMsgSource);
1593 g_source_unref(gGSSDPRegSource);
1594 g_object_unref(gSock);
1595 g_object_unref(cData.
gbSock);
1596 g_object_unref(gsAddr);
1597 g_object_unref(gbAddr);
1606 g_main_loop_unref(loop);
1608 g_message(
"gtkDS: shutdown...");
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gboolean ui_add_message_entry(GtkWidget *treeview, PMsgData msg, gboolean limiter)
struct _registryData RegData
struct _ipBroadcastArray * PIPBroadcastArray
GSSDPResourceBrowser * resource_browser
struct _gssdpRegistryData * PGSSDPRegData
#define UDP_BROADCAST_PORT
gint skn_get_default_interface_name(char *pchDefaultInterfaceName)
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gchar ch_timestamp[SZ_TIMESTAMP_BUFF]
GDestroyNotify destroy_message
struct _ipBroadcastArray IPBroadcastArray
char maskAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
gchar ch_ip[SZ_PARAMS_BUFF]
GAsyncQueue * queueMessage
GAsyncQueue * queueGSSDPRegistry
static gboolean message_queue_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
gchar ch_message[SZ_MESSAGE_BUFF]
static gboolean cb_message_request_handler(PMsgData msg, PControlData pctrl)
gchar ch_timestamp[SZ_TIMESTAMP_BUFF]
GtkWidget * ui_registry_page_new(GtkWidget *parent, guint gSmall)
gchar * skn_gio_condition_to_string(GIOCondition condition)
gchar * skn_strip(gchar *alpha)
char cbName[SZ_CHAR_BUFF]
gchar ch_remoteAddress[SZ_RMTADDR_BUFF]
gchar ch_port[SZ_PARAMS_BUFF]
gboolean ui_add_registry_entry(GtkWidget *treeview, PRegData msg, gboolean limiter)
static gboolean cb_udp_broadcast_response_handler(GSocket *gSock, GIOCondition condition, PControlData pctrl)
#define SZ_TIMESTAMP_BUFF
guint ui_update_status_bar(PControlData pctrl)
gboolean(* MessageQueueSourceFunc)(gpointer message, gpointer user_data)
int main(int argc, char **argv)
static gboolean cb_unix_signal_handler(PUSignalData psig)
gboolean gssdp_browse(PControlData pctrl)
gboolean gssdp_publish(PControlData pctrl, guint udp_port)
static GSourceFuncs message_queue_source_funcs
gchar ch_status[SZ_PARAMS_BUFF]
static void cb_gssdp_resource_unavailable(GSSDPResourceBrowser *resource_browser, const char *usn, PControlData pctrl)
static void cb_gtk_shutdown(GtkWidget *object, gpointer data)
#define G_OPTION_FLAG_NONE
struct _registryData ** PPRegData
gchar ch_name[SZ_RMTADDR_BUFF]
gchar ch_urn[SZ_RMTADDR_BUFF]
PPRegData udp_registry_response_parser(PRegData msg, gchar *response)
PIPBroadcastArray skn_get_default_interface_name_and_ipv4_address(char *intf, char *ipv4)
struct _messageData MsgData
gchar ch_this_ip[SZ_RMTADDR_BUFF]
static gboolean cb_registry_refresh(PControlData pctrl)
gchar ch_message[SZ_MESSAGE_BUFF]
struct _controlData ControlData
char chDefaultIntfName[SZ_CHAR_BUFF]
static gboolean cb_gssdp_registry_request_handler(PGSSDPRegData msg, PControlData pctrl)
struct _controlData * PControlData
#define SKN_SMALL_DISPLAY_MODE_OFF
static void message_queue_source_finalize(GSource *source)
struct _signalData * PUSignalData
gboolean ui_add_gssdp_registry_entry(GtkWidget *treeview, PGSSDPRegData msg, gboolean limiter)
static gboolean message_queue_source_prepare(GSource *source, gint *timeout_)
GAsyncQueue * queueRegistry
gchar ch_from[SZ_RMTADDR_BUFF]
GtkWidget * ui_page_layout(GtkWidget *parent, PControlData pctrl)
static gboolean message_queue_source_closure_callback(gpointer message, gpointer user_data)
struct _registryData * PRegData
struct _signalData USignalData
enum _registry EUDPRegistry
GSource * message_queue_source_new(GAsyncQueue *queue, GDestroyNotify destroy_message, GCancellable *cancellable)
struct _gssdpRegistryData GSSDPRegData
static void cb_gssdp_resource_available(GSSDPResourceBrowser *resource_browser, const char *usn, GList *locations, PControlData pctrl)
gchar ch_location[SZ_RMTADDR_BUFF]
gchar ch_timestamp[SZ_TIMESTAMP_BUFF]
static gboolean cb_udp_comm_request_handler(GSocket *socket, GIOCondition condition, PControlData pctrl)
GtkWidget * ui_message_page_new(GtkWidget *parent, guint gSmall)
char broadAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
GSSDPResourceGroup * resource_group
GtkWidget * ui_gssdp_registry_page_new(GtkWidget *parent, guint gSmall)
enum _gssdp_registry EGSSDPRegistry
gint skn_get_broadcast_ip_array(PIPBroadcastArray paB)
#define MAX_MESSAGES_VIEWABLE
struct _messageData * PMsgData
gboolean skn_udp_network_broadcast_all_interfaces(GSocket *gSock, PIPBroadcastArray pab)
gchar * skn_get_timestamp()
GSSDPClient * gssdp_rgroup_client
gchar ch_intfName[SZ_RMTADDR_BUFF]
static gboolean cb_registry_request_handler(PRegData msg, PControlData pctrl)