RPi Locator and Display Services
skn_network_helpers.c File Reference
+ Include dependency graph for skn_network_helpers.c:

Go to the source code of this file.

Functions

static void skn_locator_print_usage ()
 
static void exit_handler (int sig)
 
static void * service_registry_entry_create_helper (char *key, char **name, char **ip, char **port)
 
static PServiceRegistry service_registry_create ()
 
static int service_registry_entry_create (PServiceRegistry psreg, char *name, char *ip, char *port, int *errors)
 
static int service_registry_response_parse (PServiceRegistry psreg, const char *response, int *errors)
 
long skn_get_number_of_cpu_cores ()
 
int generate_loadavg_info (char *msg)
 
int generate_uname_info (char *msg)
 
int generate_datetime_info (char *msg)
 
int skn_time_delay (double delay_time)
 
uid_t skn_get_userids ()
 
void signals_init ()
 
void signals_cleanup (int sig)
 
void get_default_interface_name_and_ipv4_address (char *intf, char *ipv4)
 
int get_broadcast_ip_array (PIPBroadcastArray paB)
 
int get_default_interface_name (char *pchDefaultInterfaceName)
 
int skn_handle_locator_command_line (int argc, char **argv)
 
void skn_program_name_and_description_set (const char *name, const char *desc)
 
char * skn_strip (char *alpha)
 
int skn_udp_host_create_regular_socket (int port, double rcvTimeout)
 
int skn_udp_host_create_broadcast_socket (int port, double rcvTimeout)
 
PServiceRequest skn_service_request_create (PRegistryEntry pre, int host_socket, char *request)
 
double skn_duration_in_milliseconds (struct timeval *pstart, struct timeval *pend)
 
int skn_udp_service_request (PServiceRequest psr)
 
int service_registry_provider (int i_socket, char *response)
 
int service_registry_valiadate_response_format (const char *response)
 
PServiceRegistry service_registry_valiadated_registry (const char *response)
 
void service_registry_entry_response_message_log (const char *response)
 
PRegistryEntry service_registry_find_entry (PServiceRegistry psreg, char *serviceName)
 
int service_registry_entry_count (PServiceRegistry psr)
 
int service_registry_list_entries (PServiceRegistry psr)
 
void * service_registry_get_entry_field_ref (PRegistryEntry prent, char *field)
 
PServiceRegistry service_registry_get_via_udp_broadcast (int i_socket, char *request)
 
void service_registry_destroy (PServiceRegistry psreg)
 

Variables

sig_atomic_t gi_exit_flag = SKN_RUN_MODE_RUN
 
char * gd_pch_message = NULL
 
signed int gd_i_debug = 0
 
char gd_ch_program_name [SZ_INFO_BUFF]
 
char gd_ch_program_desc [SZ_INFO_BUFF]
 
char * gd_pch_effective_userid = NULL
 
int gd_i_socket = -1
 
int gd_i_display = 0
 
int gd_i_update = 0
 
int gd_i_unique_registry = 0
 
char gd_ch_ipAddress [SZ_CHAR_BUFF]
 
char gd_ch_intfName [SZ_CHAR_BUFF]
 
char gd_ch_hostName [SZ_CHAR_BUFF]
 
char gd_ch_hostShortName [SZ_CHAR_BUFF]
 
char * gd_pch_service_name
 
int gd_i_i2c_address = 0
 

Function Documentation

static void exit_handler ( int  sig)
static

Control-C Program exit ref: http://www.cons.org/cracauer/sigint.html http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_21.html#SEC361

Definition at line 174 of file skn_network_helpers.c.

References gi_exit_flag, and SD_NOTICE.

Referenced by signals_init().

174  {
175  gi_exit_flag = sig;
176  skn_logger(SD_NOTICE, "Program Exiting, from signal=%d:%s\n", sig, strsignal(sig));
177 }
sig_atomic_t gi_exit_flag
#define SD_NOTICE

+ Here is the caller graph for this function:

int generate_datetime_info ( char *  msg)

Definition at line 78 of file skn_network_helpers.c.

References SZ_INFO_BUFF, and TZ_ADJUST.

Referenced by main(), and skn_display_manager_do_work().

78  {
79  int mLen = 0;
80  struct tm *t;
81  time_t tim;
82 
83  tim = time(NULL);
84  t = localtime(&tim);
85 
86  mLen = snprintf(msg, SZ_INFO_BUFF -1, "%02d:%02d:%04d %02d:%02d:%02d",
87  t->tm_mon + 1, t->tm_mday, t->tm_year + 1900,
88  ((t->tm_hour - TZ_ADJUST) < 0 ? (t->tm_hour - TZ_ADJUST + 12) : (t->tm_hour - TZ_ADJUST)), t->tm_min, t->tm_sec);
89 
90  return mLen;
91 }
#define SZ_INFO_BUFF
Definition: cmdDC.c:56
#define TZ_ADJUST

+ Here is the caller graph for this function:

int generate_loadavg_info ( char *  msg)

Definition at line 45 of file skn_network_helpers.c.

References PLATFORM_ERROR, and SZ_INFO_BUFF.

Referenced by main(), and skn_display_manager_do_work().

45  {
46  double loadavg[4];
47  int rc = 0;
48 
49  rc = getloadavg(loadavg, 3);
50 
51  if (rc != PLATFORM_ERROR) {
52  snprintf(msg, SZ_INFO_BUFF -1, "LoadAvg: 1m=%2.1f, 5m=%2.1f, 15m=%2.1F",
53  loadavg[0], loadavg[1], loadavg[2]);
54  } else {
55  snprintf(msg, SZ_INFO_BUFF -1, "Load Average: Not Available %d:%d:%s",
56  rc, errno, strerror(errno));
57  }
58 
59  return rc;
60 }
#define PLATFORM_ERROR
Definition: cmdDC.c:63
#define SZ_INFO_BUFF
Definition: cmdDC.c:56

+ Here is the caller graph for this function:

int generate_uname_info ( char *  msg)

Definition at line 62 of file skn_network_helpers.c.

References skn_get_number_of_cpu_cores(), and SZ_INFO_BUFF.

Referenced by main(), and skn_display_manager_do_work().

62  {
63  struct utsname info;
64 
65  int mLen = 0;
66  char * message = "uname() api failed.";
67 
68  if (uname(&info) != 0) {
69  mLen = snprintf(msg, SZ_INFO_BUFF -1, "%s", message);
70  } else {
71  mLen = snprintf(msg, SZ_INFO_BUFF -1, "%s %s, %s %s | Cores=%ld",
72  info.sysname, info.release, info.version, info.machine,
74  }
75  return mLen;
76 }
long skn_get_number_of_cpu_cores()
#define SZ_INFO_BUFF
Definition: cmdDC.c:56

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int 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 214 of file skn_network_helpers.c.

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

Referenced by get_default_interface_name_and_ipv4_address(), service_registry_get_via_udp_broadcast(), service_registry_provider(), and skn_display_manager_message_consumer_thread().

214  {
215  struct ifaddrs * ifap;
216  struct ifaddrs * p;
217  int rc = 0;
218 
219  memset(paB, 0, sizeof(IPBroadcastArray));
220  paB->count = 0;
221  paB->defaultIndex = 0;
222  strcpy(paB->cbName, "IPBroadcastArray");
223 
225  if (rc == EXIT_FAILURE) { // Alternate method for Mac: 'route -n -A inet'
226  skn_logger(SD_ERR, "No Default Network Interfaces Found!.");
227  paB->chDefaultIntfName[0] = 0;
228  }
229  rc = getifaddrs(&ifap);
230  if (rc != 0) {
231  skn_logger(SD_ERR, "No Network Interfaces Found at All ! %d:%d:%s", rc, errno, strerror(errno) );
232  return (PLATFORM_ERROR);
233  }
234  p = ifap;
235 
236  while (p && paB->count < ARY_MAX_INTF) {
237  if (p->ifa_addr != NULL && p->ifa_addr->sa_family == AF_INET && ((p->ifa_flags & IFF_BROADCAST) > 0)) {
238 
239  inet_ntop(p->ifa_addr->sa_family, &((struct sockaddr_in *) p->ifa_addr)->sin_addr, paB->ipAddrStr[paB->count], (SZ_CHAR_BUFF - 1));
240  inet_ntop(p->ifa_addr->sa_family, &((struct sockaddr_in *) p->ifa_netmask)->sin_addr, paB->maskAddrStr[paB->count], (SZ_CHAR_BUFF - 1));
241  inet_ntop(p->ifa_addr->sa_family, &((struct sockaddr_in *) p->ifa_broadaddr)->sin_addr, paB->broadAddrStr[paB->count], (SZ_CHAR_BUFF - 1));
242 
243  strncpy(paB->ifNameStr[paB->count], p->ifa_name, (SZ_CHAR_BUFF -1));
244 
245  /* Take match as the default */
246  if (strcmp(paB->chDefaultIntfName, p->ifa_name) == 0) {
247  paB->defaultIndex = paB->count;
248  }
249 
250  paB->count++;
251  }
252  p = p->ifa_next;
253  } // end while
254  freeifaddrs(ifap);
255 
256  return paB->count;
257 }
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:68
#define ARY_MAX_INTF
Definition: cmdDC.c:62
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:69
#define PLATFORM_ERROR
Definition: cmdDC.c:63
char maskAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:70
#define SZ_CHAR_BUFF
Definition: cmdDC.c:57
char cbName[SZ_CHAR_BUFF]
Definition: cmdDC.c:66
#define SD_ERR
int defaultIndex
Definition: cmdDC.c:72
int get_default_interface_name(char *pchDefaultInterfaceName)
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:

int 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 275 of file skn_network_helpers.c.

References SD_ERR, skn_strip(), and SZ_INFO_BUFF.

Referenced by get_broadcast_ip_array().

275  {
276  FILE *f_route;
277  char line[SZ_INFO_BUFF], *dRoute = NULL, *iName = NULL;
278 
279  f_route = fopen("/proc/net/route", "r");
280  if (f_route != NULL) {
281  while (fgets(line, SZ_INFO_BUFF - 1, f_route)) {
282  iName = strtok(line, "\t");
283  dRoute = strtok(NULL, "\t");
284 
285  if (iName != NULL && dRoute != NULL) {
286  if (strcmp(dRoute, "00000000") == 0) {
287  strncpy(pchDefaultInterfaceName, iName, (SZ_INFO_BUFF - 1));
288  break;
289  }
290  }
291  }
292  fclose(f_route);
293 
294  return EXIT_SUCCESS;
295  }
296  skn_logger(SD_ERR, "Opening ProcFs for RouteInfo Failed: %d:%s, Alternate method will be attempted.", errno, strerror(errno));
297 
298  f_route = popen("route -n get 0.0.0.0", "r"); // for linux 'route -n -A inet', with interface at line_word[7]
299  if (f_route != NULL) {
300  while (fgets(line, SZ_INFO_BUFF - 1, f_route)) {
301  dRoute = strtok(line, ":");
302  iName = strtok(NULL, "\n");
303  if (strcmp(skn_strip(dRoute), "interface") == 0) {
304  strncpy(pchDefaultInterfaceName, skn_strip(iName), (SZ_INFO_BUFF - 1));
305  break;
306  }
307  }
308  fclose(f_route);
309 
310  return EXIT_SUCCESS;
311  } else {
312  skn_logger(SD_ERR, "Alternate method to get RouteInfo Failed: %d:%s", errno, strerror(errno));
313  return EXIT_FAILURE;
314  }
315 
316 }
#define SD_ERR
#define SZ_INFO_BUFF
Definition: cmdDC.c:56
char * skn_strip(char *alpha)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void get_default_interface_name_and_ipv4_address ( char *  intf,
char *  ipv4 
)

Definition at line 196 of file skn_network_helpers.c.

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

Referenced by main().

196  {
197  IPBroadcastArray aB;
198 
200  memcpy(intf, aB.chDefaultIntfName, SZ_CHAR_BUFF);
201  memcpy(ipv4, aB.ipAddrStr[aB.defaultIndex], SZ_CHAR_BUFF);
202  } else {
203  skn_logger(SD_ERR, "InterfaceName and Address: unable to access information.");
204  }
205 }
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:69
#define PLATFORM_ERROR
Definition: cmdDC.c:63
#define SZ_CHAR_BUFF
Definition: cmdDC.c:57
#define SD_ERR
int defaultIndex
Definition: cmdDC.c:72
char chDefaultIntfName[SZ_CHAR_BUFF]
Definition: cmdDC.c:67
int get_broadcast_ip_array(PIPBroadcastArray paB)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PServiceRegistry service_registry_create ( )
static

service_registry_create()

  • Collection of Services and their locations
  • Returns the Registry

Definition at line 797 of file skn_network_helpers.c.

References _serviceRegistry::cbName, _serviceRegistry::computedMax, _serviceRegistry::count, and _serviceRegistry::entry.

Referenced by service_registry_get_via_udp_broadcast(), service_registry_valiadate_response_format(), and service_registry_valiadated_registry().

797  {
798  PServiceRegistry psreg = NULL;
799 
800  psreg = (PServiceRegistry) malloc(sizeof(ServiceRegistry));
801  if (psreg != NULL) {
802  memset(psreg, 0, sizeof(ServiceRegistry));
803  strcpy(psreg->cbName, "PServiceRegistry");
804  psreg->computedMax = (sizeof(psreg->entry) / sizeof(void *));
805  psreg->count = 0;
806  }
807 
808  return psreg;
809 }
struct _serviceRegistry * PServiceRegistry
char cbName[SZ_CHAR_BUFF]
PRegistryEntry entry[ARY_MAX_REGISTRY]

+ Here is the caller graph for this function:

void service_registry_destroy ( PServiceRegistry  psreg)

service_registry_destroy()

  • Free each entry, then the Registry itself.

Definition at line 1159 of file skn_network_helpers.c.

References _serviceRegistry::count, and _serviceRegistry::entry.

Referenced by main(), and service_registry_valiadate_response_format().

1159  {
1160  int index = 0;
1161 
1162  if (psreg == NULL)
1163  return;
1164 
1165  for (index = 0; index < psreg->count; index++) {
1166  free(psreg->entry[index]);
1167  }
1168  free(psreg);
1169 }
PRegistryEntry entry[ARY_MAX_REGISTRY]

+ Here is the caller graph for this function:

int service_registry_entry_count ( PServiceRegistry  psr)

Returns the number of services in registry

Definition at line 947 of file skn_network_helpers.c.

References _serviceRegistry::count.

Referenced by main().

947  {
948  return psr->count;
949 }

+ Here is the caller graph for this function:

static int service_registry_entry_create ( PServiceRegistry  psreg,
char *  name,
char *  ip,
char *  port,
int *  errors 
)
static

service_registry_entry_create()

  • Create a Service Entry and adds it to the Registry collection
  • Returns EXIT_FAILURE/SUCCESS

Definition at line 817 of file skn_network_helpers.c.

References _serviceEntry::cbName, _serviceRegistry::computedMax, _serviceRegistry::count, _serviceRegistry::entry, gd_i_unique_registry, _serviceEntry::ip, _serviceEntry::name, _serviceEntry::port, SD_DEBUG, SD_WARNING, and service_registry_find_entry().

Referenced by service_registry_response_parse().

817  {
818  PRegistryEntry prent = NULL;
819 
820  if ((psreg == NULL) || (name == NULL) || (ip == NULL) || (port == NULL)) {
821  skn_logger(SD_DEBUG, "Parse failure missing value: (%s,%s,%s)", name, ip, port);
822  if (errors != NULL)
823  (*errors)++;
824  return EXIT_FAILURE;
825  }
826 
827  if (psreg->count >= psreg->computedMax) {
828  skn_logger(SD_WARNING, "Capacity Error: Too many! New entry %d:%s exceeds maximum of %d allowed! Consider using the --unique-registry option.", psreg->count, name, psreg->computedMax);
829  if (errors != NULL)
830  (*errors)++;
831  return EXIT_FAILURE;
832  }
833 
834  /* update or create entry */
835  if (gd_i_unique_registry) {
836  prent = service_registry_find_entry(psreg, name);
837  }
838  if (prent == NULL) {
839  prent = (PRegistryEntry) malloc(sizeof(RegistryEntry));
840  if (prent != NULL) {
841  psreg->entry[psreg->count] = prent;
842  psreg->count++;
843  }
844  }
845 
846  if (prent != NULL) {
847  memset(prent, 0, sizeof(RegistryEntry));
848  strcpy(prent->cbName, "PRegistryEntry");
849  strcpy(prent->name, name);
850  strcpy(prent->ip, ip);
851  prent->port = atoi(port);
852  } else {
853  skn_logger(SD_WARNING, "Internal Memory Error: Could not allocate memory for entry %d:%s !", name, psreg->count);
854  if (errors != NULL)
855  (*errors)++;
856 
857  return EXIT_FAILURE;
858  }
859 
860  return psreg->count;
861 }
#define SD_DEBUG
int port
int gd_i_unique_registry
#define SD_WARNING
char name[SZ_INFO_BUFF]
char cbName[SZ_CHAR_BUFF]
struct _serviceEntry * PRegistryEntry
char ip[SZ_INFO_BUFF]
PRegistryEntry service_registry_find_entry(PServiceRegistry psreg, char *serviceName)
PRegistryEntry entry[ARY_MAX_REGISTRY]

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void * service_registry_entry_create_helper ( char *  key,
char **  name,
char **  ip,
char **  port 
)
static

service_registry_entry_create_helper()

  • Determines which field should be updated
  • compute the address of each field on demand, from local vars
  • Returns the address offset of the registry field requested

Definition at line 993 of file skn_network_helpers.c.

References skn_strip().

Referenced by service_registry_response_parse().

993  {
994  int index = 0;
995  char * guess = NULL;
996  void * result = NULL;
997  char * names[4] = { "name", "ip", "port", NULL };
998  void * offsets[] = { name, ip, port, NULL };
999 
1000  skn_strip(key); // cleanup first
1001  for (index = 0; names[index] != NULL; index++) { // find direct match
1002  if (strcmp(names[index], key) == 0) {
1003  result = offsets[index];
1004  break;
1005  }
1006  }
1007  if (result == NULL) { // try to guess what the key is
1008  if ((guess = strstr(key, "e")) != NULL) {
1009  result = offsets[0];
1010  } else if ((guess = strstr(key, "i")) != NULL) {
1011  result = offsets[1];
1012  } else if ((guess = strstr(key, "t")) != NULL) {
1013  result = offsets[2];
1014  }
1015  }
1016 
1017  return result;
1018 }
char * skn_strip(char *alpha)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void service_registry_entry_response_message_log ( const char *  response)

service_registry_entry_response_message_log()

  • Prints each pair of values from a text registry entry

Definition at line 907 of file skn_network_helpers.c.

References SD_NOTICE.

Referenced by main(), and service_registry_provider().

907  {
908  char * worker = NULL, *parser = NULL, *base = strdup(response);
909  parser = base;
910  skn_logger(SD_NOTICE, "Response Message:");
911  while (( ((worker = strsep(&parser, "|")) != NULL) ||
912  ((worker = strsep(&parser, "%")) != NULL) ||
913  ((worker = strsep(&parser, ";")) != NULL)) &&
914  (strlen(worker) > 8)) {
915  skn_logger(SD_NOTICE, "[%s]", worker);
916  }
917  free(base);
918 }
#define SD_NOTICE

+ Here is the caller graph for this function:

PRegistryEntry service_registry_find_entry ( PServiceRegistry  psreg,
char *  serviceName 
)

service_registry_find_entry()

  • Finds an existing entry
  • Returns EXIT_FAILURE/SUCCESS

Definition at line 926 of file skn_network_helpers.c.

References _serviceRegistry::entry, and _serviceEntry::name.

Referenced by main(), and service_registry_entry_create().

926  {
927  PRegistryEntry prent = NULL;
928  int index = 0;
929 
930  if (psreg == NULL)
931  return NULL;
932 
933  while (index < psreg->count) {
934  if (strcmp(serviceName, psreg->entry[index]->name) == 0) {
935  prent = psreg->entry[index];
936  break;
937  }
938  index++;
939  }
940 
941  return prent;
942 }
char name[SZ_INFO_BUFF]
PRegistryEntry entry[ARY_MAX_REGISTRY]

+ Here is the caller graph for this function:

void* service_registry_get_entry_field_ref ( PRegistryEntry  prent,
char *  field 
)

service_registry_get_entry_field_ref()

  • compute the address of each field on demand, from struct
  • Returns the address offset of the registry field requested

Definition at line 969 of file skn_network_helpers.c.

969  {
970  int index = 0;
971  void * result = NULL;
972  char * names[4] = { "name", "ip", "port", NULL };
973  int offsets[4] = { offsetof(RegistryEntry, name),
974  offsetof(RegistryEntry, ip),
975  offsetof(RegistryEntry, port),
976  0
977  };
978  for (index = 0; names[index] != NULL; index++) {
979  if (strcmp(names[index], field) == 0) {
980  result = (void *) prent + offsets[index];
981  break;
982  }
983  }
984  return result;
985 }
PServiceRegistry service_registry_get_via_udp_broadcast ( int  i_socket,
char *  request 
)

service_registry_get_via_udp_broadcast()

  • Retrieves entries from every service that responds to the broadcast parses and builds a new Registry of all entries, or unique entries.
  • Returns Populated Registry

Definition at line 1094 of file skn_network_helpers.c.

References _ipBroadcastArray::broadAddrStr, _ipBroadcastArray::chDefaultIntfName, _ipBroadcastArray::count, _ipBroadcastArray::defaultIndex, gd_ch_intfName, gd_ch_ipAddress, get_broadcast_ip_array(), gi_exit_flag, _ipBroadcastArray::ifNameStr, _ipBroadcastArray::ipAddrStr, PLATFORM_ERROR, SD_DEBUG, SD_EMERG, SD_NOTICE, SD_WARNING, service_registry_create(), service_registry_response_parse(), skn_duration_in_milliseconds(), SKN_FIND_RPI_PORT, SKN_RUN_MODE_RUN, SZ_CHAR_BUFF, and SZ_INFO_BUFF.

Referenced by main().

1094  {
1095  struct sockaddr_in remaddr; /* remote address */
1096  socklen_t addrlen = sizeof(remaddr); /* length of addresses */
1097  IPBroadcastArray aB;
1098  int vIndex = 0;
1099  char response[SZ_INFO_BUFF];
1100  char recvHostName[SZ_INFO_BUFF];
1101  signed int rLen = 0;
1102  struct timeval start;
1103 
1104  memset(response, 0, sizeof(response));
1105  memset(recvHostName, 0, sizeof(recvHostName));
1106 
1110 
1111  skn_logger(SD_NOTICE, "Socket Bound to %s", aB.ipAddrStr[aB.defaultIndex]);
1112 
1113  gettimeofday(&start, NULL);
1114  for (vIndex = 0; vIndex < aB.count; vIndex++) {
1115  memset(&remaddr, 0, sizeof(remaddr));
1116  remaddr.sin_family = AF_INET;
1117  remaddr.sin_addr.s_addr = inet_addr(aB.broadAddrStr[vIndex]);
1118  remaddr.sin_port = htons(SKN_FIND_RPI_PORT);
1119 
1120  if (sendto(i_socket, request, strlen(request), 0, (struct sockaddr *) &remaddr, addrlen) < 0) {
1121  skn_logger(SD_WARNING, "SendTo() Timed out; Failure code=%d, etext=%s", errno, strerror(errno));
1122  break;
1123  }
1124  skn_logger(SD_NOTICE, "Message Broadcasted on %s:%s:%d", aB.ifNameStr[vIndex], aB.broadAddrStr[vIndex], SKN_FIND_RPI_PORT);
1125  }
1126 
1128  skn_logger(SD_DEBUG, "Waiting for all responses\n");
1129  while (gi_exit_flag == SKN_RUN_MODE_RUN) { // depends on a socket timeout of 5 seconds
1130 
1131  rLen = recvfrom(i_socket, response, (SZ_INFO_BUFF - 1), 0, (struct sockaddr *) &remaddr, &addrlen);
1132  if (rLen == PLATFORM_ERROR) { // EAGAIN
1133  break;
1134  }
1135  response[rLen] = 0;
1136 
1137  rLen = getnameinfo(((struct sockaddr *) &remaddr), sizeof(struct sockaddr_in), recvHostName, (SZ_INFO_BUFF -1), NULL, 0, NI_DGRAM);
1138  if (rLen != 0) {
1139  skn_logger(SD_EMERG, "getnameinfo() failed: %s\n", gai_strerror(rLen));
1140  break;
1141  }
1142 
1143  skn_logger(SD_DEBUG, "Response(%1.3fs) received from %s @ %s:%d",
1144  skn_duration_in_milliseconds(&start, NULL),
1145  recvHostName,
1146  inet_ntoa(remaddr.sin_addr),
1147  ntohs(remaddr.sin_port)
1148  );
1149  service_registry_response_parse(psr, response, NULL);
1150  }
1151 
1152  return (psr);
1153 }
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:68
double skn_duration_in_milliseconds(struct timeval *pstart, struct timeval *pend)
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:69
#define PLATFORM_ERROR
Definition: cmdDC.c:63
#define SD_DEBUG
char gd_ch_intfName[SZ_CHAR_BUFF]
#define SZ_CHAR_BUFF
Definition: cmdDC.c:57
static int service_registry_response_parse(PServiceRegistry psreg, const char *response, int *errors)
#define SD_WARNING
#define SD_EMERG
#define SZ_INFO_BUFF
Definition: cmdDC.c:56
int defaultIndex
Definition: cmdDC.c:72
char chDefaultIntfName[SZ_CHAR_BUFF]
Definition: cmdDC.c:67
#define SKN_RUN_MODE_RUN
sig_atomic_t gi_exit_flag
#define SD_NOTICE
int get_broadcast_ip_array(PIPBroadcastArray paB)
static PServiceRegistry service_registry_create()
char broadAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:71
char gd_ch_ipAddress[SZ_CHAR_BUFF]
#define SKN_FIND_RPI_PORT

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int service_registry_list_entries ( PServiceRegistry  psr)

Logs each entry in service registry

Definition at line 954 of file skn_network_helpers.c.

References _serviceRegistry::count, _serviceRegistry::entry, _serviceEntry::ip, _serviceEntry::name, _serviceEntry::port, and SD_INFO.

Referenced by main().

954  {
955  int index = 0;
956 
957  skn_logger(" ", "\nServiceRegistry:");
958  for (index = 0; index < psr->count; index++) {
959  skn_logger(SD_INFO, "RegistryEntry(%02d) name=%s, ip=%s, port=%d", index, psr->entry[index]->name, psr->entry[index]->ip, psr->entry[index]->port);
960  }
961  return index;
962 }
#define SD_INFO
int port
char name[SZ_INFO_BUFF]
char ip[SZ_INFO_BUFF]
PRegistryEntry entry[ARY_MAX_REGISTRY]

+ Here is the caller graph for this function:

int service_registry_provider ( int  i_socket,
char *  response 
)

Definition at line 692 of file skn_network_helpers.c.

References _ipBroadcastArray::chDefaultIntfName, _ipBroadcastArray::defaultIndex, gd_i_display, gd_pch_service_name, get_broadcast_ip_array(), gi_exit_flag, _ipBroadcastArray::ipAddrStr, PLATFORM_ERROR, SD_DEBUG, SD_EMERG, SD_ERR, SD_NOTICE, service_registry_entry_response_message_log(), service_registry_valiadate_response_format(), SKN_FIND_RPI_PORT, SKN_RPI_DISPLAY_SERVICE_PORT, SKN_RUN_MODE_RUN, SZ_COMM_BUFF, and SZ_INFO_BUFF.

Referenced by main().

692  {
693  struct sockaddr_in remaddr; /* remote address */
694  socklen_t addrlen = sizeof(remaddr); /* length of addresses */
695  IPBroadcastArray aB;
696  char request[SZ_INFO_BUFF];
697  char recvHostName[SZ_INFO_BUFF];
698  signed int rLen = 0, rc = 0;
699  int exit_code = EXIT_SUCCESS, i_response_len = 0;
700 
701 
702  memset(request, 0, sizeof(request));
703  memset(recvHostName, 0, sizeof(recvHostName));
704 
705  rc = get_broadcast_ip_array(&aB);
706  if (rc == PLATFORM_ERROR) {
707  return EXIT_FAILURE;
708  }
709 
710  if (gd_pch_service_name == NULL) {
711  gd_pch_service_name = "lcd_display_service";
712  }
713 
714  if (strlen(response) < 16) {
715  if (gd_i_display) {
716  i_response_len = snprintf(response, (SZ_INFO_BUFF - 1),
717  "name=rpi_locator_service,ip=%s,port=%d|"
718  "name=%s,ip=%s,port=%d|",
722  } else {
723  i_response_len = snprintf(response, (SZ_INFO_BUFF - 1),
724  "name=rpi_locator_service,ip=%s,port=%d|",
726  }
727  }
729 
730  skn_logger(SD_DEBUG, "Socket Bound to %s:%s", aB.chDefaultIntfName, aB.ipAddrStr[aB.defaultIndex]);
731 
732  while (gi_exit_flag == SKN_RUN_MODE_RUN) {
733  memset(&remaddr, 0, sizeof(remaddr));
734  remaddr.sin_family = AF_INET;
735  remaddr.sin_port = htons(SKN_FIND_RPI_PORT);
736  remaddr.sin_addr.s_addr = htonl(INADDR_ANY);
737  addrlen = sizeof(remaddr);
738 
739  if ((rLen = recvfrom(i_socket, request, (SZ_INFO_BUFF - 1), 0, (struct sockaddr *) &remaddr, &addrlen)) < 0) {
740  if (errno == EAGAIN) {
741  continue;
742  }
743  skn_logger(SD_ERR, "RcvFrom() Failure code=%d, etext=%s", errno, strerror(errno));
744  exit_code = EXIT_FAILURE;
745  break;
746  }
747  request[rLen] = 0;
748 
749  rc = getnameinfo(((struct sockaddr *) &remaddr), sizeof(struct sockaddr_in), recvHostName, (SZ_INFO_BUFF-1), NULL, 0, NI_DGRAM);
750  if (rc != 0) {
751  skn_logger(SD_ERR, "GetNameInfo() Failure code=%d, etext=%s", errno, strerror(errno));
752  exit_code = EXIT_FAILURE;
753  break;
754  }
755  skn_logger(SD_NOTICE, "Received request from %s @ %s:%d", recvHostName, inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port));
756  skn_logger(SD_NOTICE, "Request data: [%s]\n", request);
757 
758  /*
759  * Add new registry entry by command */
760  if ((strncmp("ADD ", request, sizeof("ADD")) == 0) &&
761  (service_registry_valiadate_response_format(&request[4]) == EXIT_SUCCESS)) {
762  if ((response[i_response_len-1] == '|') ||
763  (response[i_response_len-1] == '%') ||
764  (response[i_response_len-1] == ';')) {
765  strncpy(&response[i_response_len], &request[4], ((SZ_COMM_BUFF - 1) - (strlen(response) + strlen(&request[4]))) );
766  i_response_len += (rLen - 4);
767  skn_logger(SD_NOTICE, "COMMAND: Add New RegistryEntry Request Accepted!");
768  }
769  }
770 
771  if (sendto(i_socket, response, strlen(response), 0, (struct sockaddr *) &remaddr, addrlen) < 0) {
772  skn_logger(SD_EMERG, "SendTo() Failure code=%d, etext=%s", errno, strerror(errno));
773  exit_code = EXIT_FAILURE;
774  break;
775  }
776 
777  /*
778  * Shutdown by command */
779  if (strcmp("QUIT!", request) == 0) {
780  skn_logger(SD_NOTICE, "COMMAND: Shutdown Requested! exit code=%d", gi_exit_flag);
781  break;
782  }
783  }
784 
785  return exit_code;
786 }
char * gd_pch_service_name
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
Definition: cmdDC.c:69
#define PLATFORM_ERROR
Definition: cmdDC.c:63
#define SD_DEBUG
#define SD_ERR
#define SZ_COMM_BUFF
Definition: cmdDC.c:59
#define SD_EMERG
void service_registry_entry_response_message_log(const char *response)
#define SZ_INFO_BUFF
Definition: cmdDC.c:56
#define SKN_RPI_DISPLAY_SERVICE_PORT
int gd_i_display
int defaultIndex
Definition: cmdDC.c:72
char chDefaultIntfName[SZ_CHAR_BUFF]
Definition: cmdDC.c:67
#define SKN_RUN_MODE_RUN
int service_registry_valiadate_response_format(const char *response)
sig_atomic_t gi_exit_flag
#define SD_NOTICE
int get_broadcast_ip_array(PIPBroadcastArray paB)
#define SKN_FIND_RPI_PORT

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int service_registry_response_parse ( PServiceRegistry  psreg,
const char *  response,
int *  errors 
)
static

service_registry_response_parse()

Parse this response message, guess spellings, skip invalid, export error count

Format: name=rpi_locator_service,ip=10.100.1.19,port=48028| name=lcd_display_service,ip=10.100.1.19,port=48029|

the vertical bar char '|' is the line separator, % and ; are also supported

Definition at line 1031 of file skn_network_helpers.c.

References _serviceRegistry::count, SD_WARNING, service_registry_entry_create(), service_registry_entry_create_helper(), and skn_strip().

Referenced by service_registry_get_via_udp_broadcast(), service_registry_valiadate_response_format(), and service_registry_valiadated_registry().

1031  {
1032  int control = 1;
1033  char *base = NULL, *psep = NULL, *resp = NULL, *line = NULL,
1034  *keypair = NULL, *element = NULL,
1035  *name = NULL, *ip = NULL, *pport = NULL,
1036  **meta = NULL;
1037 
1038  base = resp = strdup(response);
1039 
1040  if (strstr(response, "|")) {
1041  psep = "|";
1042  } else if (strstr(response, "%")) {
1043  psep = "%";
1044  } else if (strstr(response, ";")) {
1045  psep = ";";
1046  }
1047 
1048  while ((line = strsep(&resp, psep)) != NULL) {
1049  if (strlen(line) < 16) {
1050  continue;
1051  }
1052 
1053  pport = ip = name = NULL;
1054  while ((keypair = strsep(&line, ",")) != NULL) {
1055  if (strlen(keypair) < 1) {
1056  continue;
1057  }
1058 
1059  control = 1;
1060  element = strstr(keypair, "=");
1061  if (element != NULL) {
1062  element[0] = 0;
1063  meta = service_registry_entry_create_helper(keypair, &name, &ip, &pport);
1064  if (meta != NULL && (element[1] != 0)) {
1065  *meta = skn_strip(++element);
1066  } else {
1067  control = 0;
1068  if (errors != NULL)
1069  (*errors)++;
1070  skn_logger(SD_WARNING, "Response format failure: for name=%s, ip=%s, port=%s, first failing entry: [%s]", name, ip, pport, keypair);
1071  break;
1072  }
1073  }
1074  } // end while line
1075 
1076  if (control == 1) { // catch a breakout caused by no value
1077  service_registry_entry_create(psreg, name, ip, pport, errors);
1078  }
1079 
1080  } // end while buffer
1081 
1082  free(base);
1083  return psreg->count;
1084 }
#define SD_WARNING
static void * service_registry_entry_create_helper(char *key, char **name, char **ip, char **port)
char * skn_strip(char *alpha)
static int service_registry_entry_create(PServiceRegistry psreg, char *name, char *ip, char *port, int *errors)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int service_registry_valiadate_response_format ( const char *  response)

service_registry_valiadate_response_format()

  • Validates a text registry entry format
  • Returns EXIT_FAILURE/SUCCESS

Definition at line 869 of file skn_network_helpers.c.

References service_registry_create(), service_registry_destroy(), and service_registry_response_parse().

Referenced by main(), and service_registry_provider().

869  {
870  int errors = 0; // false
871 
873  service_registry_response_parse(psr, response, &errors);
875 
876  if (errors > 0) {
877  return EXIT_FAILURE; // false
878  } else {
879  return EXIT_SUCCESS; // true
880  }
881 }
static int service_registry_response_parse(PServiceRegistry psreg, const char *response, int *errors)
void service_registry_destroy(PServiceRegistry psreg)
static PServiceRegistry service_registry_create()

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

PServiceRegistry service_registry_valiadated_registry ( const char *  response)

service_registry_valiadated_registry()

  • Validate the text formatted entry and return registry collection
  • Returns a Registry with one entry

Definition at line 889 of file skn_network_helpers.c.

References service_registry_create(), and service_registry_response_parse().

889  {
890  int errors = 0;
891 
893  service_registry_response_parse(psr, response, &errors);
894  if (errors > 0) {
895  free(psr);
896  return NULL; // false
897  }
898 
899  return psr;
900 }
static int service_registry_response_parse(PServiceRegistry psreg, const char *response, int *errors)
static PServiceRegistry service_registry_create()

+ Here is the call graph for this function:

void signals_cleanup ( int  sig)

Definition at line 185 of file skn_network_helpers.c.

References gi_exit_flag, and SKN_RUN_MODE_RUN.

Referenced by main().

185  {
186  signal(SIGINT, SIG_DFL);
187  signal(SIGQUIT, SIG_DFL);
188  signal(SIGTERM, SIG_DFL);
189 
190  if (gi_exit_flag > SKN_RUN_MODE_RUN) { // exit caused by some interrupt -- otherwise it would be exactly 0
191  kill(getpid(), sig);
192  }
193 }
#define SKN_RUN_MODE_RUN
sig_atomic_t gi_exit_flag

+ Here is the caller graph for this function:

void signals_init ( )

Definition at line 179 of file skn_network_helpers.c.

References exit_handler().

Referenced by main().

179  {
180  signal(SIGINT, exit_handler); // Ctrl-C
181  signal(SIGQUIT, exit_handler); // Quit
182  signal(SIGTERM, exit_handler); // Normal kill command
183 }
static void exit_handler(int sig)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

double skn_duration_in_milliseconds ( struct timeval *  pstart,
struct timeval *  pend 
)

skn_duration_in_microseconds()

  • expressed in %1.6us seconds.miroseconds

Definition at line 622 of file skn_network_helpers.c.

Referenced by service_registry_get_via_udp_broadcast(), and skn_udp_service_request().

622  {
623  long secs_used = 0;
624  double total_micros_used = 0.0;
625  struct timeval end;
626 
627  if (pend == NULL) { // calc running duration
628  pend = &end;
629  gettimeofday(pend, NULL);
630  }
631 
632  secs_used=(pend->tv_sec - pstart->tv_sec); //avoid overflow by subtracting first
633  total_micros_used = secs_used * 1000.0; // sec to ms
634  total_micros_used += (pend->tv_usec - pstart->tv_usec) / 1000.0; // us to ms
635 
636  return total_micros_used / 1000.0; // express in seconds.milliseconds
637 }

+ Here is the caller graph for this function:

long skn_get_number_of_cpu_cores ( )

Definition at line 40 of file skn_network_helpers.c.

Referenced by generate_rpi_model_info(), generate_uname_info(), and main().

40  {
41  return sysconf(_SC_NPROCESSORS_ONLN);
42 }

+ Here is the caller graph for this function:

uid_t skn_get_userids ( )

DELAY FOR # uS WITHOUT SLEEPING Ref: http://www.raspberry-projects.com/pi/programming-in-c/timing/clock_gettime-for-acurate-timing

Using delayMicroseconds lets the linux scheduler decide to jump to another process. Using this function avoids letting the scheduler know we are pausing and provides much faster operation if you are needing to use lots of delays.

Fixup incase your building on for OSX, which does not implement clock_gettime()

#ifdef MACH #include <sys/time.h> #define CLOCK_REALTIME 0

  clock_gettime is not implemented on OSX *

int clock_gettime(int clk_id, struct timespec* t) { struct timeval now; int rv = gettimeofday(&now, NULL); if (rv) return rv; t->tv_sec = now.tv_sec; t->tv_nsec = now.tv_usec * 1000; return 0; } #endif

void skn_delay_microseconds (int delay_us) { long int start_time; long int time_difference; struct timespec gettime_now;

clock_gettime(CLOCK_REALTIME, &gettime_now); start_time = gettime_now.tv_nsec; //Get nS value while (1) { clock_gettime(CLOCK_REALTIME, &gettime_now); time_difference = gettime_now.tv_nsec - start_time; if (time_difference < 0) time_difference += 1000000000; //(Rolls over every 1 second) if (time_difference > (delay_us * 1000)) //Delay for # nS break; } } Setup effective and real userid

Definition at line 152 of file skn_network_helpers.c.

References gd_pch_effective_userid.

Referenced by main().

152  {
153  uid_t real_user_id = 0;
154  uid_t effective_user_id = 0;
155  struct passwd *userinfo = NULL;
156 
157  real_user_id = getuid();
158  if (gd_pch_effective_userid != NULL) {
159  userinfo = getpwnam(gd_pch_effective_userid);
160  effective_user_id = userinfo->pw_uid;
161  } else {
162  effective_user_id = geteuid();
163  userinfo = getpwuid(effective_user_id);
164  gd_pch_effective_userid = userinfo->pw_name;
165  }
166 
167  return real_user_id;
168 }
char * gd_pch_effective_userid

+ Here is the caller graph for this function:

int skn_handle_locator_command_line ( int  argc,
char **  argv 
)

Definition at line 373 of file skn_network_helpers.c.

References gd_ch_program_name, gd_i_debug, gd_i_display, gd_i_i2c_address, gd_i_unique_registry, gd_i_update, gd_pch_message, gd_pch_service_name, PACKAGE_VERSION, SD_ERR, SD_WARNING, and skn_locator_print_usage().

Referenced by main().

373  {
374  int opt = 0;
375  int longindex = 0;
376  struct option longopts[] = { { "include-display-service", 0, NULL, 's' }, /* set true if present */
377  { "alt-service-name", 1, NULL, 'a' }, /* set true if present */
378  { "unique-registry", 0, NULL, 'u' }, /* set true if present */
379  { "non-stop", 1, NULL, 'n' }, /* required param if */
380  { "debug", 1, NULL, 'd' }, /* required param if */
381  { "message", 1, NULL, 'm' }, /* required param if */
382  { "i2c-address", 1, NULL, 'i' }, /* required param if */
383  { "version", 0, NULL, 'v' }, /* set true if present */
384  { "help", 0, NULL, 'h' }, /* set true if present */
385  { 0, 0, 0, 0 } };
386 
387  /*
388  * Get commandline options
389  * longindex is the current index into longopts
390  * optind is current/last index into argv
391  * optarg is value attached(-d88) or next element(-d 88) of argv
392  * opterr flags a scanning error
393  */
394  while ((opt = getopt_long(argc, argv, "d:m:n:i:a:usvh", longopts, &longindex)) != -1) {
395  switch (opt) {
396  case 'u':
398  break;
399  case 's':
400  gd_i_display = 1;
401  break;
402  case 'd':
403  if (optarg) {
404  gd_i_debug = atoi(optarg);
405  } else {
406  skn_logger(SD_WARNING, "%s: input param was invalid! %c[%d:%d:%d]\n", gd_ch_program_name, (char) opt, longindex, optind, opterr);
407  return (EXIT_FAILURE);
408  }
409  break;
410  case 'm':
411  if (optarg) {
412  gd_pch_message = strdup(optarg);
413  } else {
414  skn_logger(SD_WARNING, "%s: input param was invalid! %c[%d:%d:%d]\n", gd_ch_program_name, (char) opt, longindex, optind, opterr);
415  return (EXIT_FAILURE);
416  }
417  break;
418  case 'n':
419  if (optarg) {
420  gd_i_update = atoi(optarg);
421  } else {
422  skn_logger(SD_WARNING, "%s: input param was invalid! %c[%d:%d:%d]\n", gd_ch_program_name, (char) opt, longindex, optind, opterr);
423  return (EXIT_FAILURE);
424  }
425  break;
426  case 'a':
427  if (optarg) {
428  gd_pch_service_name = strdup(optarg);
429  } else {
430  skn_logger(SD_WARNING, "%s: input param was invalid! %c[%d:%d:%d]\n", gd_ch_program_name, (char) opt, longindex, optind, opterr);
431  return (EXIT_FAILURE);
432  }
433  break;
434  case 'i':
435  if (optarg) {
436  gd_i_i2c_address = atoi(optarg);
437  } else {
438  skn_logger(SD_ERR, "%s: input param was invalid! %c[%d:%d:%d]\n", gd_ch_program_name, (char) opt, longindex, optind,
439  opterr);
440  return (EXIT_FAILURE);
441  }
442  break;
443  case 'v':
444  skn_logger(SD_WARNING, "\n\tProgram => %s\n\tVersion => %s\n\tSkoona Development\n\t<skoona@gmail.com>\n", gd_ch_program_name, PACKAGE_VERSION);
445  return (EXIT_FAILURE);
446  break;
447  case '?':
448  skn_logger(SD_WARNING, "%s: unknown input param! %c[%d:%d:%d]\n", gd_ch_program_name, (char) opt, longindex, optind, opterr);
450  return (EXIT_FAILURE);
451  break;
452  default: /* help and default */
454  return (EXIT_FAILURE);
455  break;
456  }
457  }
458 
459  return EXIT_SUCCESS;
460 }
static void skn_locator_print_usage()
char * gd_pch_service_name
int gd_i_update
char * gd_pch_message
int gd_i_i2c_address
#define SD_ERR
int gd_i_unique_registry
#define SD_WARNING
int gd_i_display
char gd_ch_program_name[SZ_INFO_BUFF]
signed int gd_i_debug
#define PACKAGE_VERSION
Definition: cmdDC.c:19

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void skn_locator_print_usage ( )
static

Definition at line 331 of file skn_network_helpers.c.

References gd_ch_program_desc, and gd_ch_program_name.

Referenced by skn_handle_locator_command_line().

331  {
332  skn_logger(" ", "%s -- %s", gd_ch_program_name, gd_ch_program_desc);
333  skn_logger(" ", "\tSkoona Development <skoona@gmail.com>");
334  if (strcmp(gd_ch_program_name, "udp_locator_client") == 0) {
335  skn_logger(" ", "Usage:\n %s [-v] [-m 'any text msg'] [-u] [-h|--help]", gd_ch_program_name);
336  skn_logger(" ", "\nOptions:");
337  skn_logger(" ", " -u, --unique-registry\t List unique entries from all responses.");
338  skn_logger(" ", " -m, --message\tAny text to send; 'stop' cause service to terminate.");
339  } else if (strcmp(gd_ch_program_name, "udp_locator_service") == 0) {
340  skn_logger(" ", "Usage:\n %s [-s] [-v] [-m '<delimited-response-message-string>'] [-a 'my_service_name'] [-h|--help]", gd_ch_program_name);
341  skn_logger(" ", " Format: name=<service-name>,ip=<service-ipaddress>ddd.ddd.ddd.ddd,port=<service-portnumber>ddddd <line-delimiter>");
342  skn_logger(" ", " REQUIRED <line-delimiter> is one of these '|', '%', ';'");
343  skn_logger(" ", " example: -m 'name=rpi_locator_service,ip=192.168.1.15,port=48028|name=lcd_display_service, ip=192.168.1.15, port=48029|'");
344  skn_logger(" ", "\nOptions:");
345  skn_logger(" ", " -a, --alt-service-name=my_service_name");
346  skn_logger(" ", " lcd_display_service is default, use this to change name.");
347  skn_logger(" ", " -s, --include-display-service\tInclude DisplayService entry in default registry.");
348  } else if (strcmp(gd_ch_program_name, "lcd_display_client") == 0) {
349  skn_logger(" ", "Usage:\n %s [-v] [-m 'message for display'] [-n 1|300] [-a 'my_service_name'] [-h|--help]", gd_ch_program_name);
350  skn_logger(" ", "\nOptions:");
351  skn_logger(" ", " -a, --alt-service-name=my_service_name");
352  skn_logger(" ", " lcd_display_service is default, use this to change name.");
353  skn_logger(" ", " -m, --message\tRequest message to send.");
354  skn_logger(" ", " -n, --non-stop=DD\tContinue to send updates every DD seconds until ctrl-break.");
355  } else if (strcmp(gd_ch_program_name, "a2d_display_client") == 0) {
356  skn_logger(" ", "Usage:\n %s [-v] [-n 1|300] [-i ddd] [-a 'my_service_name'] [-h|--help]", gd_ch_program_name);
357  skn_logger(" ", "\nOptions:");
358  skn_logger(" ", " -a, --alt-service-name=my_service_name");
359  skn_logger(" ", " lcd_display_service is default, use this to change target.");
360  skn_logger(" ", " -i, --i2c-address=ddd\tI2C decimal address. | [0x27=39, 0x20=32]");
361  skn_logger(" ", " -n, --non-stop=DD\tContinue to send updates every DD seconds until ctrl-break.");
362  }
363  skn_logger(" ", " -v, --version\tVersion printout.");
364  skn_logger(" ", " -h, --help\t\tShow this help screen.");
365 }
char gd_ch_program_desc[SZ_INFO_BUFF]
char gd_ch_program_name[SZ_INFO_BUFF]

+ Here is the caller graph for this function:

void skn_program_name_and_description_set ( const char *  name,
const char *  desc 
)

Definition at line 462 of file skn_network_helpers.c.

References gd_ch_hostName, gd_ch_hostShortName, gd_ch_program_desc, gd_ch_program_name, and SZ_CHAR_BUFF.

Referenced by main().

462  {
463  char hostName[SZ_CHAR_BUFF];
464  char * phostName = hostName;
465 
466  strncpy(gd_ch_program_name, name, sizeof(gd_ch_program_name) - 1);
467  strncpy(gd_ch_program_desc, desc, sizeof(gd_ch_program_desc) - 1);
468 
469  gethostname(hostName, sizeof(hostName) - 1);
470  strncpy(gd_ch_hostName, hostName, sizeof(gd_ch_hostName) - 1);
471  strsep(&phostName, ".");
472  strncpy(gd_ch_hostShortName, hostName, sizeof(gd_ch_hostShortName) - 1);
473 
474 }
char gd_ch_program_desc[SZ_INFO_BUFF]
#define SZ_CHAR_BUFF
Definition: cmdDC.c:57
char gd_ch_hostName[SZ_CHAR_BUFF]
char gd_ch_program_name[SZ_INFO_BUFF]
char gd_ch_hostShortName[SZ_CHAR_BUFF]

+ Here is the caller graph for this function:

PServiceRequest skn_service_request_create ( PRegistryEntry  pre,
int  host_socket,
char *  request 
)

Definition at line 603 of file skn_network_helpers.c.

References _serviceRequest::cbName, _serviceRequest::pre, _serviceRequest::request, _serviceRequest::socket, and SZ_INFO_BUFF.

Referenced by main().

603  {
604  PServiceRequest psr = NULL;
605 
606  if (pre == NULL) {
607  return NULL;
608  }
609  psr = (PServiceRequest) malloc(sizeof(ServiceRequest));
610  memset(psr, 0, sizeof(ServiceRequest));
611  strcpy(psr->cbName, "PServiceRequest");
612  psr->socket = host_socket;
613  psr->pre = pre;
614  strncpy(psr->request, request, SZ_INFO_BUFF-1);
615  return psr;
616 }
struct _serviceRequest * PServiceRequest
#define SZ_INFO_BUFF
Definition: cmdDC.c:56
char request[SZ_INFO_BUFF]
char cbName[SZ_CHAR_BUFF]
PRegistryEntry pre

+ Here is the caller graph for this function:

char* skn_strip ( char *  alpha)

Remove Trailing and Leading Blanks

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

Definition at line 480 of file skn_network_helpers.c.

References SD_NOTICE, and SZ_LINE_BUFF.

Referenced by get_default_interface_name(), service_registry_entry_create_helper(), and service_registry_response_parse().

480  {
481  if (alpha == NULL || strlen(alpha) < 1)
482  return alpha;
483 
484  int len = strlen(alpha);
485  int end = len - 1;
486  int start = 0;
487 
488  // use isgraph() or !isspace() vs isalnum() to allow ['|' ';' '%']
489  while (isgraph(alpha[end]) == 0 && end > 0) { // remove trailing non-alphanumeric chars
490  alpha[end--] = 0;
491  }
492 
493  len = strlen(alpha);
494  while ((isalnum(alpha[start]) == 0) && start < len) { // find first non-alpha stricter
495  start++;
496  }
497  if (start < len && start > 0) { // move in place
498  end = len - start;
499  memmove(&alpha[0], &alpha[start], end);
500  alpha[end] = 0;
501  }
502 
503  return alpha;
504 }

+ Here is the caller graph for this function:

int skn_time_delay ( double  delay_time)

Traditional Millisecond delay.

Definition at line 96 of file skn_network_helpers.c.

Referenced by skn_display_manager_do_work(), skn_display_manager_message_consumer_thread(), and skn_scroller_scroll_lines().

96  {
97  struct timespec timeout;
98  if (delay_time == 0.0 || delay_time == 0) delay_time = 0.001;
99  timeout.tv_sec = (time_t) delay_time; // extract integer only
100  timeout.tv_nsec = (long) ((delay_time - timeout.tv_sec) * 1000000000L); // 1e+9
101  return nanosleep(&timeout, NULL);
102 }

+ Here is the caller graph for this function:

int skn_udp_host_create_broadcast_socket ( int  port,
double  rcvTimeout 
)

skn_udp_host_create_broadcast_socket()

  • creates a dgram socket with broadcast enabled
  • returns i_socket | EXIT_FAILURE

Definition at line 568 of file skn_network_helpers.c.

References SD_EMERG, and SD_INFO.

Referenced by main().

568  {
569  struct sockaddr_in addr;
570  int i_socket, broadcastEnable = 1;
571 
572  if ((i_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
573  skn_logger(SD_EMERG, "Create Socket error=%d, etext=%s", errno, strerror(errno));
574  return (EXIT_FAILURE);
575  }
576  if ((setsockopt(i_socket, SOL_SOCKET, SO_BROADCAST, &broadcastEnable, sizeof(broadcastEnable))) < 0) {
577  skn_logger(SD_EMERG, "Set Socket Broadcast Option error=%d, etext=%s", errno, strerror(errno));
578  return (EXIT_FAILURE);
579  }
580 
581  struct timeval tv;
582  tv.tv_sec = rcvTimeout;
583  tv.tv_usec = (long)(rcvTimeout - tv.tv_sec) * 1000000L;
584  skn_logger(SD_INFO, "Set Socket RcvTimeout Option set to: tv_sec=%ld, tv_usec=%ld", tv.tv_sec, tv.tv_usec);
585  if ((setsockopt(i_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) < 0) {
586  skn_logger(SD_EMERG, "Set Socket RcvTimeout Option error=%d, etext=%s", errno, strerror(errno));
587  return (EXIT_FAILURE);
588  }
589 
590  /* set up local address */
591  memset(&addr, 0, sizeof(addr));
592  addr.sin_family = AF_INET;
593  addr.sin_addr.s_addr = htonl(INADDR_ANY);
594  addr.sin_port = htons(port);
595  if (bind(i_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
596  skn_logger(SD_EMERG, "Bind to local Socket error=%d, etext=%s", errno, strerror(errno));
597  return (EXIT_FAILURE);
598  }
599 
600  return i_socket;
601 }
#define SD_INFO
#define SD_EMERG

+ Here is the caller graph for this function:

int skn_udp_host_create_regular_socket ( int  port,
double  rcvTimeout 
)

skn_udp_host_create_regular_socket()

  • creates a dgram socket without broadcast enabled
  • returns i_socket | EXIT_FAILURE

Definition at line 527 of file skn_network_helpers.c.

References SD_EMERG.

Referenced by main(), and skn_display_manager_message_consumer_startup().

527  {
528  struct sockaddr_in addr;
529  int i_socket, reuseEnable = 1;
530 
531  if ((i_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
532  skn_logger(SD_EMERG, "Create Socket error=%d, etext=%s", errno, strerror(errno));
533  return (EXIT_FAILURE);
534  }
535 
536  if ((setsockopt(i_socket, SOL_SOCKET, SO_REUSEADDR, &reuseEnable, sizeof(reuseEnable))) < 0) {
537  skn_logger(SD_EMERG, "Set Socket Reuse Option error=%d, etext=%s", errno, strerror(errno));
538  return (EXIT_FAILURE);
539  }
540 
541  struct timeval tv;
542  tv.tv_sec = rcvTimeout;
543  tv.tv_usec = (long)(rcvTimeout - tv.tv_sec) * 1000000L;
544  if ((setsockopt(i_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) < 0) {
545  skn_logger(SD_EMERG, "Set Socket RcvTimeout Option error=%d, etext=%s", errno, strerror(errno));
546  return (EXIT_FAILURE);
547  }
548 
549  /* set up local address */
550  memset(&addr, 0, sizeof(addr));
551  addr.sin_family = AF_INET;
552  addr.sin_addr.s_addr = htonl(INADDR_ANY);
553  addr.sin_port = htons(port);
554  if (bind(i_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
555  skn_logger(SD_EMERG, "Bind to local Socket error=%d, etext=%s", errno, strerror(errno));
556  return (EXIT_FAILURE);
557  }
558 
559  return i_socket;
560 }
#define SD_EMERG

+ Here is the caller graph for this function:

int skn_udp_service_request ( PServiceRequest  psr)

skn_udp_service_request()

  • side effects: none
  • returns EXIT_SUCCESS | EXIT_FAILURE

Definition at line 645 of file skn_network_helpers.c.

References _serviceEntry::ip, _serviceEntry::name, PLATFORM_ERROR, _serviceEntry::port, _serviceRequest::pre, _serviceRequest::request, _serviceRequest::response, SD_INFO, SD_NOTICE, SD_WARNING, skn_duration_in_milliseconds(), _serviceRequest::socket, and SZ_INFO_BUFF.

Referenced by main().

645  {
646  struct sockaddr_in remaddr; /* remote address */
647  socklen_t addrlen = sizeof(remaddr); /* length of addresses */
648  signed int vIndex = 0;
649  struct timeval start, end;
650 
651  memset(&remaddr, 0, sizeof(remaddr));
652  remaddr.sin_family = AF_INET;
653  remaddr.sin_addr.s_addr = inet_addr(psr->pre->ip);
654  remaddr.sin_port = htons(psr->pre->port);
655 
656  /*
657  * SEND */
658  gettimeofday(&start, NULL);
659  if (sendto(psr->socket, psr->request, strlen(psr->request), 0, (struct sockaddr *) &remaddr, addrlen) < 0) {
660  gettimeofday(&end, NULL);
661  skn_logger(SD_WARNING, "ServiceRequest: SendTo(%1.6f) Timed out; Failure code=%d, etext=%s", skn_duration_in_milliseconds(&start,&end), errno, strerror(errno));
662  return EXIT_FAILURE;
663  }
664  skn_logger(SD_NOTICE, "ServiceRequest sent to %s:%s:%d", psr->pre->name, psr->pre->ip, psr->pre->port);
665 
666  /*
667  * RECEIVE */
668  vIndex = recvfrom(psr->socket, psr->response, (SZ_INFO_BUFF - 1), 0, (struct sockaddr *) &remaddr, &addrlen);
669  if (vIndex == PLATFORM_ERROR) {
670  gettimeofday(&end, NULL);
671  skn_logger(SD_WARNING, "ServiceRequest: recvfrom(%1.6f) Failure code=%d, etext=%s", skn_duration_in_milliseconds(&start,&end), errno, strerror(errno));
672  return EXIT_FAILURE;
673  }
674  psr->response[vIndex] = 0;
675  gettimeofday(&end, NULL);
676 
677  skn_logger(SD_INFO, "Response(%1.3fs) received from [%s] %s:%d",
678  skn_duration_in_milliseconds(&start,&end),
679  psr->response,
680  inet_ntoa(remaddr.sin_addr),
681  ntohs(remaddr.sin_port)
682  );
683 
684  if (strcmp(psr->response, "QUIT!") == 0) {
685  skn_logger(SD_NOTICE, "Shutdown Requested!");
686  return EXIT_FAILURE;
687  }
688 
689  return (EXIT_SUCCESS);
690 }
double skn_duration_in_milliseconds(struct timeval *pstart, struct timeval *pend)
#define PLATFORM_ERROR
Definition: cmdDC.c:63
#define SD_INFO
int port
#define SD_WARNING
#define SZ_INFO_BUFF
Definition: cmdDC.c:56
char name[SZ_INFO_BUFF]
char request[SZ_INFO_BUFF]
char response[SZ_INFO_BUFF]
#define SD_NOTICE
PRegistryEntry pre
char ip[SZ_INFO_BUFF]

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

char gd_ch_hostName[SZ_CHAR_BUFF]

Definition at line 24 of file skn_network_helpers.c.

Referenced by skn_program_name_and_description_set().

char gd_ch_hostShortName[SZ_CHAR_BUFF]

Definition at line 25 of file skn_network_helpers.c.

Referenced by skn_program_name_and_description_set().

char gd_ch_intfName[SZ_CHAR_BUFF]
char gd_ch_ipAddress[SZ_CHAR_BUFF]
signed int gd_i_debug = 0
int gd_i_display = 0
int gd_i_socket = -1

Definition at line 18 of file skn_network_helpers.c.

Referenced by main().

int gd_i_unique_registry = 0
int gd_i_update = 0

Definition at line 20 of file skn_network_helpers.c.

Referenced by main(), and skn_handle_locator_command_line().

char* gd_pch_effective_userid = NULL

Definition at line 17 of file skn_network_helpers.c.

Referenced by main(), and skn_get_userids().

char* gd_pch_message = NULL
char* gd_pch_service_name