Updated tomd and tomc to do solid communication over sockets.
[tlb/tomd.git] / src / tomd / main.c
index 1b97524..dea236d 100644 (file)
 #include <sys/stat.h>
 #include <sys/socket.h>
 
+#include "../../include/macros.h"
+#include "../../include/manifest.h"
+
 static void header(void)
 {
-  printf("[tomd] Tom's Daemon, Copyright (C) 2018 Thomas Balzer\n");
-  printf("[tomd] GPL v3 or later license.\n");
+  tomd_p("Tom's Daemon, Copyright (C) 2018 Thomas Balzer");
+  tomd_p("GPL v3 or later license.");
 }
 
 static int sfd;
@@ -46,7 +49,7 @@ static void gen_socket_filename(void)
           "/run/user/%d/tomd/socket",
           this_user_id);
 
-  printf("[tomd] making dir '%s'\n", socket_dirname);
+  tomd_p("making dir '%s'", socket_dirname);
   /* lazy way */
   char buf[100];
   sprintf(buf, "mkdir -p %s", socket_dirname);
@@ -56,10 +59,10 @@ static void gen_socket_filename(void)
   /*   exit(EXIT_FAILURE); */
   /* } */
 
-  printf("[tomd] removing file '%s'\n", socket_filename);
+  tomd_p("removing file '%s'", socket_filename);
   if(unlink(socket_filename) != 0){
     if(errno == ENOENT){
-      printf("[tomd] socket file doesn't exist\n");
+      tomd_p("socket file doesn't exist");
     }else{
       perror("[tomd] socket unlink");
       exit(EXIT_FAILURE);
@@ -67,7 +70,7 @@ static void gen_socket_filename(void)
   }
 }
 
-static void init(void)
+static void socket_init(void)
 {
   gen_socket_filename();
   
@@ -92,7 +95,7 @@ static void init(void)
           sizeof(name.sun_path));
 
   size = SUN_LEN(&name);
-  printf("[tomd] attempting to bind to '%s'\n",
+  tomd_p("attempting to bind to '%s'",
          socket_filename);
   if(bind(sfd,
           (struct sockaddr *) &name,
@@ -101,10 +104,22 @@ static void init(void)
     exit(EXIT_FAILURE);
   }
 
-  printf("[tomd] initialized tomd socket connections\n");
+  tomd_p("initialized tomd socket connections");
 }
 
-/* These defines are here to improve the local readability */
+static void init(void)
+{
+  socket_init();
+  load_jobs();
+}
+
+#define SEND_ACK {                                                      \
+    int size;                                                           \
+    if(size = write(asfd, "ACK", sizeof "ACK") != sizeof "ACK") {       \
+      tomd_p("didn't send as much as we though (%d != %d)", size, sizeof "ACK"); \
+    }                                                                   \
+  }
+
 #define CHDIR            0
 #define DONT_CHDIR       1
 #define CLOSE_PIPES      0
@@ -120,6 +135,85 @@ static void daemonize(void)
   daemon(DONT_CHDIR, DONT_CLOSE_PIPES);
 }
 
+#define READ_SOCKET {\
+    int size = read(asfd, buf, 100);            \
+    buf[size] = '\0';                           \
+  }
+
+static int validate_sender(int asfd, char *buf)
+{
+  READ_SOCKET;
+  if(strcmp(buf, "client:tomc") == 0){
+    SEND_ACK;
+    return 0;
+  }
+  tomd_p("received '%s' instead of client:tomc", buf);
+  return -1;
+}
+
+enum requests { KILL, STATUS, STOP, START, UNKNOWN};
+#define X(a, b) { a, b }
+static struct {
+  char *str;
+  enum requests request;
+} request_types[] =
+  {
+   X("kill", KILL),
+   X("status", STATUS),
+   X("start", START),
+   X("stop", STOP),
+   X(NULL, -1)
+  };
+#undef X
+
+static void handle_request(int asfd, char *buf)
+{
+  READ_SOCKET;
+  enum requests request = UNKNOWN;
+  int i = 0;
+  while(1){
+    if(request_types[i].str == NULL){
+      break;
+    }
+
+    tomd_p("loop [%d]: comparing '%s' to '%s'",
+           i, buf, request_types[i].str);
+    if(strcmp(buf, request_types[i].str) == 0){
+      request = request_types[i].request;
+      break;
+    }
+    
+    i++;
+  }
+
+  if(request == UNKNOWN){
+    tomd_p("unknown request type!");
+    return;
+  }
+
+  SEND_ACK;
+  READ_SOCKET;
+  // cross reference given name against known services
+  tomd_p("looking up '%s'", buf);
+  SEND_ACK;
+  /* lookup_job(buf); */
+}
+
+static void handle_connection(int asfd)
+{
+  char buf[100] = {};
+
+  if(validate_sender(asfd, buf) != 0){
+    tomd_p("invalid sender.");
+    return;
+  }
+
+  tomd_p("validated client");
+  handle_request(asfd, buf);
+
+  close(asfd);
+}
+
 static void run(void)
 {
   /* loop: */
@@ -134,30 +228,26 @@ static void run(void)
     exit(EXIT_FAILURE);
   }
 
+  int i = 0;
   for(;;){
     struct sockaddr addr;
-    socklen_t size;
+    /* sometimes gives EINVAL if not initialized. */
+    socklen_t size = sizeof(addr);
+    tomd_p("accept loop [%d]", i++);
+    errno = 0;
     int accept_sfd =
       accept(sfd,
              &addr,             /* requester info */
              &size);            /* len of requester info */
     if(accept_sfd < 0){
+      if(errno == EINVAL){
+        tomd_p("EINVAL");
+      }
       perror("[tomd] accept socket");
       exit(EXIT_FAILURE);
     }
-
-    /* int getsockname(accept_sfd, */
-    /*                 addr, */
-    /*                 size); */
-    
-    printf("[tomd] accepted socket connection from '%s'\n",
-           ((struct sockaddr_un *) &addr)->sun_path);
-
-    char accept_buf[100] = {};
     
-    read(accept_sfd, accept_buf, 100);
-    printf("[tomd] got message '%s'\n, accept_buf");
-    close(accept_sfd);
+    handle_connection(accept_sfd);
   }
 }
 
@@ -172,6 +262,7 @@ int main(int argc, char **argv)
 {
   header();
   init();
+  run_jobs();
   daemonize();
   run();
   cleanup();