1 contributor
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#define MAC_PATH "/sys/class/net/eth0/address"
//~ #define MAC_PATH "/sys/class/net/wlp0s20f3/address"
#define PROC_TCP "/proc/net/tcp"
#define PROGNAME "heartbeat-cli"
static volatile int keep_running = 1;
void handle_sigint(int sig) {
(void)sig;
keep_running = 0;
}
// Check if there is an established TCP connection on given port (state == 1)
int check_port_connected(int port) {
FILE *fp = fopen(PROC_TCP, "r");
if (!fp) return 0;
char line[512];
int connected = 0;
// Skip header
if (!fgets(line, sizeof(line), fp)) {
fclose(fp);
return 0;
}
while (fgets(line, sizeof(line), fp)) {
unsigned int local_addr, rem_addr;
unsigned int local_port, rem_port, state;
if (sscanf(line, "%*d: %x:%x %x:%x %x",
&local_addr, &local_port, &rem_addr, &rem_port, &state) == 5) {
if (ntohs((unsigned short)rem_port) == ntohs(port) && state == 1) {
connected = 1;
break;
}
}
}
fclose(fp);
return connected;
}
// Get eth0 MAC address
void get_mac_address(char *mac_str, size_t len) {
FILE *fp = fopen(MAC_PATH, "r");
if (!fp) {
snprintf(mac_str, len, "00:00:00:00:00:00");
return;
}
if (fgets(mac_str, len, fp)) {
mac_str[strcspn(mac_str, "\n")] = 0; // remove newline
} else {
snprintf(mac_str, len, "00:00:00:00:00:00");
}
fclose(fp);
}
int connect_server(const char *ip, int port) {
int sock;
struct sockaddr_in addr;
time_t now = time(NULL);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
//perror("socket");
printf("%ld %s ERROR: socket\n",(long int)now, PROGNAME);
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &addr.sin_addr) <= 0) {
//perror("inet_pton");
now = time(NULL);
printf("%ld %s ERROR: inet_pton\n",(long int)now, PROGNAME);
close(sock);
return -1;
}
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
//perror("connect");
now = time(NULL);
printf("%ld %s ERROR: inet_pton\n",(long int)now, PROGNAME);
close(sock);
return -1;
}
now = time(NULL);
//printf("Connected to %s:%d\n", ip, port);
printf("%ld %s Connected to %s:%d\n",(long int)now, PROGNAME, ip, port);
return sock;
}
int main(int argc, char *argv[]) {
char *server_ip = NULL;
int server_port = 0;
int interval = 0;
int opt;
while ((opt = getopt(argc, argv, "s:p:t:")) != -1) {
switch (opt) {
case 's': server_ip = optarg; break;
case 'p': server_port = atoi(optarg); break;
case 't': interval = atoi(optarg); break;
default:
fprintf(stderr, "Usage: %s -s <server_ip> -p <port> -t <seconds>\n", argv[0]);
exit(EXIT_FAILURE);
}
}
if (!server_ip || !server_port || !interval) {
fprintf(stderr, "Missing arguments.\n");
fprintf(stderr, "Usage: %s -s <server_ip> -p <port> -t <seconds>\n", argv[0]);
exit(EXIT_FAILURE);
}
signal(SIGINT, handle_sigint);
time_t now = time(NULL);
printf("%ld %s Heartbeat to %s:%d every %d seconds\n",(long int)now, PROGNAME,server_ip, server_port, interval);
int sock = -1;
while (keep_running) {
if (sock < 0) {
sock = connect_server(server_ip, server_port);
if (sock < 0) {
now = time(NULL);
printf("%ld %s Retrying connection in 5 seconds...\n",(long int)now, PROGNAME);
sleep(5);
continue;
}
}
time_t now = time(NULL);
char mac[32];
get_mac_address(mac, sizeof(mac));
int status = check_port_connected(2404);
if(0==status) {
status = check_port_connected(12404);
}
if(0==status) {
status = check_port_connected(22404);
}
char msg[256];
snprintf(msg, sizeof(msg),
"{\"mac\": \"%s\",\"status\": %d,\"epoch\": %ld}\n",
mac, status, (long int)now);
char msg_log[256];
snprintf(msg_log, sizeof(msg_log),
"mac: %s status: %d epoch: %ld",
mac, status, (long int)now);
ssize_t sent = send(sock, msg, strlen(msg), 0);
if (sent < 0) {
printf("%ld %s Not Sent: %s sendError: %ld\n", (long int)now, PROGNAME, msg_log, (long int)sent);
close(sock);
sock = -1;
sleep(5);
continue;
}
printf("%ld %s Sent: %s\n", (long int)now, PROGNAME, msg_log);
sleep(interval);
}
now = time(NULL);
if (sock >= 0) close(sock);
printf("%ld %s Heartbeat stopped.\n", (long int)now, PROGNAME);
return 0;
}