flist request
[reposerve] / server / src / main.c
index c4e0846..56dbe6f 100644 (file)
@@ -1,20 +1,49 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 #include <limits.h>
+#include <time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
 #include "repo.h"
+#include "client.h"
 
 static const char *guess_repo_name(const char *path);
+static void sighandler(int s);
 static int parse_args(int argc, char **argv);
 
-static const char *repo_path, *repo_name;
+static const char *repo_name;
+static int lis = -1;
+static int port = 64357;
+static int quit;
+
+static struct client *clients;
+
+const char *repo_path;
+
 
 int main(int argc, char **argv)
 {
+       struct sockaddr_in addr;
+
        if(parse_args(argc, argv) == -1) {
                return 1;
        }
 
+       signal(SIGINT, sighandler);
+       signal(SIGQUIT, sighandler);
+       signal(SIGILL, sighandler);
+       signal(SIGSEGV, sighandler);
+       signal(SIGTERM, sighandler);
+       signal(SIGPIPE, SIG_IGN);
+
        if(repo_init(repo_path) == -1) {
                return 1;
        }
@@ -28,14 +57,91 @@ int main(int argc, char **argv)
 
        printf("Serving %s from %s\n", repo_name, repo_path);
 
-       /* DBG */
-       {
-               int i, count = repo_num_files();
-               for(i=0; i<count; i++) {
-                       printf("%s\n", repo_file(i));
+       if(!(lis = socket(PF_INET, SOCK_STREAM, 0))) {
+               fprintf(stderr, "failed to create socket: %s\n", strerror(errno));
+               return 1;
+       }
+       fcntl(lis, F_SETFL, fcntl(lis, F_GETFL) | O_NONBLOCK);
+
+       memset(&addr, 0, sizeof addr);
+       addr.sin_family = AF_INET;
+       addr.sin_port = htons(port);
+       addr.sin_addr.s_addr = INADDR_ANY;
+
+       if(bind(lis, (struct sockaddr*)&addr, sizeof addr) == -1) {
+               fprintf(stderr, "failed to bind listening socket to port %d\n", port);
+               return 1;
+       }
+       listen(lis, 8);
+
+       for(;;) {
+               int res, max_fd, s;
+               fd_set rdset;
+               struct client *c, dummy;
+
+               FD_SET(lis, &rdset);
+               max_fd = lis;
+
+               c = clients;
+               while(c) {
+                       FD_SET(c->s, &rdset);
+                       if(c->s > max_fd) max_fd = c->s;
+                       c = c->next;
+               }
+
+               if((res = select(max_fd + 1, &rdset, 0, 0, 0)) == -1 && errno != EINTR) {
+                       perror("select failed");
+                       break;
+               }
+               if(quit) break;
+               if(res <= 0) continue;
+
+               dummy.next = clients;
+               c = &dummy;
+               while(c->next) {
+                       if(FD_ISSET(c->next->s, &rdset)) {
+                               if(handle_client(c->next) == -1) {
+                                       struct client *tmp = c->next;
+                                       c->next = tmp->next;
+
+                                       printf("Client %s disconnected\n", tmp->addr ? tmp->addr : "unknown");
+                                       close(tmp->s);
+                                       free(tmp->addr);
+                                       free(tmp);
+                                       continue;
+                               }
+                       }
+                       c = c->next;
+               }
+               clients = dummy.next;
+
+               if(FD_ISSET(lis, &rdset)) {
+                       struct sockaddr_in addr;
+                       unsigned int addrsz = sizeof addr;
+
+                       if((s = accept(lis, (struct sockaddr*)&addr, &addrsz)) == -1) {
+                               perror("failed to accept connection");
+                               continue;
+                       }
+                       fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
+
+                       if(!(c = calloc(1, sizeof *c))) {
+                               perror("failed to allocate memory for client structure");
+                               close(s);
+                               continue;
+                       }
+                       c->s = s;
+                       c->next = clients;
+                       c->addr = strdup(inet_ntoa(addr.sin_addr));
+                       clients = c;
+
+                       send_string(c, "reposerve-0.1 protocol:0\n");
+
+                       printf("Connection from: %s\n", c->addr ? c->addr : "unknown");
                }
        }
 
+       printf("Shutting down\n");
        return 0;
 }
 
@@ -65,6 +171,11 @@ fail:
        return 0;
 }
 
+static void sighandler(int s)
+{
+       quit = 1;
+}
+
 static void print_usage(const char *argv0)
 {
        printf("Usage: %s [options] [repo path]\n", argv0);