41 return sysconf(_SC_NPROCESSORS_ONLN);
49 rc = getloadavg(loadavg, 3);
52 snprintf(msg,
SZ_INFO_BUFF -1,
"LoadAvg: 1m=%2.1f, 5m=%2.1f, 15m=%2.1F",
53 loadavg[0], loadavg[1], loadavg[2]);
55 snprintf(msg,
SZ_INFO_BUFF -1,
"Load Average: Not Available %d:%d:%s",
56 rc, errno, strerror(errno));
66 char * message =
"uname() api failed.";
68 if (uname(&info) != 0) {
71 mLen = snprintf(msg,
SZ_INFO_BUFF -1,
"%s %s, %s %s | Cores=%ld",
72 info.sysname, info.release, info.version, info.machine,
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,
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;
100 timeout.tv_nsec = (long) ((delay_time - timeout.tv_sec) * 1000000000L);
101 return nanosleep(&timeout, NULL);
153 uid_t real_user_id = 0;
154 uid_t effective_user_id = 0;
155 struct passwd *userinfo = NULL;
157 real_user_id = getuid();
160 effective_user_id = userinfo->pw_uid;
162 effective_user_id = geteuid();
163 userinfo = getpwuid(effective_user_id);
176 skn_logger(
SD_NOTICE,
"Program Exiting, from signal=%d:%s\n", sig, strsignal(sig));
186 signal(SIGINT, SIG_DFL);
187 signal(SIGQUIT, SIG_DFL);
188 signal(SIGTERM, SIG_DFL);
203 skn_logger(
SD_ERR,
"InterfaceName and Address: unable to access information.");
215 struct ifaddrs * ifap;
222 strcpy(paB->
cbName,
"IPBroadcastArray");
225 if (rc == EXIT_FAILURE) {
226 skn_logger(
SD_ERR,
"No Default Network Interfaces Found!.");
229 rc = getifaddrs(&ifap);
231 skn_logger(
SD_ERR,
"No Network Interfaces Found at All ! %d:%d:%s", rc, errno, strerror(errno) );
237 if (p->ifa_addr != NULL && p->ifa_addr->sa_family == AF_INET && ((p->ifa_flags & IFF_BROADCAST) > 0)) {
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));
279 f_route = fopen(
"/proc/net/route",
"r");
280 if (f_route != NULL) {
282 iName = strtok(line,
"\t");
283 dRoute = strtok(NULL,
"\t");
285 if (iName != NULL && dRoute != NULL) {
286 if (strcmp(dRoute,
"00000000") == 0) {
287 strncpy(pchDefaultInterfaceName, iName, (
SZ_INFO_BUFF - 1));
296 skn_logger(
SD_ERR,
"Opening ProcFs for RouteInfo Failed: %d:%s, Alternate method will be attempted.", errno, strerror(errno));
298 f_route = popen(
"route -n get 0.0.0.0",
"r");
299 if (f_route != NULL) {
301 dRoute = strtok(line,
":");
302 iName = strtok(NULL,
"\n");
303 if (strcmp(
skn_strip(dRoute),
"interface") == 0) {
312 skn_logger(
SD_ERR,
"Alternate method to get RouteInfo Failed: %d:%s", errno, strerror(errno));
333 skn_logger(
" ",
"\tSkoona Development <skoona@gmail.com>");
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.");
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.");
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.");
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.");
363 skn_logger(
" ",
" -v, --version\tVersion printout.");
364 skn_logger(
" ",
" -h, --help\t\tShow this help screen.");
376 struct option longopts[] = { {
"include-display-service", 0, NULL,
's' },
377 {
"alt-service-name", 1, NULL,
'a' },
378 {
"unique-registry", 0, NULL,
'u' },
379 {
"non-stop", 1, NULL,
'n' },
380 {
"debug", 1, NULL,
'd' },
381 {
"message", 1, NULL,
'm' },
382 {
"i2c-address", 1, NULL,
'i' },
383 {
"version", 0, NULL,
'v' },
384 {
"help", 0, NULL,
'h' },
394 while ((opt = getopt_long(argc, argv,
"d:m:n:i:a:usvh", longopts, &longindex)) != -1) {
407 return (EXIT_FAILURE);
415 return (EXIT_FAILURE);
423 return (EXIT_FAILURE);
431 return (EXIT_FAILURE);
438 skn_logger(
SD_ERR,
"%s: input param was invalid! %c[%d:%d:%d]\n",
gd_ch_program_name, (
char) opt, longindex, optind,
440 return (EXIT_FAILURE);
445 return (EXIT_FAILURE);
450 return (EXIT_FAILURE);
454 return (EXIT_FAILURE);
464 char * phostName = hostName;
469 gethostname(hostName,
sizeof(hostName) - 1);
471 strsep(&phostName,
".");
481 if (alpha == NULL || strlen(alpha) < 1)
484 int len = strlen(alpha);
489 while (isgraph(alpha[end]) == 0 && end > 0) {
494 while ((isalnum(alpha[start]) == 0) && start < len) {
497 if (start < len && start > 0) {
499 memmove(&alpha[0], &alpha[start], end);
506 int skn_logger(
const char *level,
const char *format, ...) {
511 va_start(args, format);
512 vsnprintf(buffer,
sizeof(buffer), format, args);
518 return fprintf(stderr,
"%s%s\n", logLevel, buffer);
528 struct sockaddr_in addr;
529 int i_socket, reuseEnable = 1;
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);
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);
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);
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);
569 struct sockaddr_in addr;
570 int i_socket, broadcastEnable = 1;
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);
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);
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);
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);
611 strcpy(psr->
cbName,
"PServiceRequest");
612 psr->
socket = host_socket;
624 double total_micros_used = 0.0;
629 gettimeofday(pend, NULL);
632 secs_used=(pend->tv_sec - pstart->tv_sec);
633 total_micros_used = secs_used * 1000.0;
634 total_micros_used += (pend->tv_usec - pstart->tv_usec) / 1000.0;
636 return total_micros_used / 1000.0;
646 struct sockaddr_in remaddr;
647 socklen_t addrlen =
sizeof(remaddr);
648 signed int vIndex = 0;
649 struct timeval start, end;
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);
658 gettimeofday(&start, NULL);
659 if (sendto(psr->
socket, psr->
request, strlen(psr->
request), 0, (
struct sockaddr *) &remaddr, addrlen) < 0) {
660 gettimeofday(&end, NULL);
670 gettimeofday(&end, NULL);
675 gettimeofday(&end, NULL);
677 skn_logger(
SD_INFO,
"Response(%1.3fs) received from [%s] %s:%d",
680 inet_ntoa(remaddr.sin_addr),
681 ntohs(remaddr.sin_port)
684 if (strcmp(psr->
response,
"QUIT!") == 0) {
685 skn_logger(
SD_NOTICE,
"Shutdown Requested!");
689 return (EXIT_SUCCESS);
693 struct sockaddr_in remaddr;
694 socklen_t addrlen =
sizeof(remaddr);
698 signed int rLen = 0, rc = 0;
699 int exit_code = EXIT_SUCCESS, i_response_len = 0;
702 memset(request, 0,
sizeof(request));
703 memset(recvHostName, 0,
sizeof(recvHostName));
714 if (strlen(response) < 16) {
717 "name=rpi_locator_service,ip=%s,port=%d|" 718 "name=%s,ip=%s,port=%d|",
724 "name=rpi_locator_service,ip=%s,port=%d|",
733 memset(&remaddr, 0,
sizeof(remaddr));
734 remaddr.sin_family = AF_INET;
736 remaddr.sin_addr.s_addr = htonl(INADDR_ANY);
737 addrlen =
sizeof(remaddr);
739 if ((rLen = recvfrom(i_socket, request, (
SZ_INFO_BUFF - 1), 0, (
struct sockaddr *) &remaddr, &addrlen)) < 0) {
740 if (errno == EAGAIN) {
743 skn_logger(
SD_ERR,
"RcvFrom() Failure code=%d, etext=%s", errno, strerror(errno));
744 exit_code = EXIT_FAILURE;
749 rc = getnameinfo(((
struct sockaddr *) &remaddr),
sizeof(
struct sockaddr_in), recvHostName, (
SZ_INFO_BUFF-1), NULL, 0, NI_DGRAM);
751 skn_logger(
SD_ERR,
"GetNameInfo() Failure code=%d, etext=%s", errno, strerror(errno));
752 exit_code = EXIT_FAILURE;
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);
760 if ((strncmp(
"ADD ", request,
sizeof(
"ADD")) == 0) &&
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!");
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;
779 if (strcmp(
"QUIT!", request) == 0) {
803 strcpy(psreg->
cbName,
"PServiceRegistry");
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);
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);
848 strcpy(prent->
cbName,
"PRegistryEntry");
849 strcpy(prent->
name, name);
850 strcpy(prent->
ip, ip);
851 prent->
port = atoi(port);
853 skn_logger(
SD_WARNING,
"Internal Memory Error: Could not allocate memory for entry %d:%s !", name, psreg->
count);
908 char * worker = NULL, *parser = NULL, *base = strdup(response);
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)) {
933 while (index < psreg->count) {
934 if (strcmp(serviceName, psreg->
entry[index]->
name) == 0) {
935 prent = psreg->
entry[index];
957 skn_logger(
" ",
"\nServiceRegistry:");
958 for (index = 0; index < psr->
count; index++) {
971 void * result = NULL;
972 char * names[4] = {
"name",
"ip",
"port", NULL };
978 for (index = 0; names[index] != NULL; index++) {
979 if (strcmp(names[index], field) == 0) {
980 result = (
void *) prent + offsets[index];
996 void * result = NULL;
997 char * names[4] = {
"name",
"ip",
"port", NULL };
998 void * offsets[] = { name, ip, port, NULL };
1001 for (index = 0; names[index] != NULL; index++) {
1002 if (strcmp(names[index], key) == 0) {
1003 result = offsets[index];
1007 if (result == NULL) {
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];
1033 char *base = NULL, *psep = NULL, *resp = NULL, *line = NULL,
1034 *keypair = NULL, *element = NULL,
1035 *name = NULL, *ip = NULL, *pport = NULL,
1038 base = resp = strdup(response);
1040 if (strstr(response,
"|")) {
1042 }
else if (strstr(response,
"%")) {
1044 }
else if (strstr(response,
";")) {
1048 while ((line = strsep(&resp, psep)) != NULL) {
1049 if (strlen(line) < 16) {
1053 pport = ip = name = NULL;
1054 while ((keypair = strsep(&line,
",")) != NULL) {
1055 if (strlen(keypair) < 1) {
1060 element = strstr(keypair,
"=");
1061 if (element != NULL) {
1064 if (meta != NULL && (element[1] != 0)) {
1070 skn_logger(
SD_WARNING,
"Response format failure: for name=%s, ip=%s, port=%s, first failing entry: [%s]", name, ip, pport, keypair);
1083 return psreg->
count;
1095 struct sockaddr_in remaddr;
1096 socklen_t addrlen =
sizeof(remaddr);
1101 signed int rLen = 0;
1102 struct timeval start;
1104 memset(response, 0,
sizeof(response));
1105 memset(recvHostName, 0,
sizeof(recvHostName));
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]);
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));
1128 skn_logger(
SD_DEBUG,
"Waiting for all responses\n");
1131 rLen = recvfrom(i_socket, response, (
SZ_INFO_BUFF - 1), 0, (
struct sockaddr *) &remaddr, &addrlen);
1137 rLen = getnameinfo(((
struct sockaddr *) &remaddr),
sizeof(
struct sockaddr_in), recvHostName, (
SZ_INFO_BUFF -1), NULL, 0, NI_DGRAM);
1139 skn_logger(
SD_EMERG,
"getnameinfo() failed: %s\n", gai_strerror(rLen));
1143 skn_logger(
SD_DEBUG,
"Response(%1.3fs) received from %s @ %s:%d",
1146 inet_ntoa(remaddr.sin_addr),
1147 ntohs(remaddr.sin_port)
1165 for (index = 0; index < psreg->
count; index++) {
1166 free(psreg->
entry[index]);
char ifNameStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
static void skn_locator_print_usage()
long skn_get_number_of_cpu_cores()
int skn_udp_host_create_regular_socket(int port, double rcvTimeout)
double skn_duration_in_milliseconds(struct timeval *pstart, struct timeval *pend)
char * gd_pch_service_name
char ipAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
char gd_ch_program_desc[SZ_INFO_BUFF]
int service_registry_entry_count(PServiceRegistry psr)
void get_default_interface_name_and_ipv4_address(char *intf, char *ipv4)
char maskAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
int service_registry_provider(int i_socket, char *response)
char gd_ch_intfName[SZ_CHAR_BUFF]
int skn_time_delay(double delay_time)
void signals_cleanup(int sig)
int skn_handle_locator_command_line(int argc, char **argv)
char cbName[SZ_CHAR_BUFF]
char gd_ch_hostName[SZ_CHAR_BUFF]
static void exit_handler(int sig)
static int service_registry_response_parse(PServiceRegistry psreg, const char *response, int *errors)
static void * service_registry_entry_create_helper(char *key, char **name, char **ip, char **port)
void service_registry_entry_response_message_log(const char *response)
PServiceRegistry service_registry_get_via_udp_broadcast(int i_socket, char *request)
char gd_ch_program_name[SZ_INFO_BUFF]
char * skn_strip(char *alpha)
int generate_uname_info(char *msg)
int get_default_interface_name(char *pchDefaultInterfaceName)
char chDefaultIntfName[SZ_CHAR_BUFF]
int service_registry_valiadate_response_format(const char *response)
PServiceRegistry service_registry_valiadated_registry(const char *response)
sig_atomic_t gi_exit_flag
int service_registry_list_entries(PServiceRegistry psr)
void service_registry_destroy(PServiceRegistry psreg)
char cbName[SZ_CHAR_BUFF]
char request[SZ_INFO_BUFF]
char cbName[SZ_CHAR_BUFF]
char response[SZ_INFO_BUFF]
PServiceRequest skn_service_request_create(PRegistryEntry pre, int host_socket, char *request)
char gd_ch_hostShortName[SZ_CHAR_BUFF]
char cbName[SZ_CHAR_BUFF]
int get_broadcast_ip_array(PIPBroadcastArray paB)
void * service_registry_get_entry_field_ref(PRegistryEntry prent, char *field)
static PServiceRegistry service_registry_create()
int skn_udp_service_request(PServiceRequest psr)
static int service_registry_entry_create(PServiceRegistry psreg, char *name, char *ip, char *port, int *errors)
int skn_udp_host_create_broadcast_socket(int port, double rcvTimeout)
char broadAddrStr[ARY_MAX_INTF][SZ_CHAR_BUFF]
char * gd_pch_effective_userid
int generate_datetime_info(char *msg)
char gd_ch_ipAddress[SZ_CHAR_BUFF]
int generate_loadavg_info(char *msg)
void skn_program_name_and_description_set(const char *name, const char *desc)
PRegistryEntry service_registry_find_entry(PServiceRegistry psreg, char *serviceName)
PRegistryEntry entry[ARY_MAX_REGISTRY]