heartbeat / heartbeat-cli.c /
Yanik Cawidrone Init
2af1abf 3 months ago
1 contributor
185 lines | 4.761kb
#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;
}