Subversion Repositories MLServ

Rev

Rev 5 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

/* $Id: server.c 7 2024-09-25 00:56:55Z nishi $ */

#include "ms_server.h"

#include <stdio.h>
#include <poll.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>

#include <cm_string.h>
#include <cm_ipc.h>
#include <cm_db.h>

#define strsend(sock, str) send(sock, str, strlen(str), 0)

void ms_handle_socket(int sock) {
        sqlite3* db = cm_db_init();
        if(db == NULL) {
                strsend(sock, "DBERROR\n");
                return;
        }
        int bad = 0;
        char* line = malloc(1);
        line[0] = 0;
        struct pollfd pollfds[1];
        pollfds[0].fd = sock;
        pollfds[0].events = POLLIN | POLLPRI;
        strsend(sock, "READY\n");
        while(1) {
                int ret = poll(pollfds, 1, 5000);
                if(ret < 0) {
                        break;
                } else if(ret == 0) {
                        strsend(sock, "TIMEOUT\n");
                        break;
                } else {
                        int i;
                        char buffer[512];
                        char cbuf[2];
                        cbuf[1] = 0;
                        int len = recv(sock, buffer, 512, 0);
                        for(i = 0; i < len; i++) {
                                if(buffer[i] == '\n') {
                                        if(strcmp(line, "BYE") == 0) {
                                                goto brk;
                                        } else if(strcmp(line, "LIST-ML") == 0) {
                                                char** list = cm_list_ml(db);
                                                if(list != NULL) {
                                                        strsend(sock, "BEGIN\n");
                                                        strsend(sock, "END\n");
                                                        int j;
                                                        for(j = 0; list[j] != NULL; j++) free(list[j]);
                                                        free(list);
                                                } else {
                                                        strsend(sock, "DBERROR\n");
                                                        goto nobye;
                                                }
                                        } else {
                                                strsend(sock, "SYNERR\n");
                                                bad++;
                                        }
                                        if(bad >= 3) {
                                                goto brk;
                                        }
                                        free(line);
                                        line = malloc(1);
                                        line[0] = 0;
                                } else if(buffer[i] != '\r') {
                                        cbuf[0] = buffer[i];
                                        char* tmp = line;
                                        line = cm_strcat(tmp, cbuf);
                                        free(tmp);
                                }
                        }
                }
        }
brk:
        strsend(sock, "BYE\n");
nobye:
        free(line);
        sqlite3_close(db);
}

int ms_handle_server(int argc, char** argv, int start) {
        int sock = cm_ipc_create();
        if(sock == -1) {
                fprintf(stderr, "Failed to create the socket\n");
        }
        signal(SIGPIPE, SIG_IGN);
        signal(SIGCHLD, SIG_IGN);
        printf("MLServ server ready\n");
        struct pollfd pollfds[1];
        pollfds[0].fd = sock;
        pollfds[0].events = POLLIN | POLLPRI;
        while(1) {
                int ret = poll(pollfds, 1, 1000);
                if(ret < 0) {
                        return 1;
                } else if(ret == 0) {

                } else if(ret > 0 && pollfds[0].revents & POLLIN) {
                        struct sockaddr_un claddr;
                        int clen = sizeof(claddr);

                        int csock = accept(sock, (struct sockaddr*)&claddr, &clen);
                        if(csock < 0) return 1;

                        if(fork() == 0) {
                                ms_handle_socket(csock);
                                close(csock);
                                _exit(0);
                        } else {
                                close(csock);
                        }
                }
        }
        return 0;
}