Subversion Repositories MLServ

Rev

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

Rev Author Line No. Line
4 nishi 1
/* $Id: server.c 7 2024-09-25 00:56:55Z nishi $ */
2
 
3
#include "ms_server.h"
4
 
5
#include <stdio.h>
5 nishi 6
#include <poll.h>
7
#include <sys/un.h>
8
#include <sys/socket.h>
9
#include <signal.h>
7 nishi 10
#include <stdlib.h>
5 nishi 11
#include <unistd.h>
12
#include <string.h>
7 nishi 13
#include <stdbool.h>
4 nishi 14
 
7 nishi 15
#include <cm_string.h>
4 nishi 16
#include <cm_ipc.h>
5 nishi 17
#include <cm_db.h>
4 nishi 18
 
5 nishi 19
#define strsend(sock, str) send(sock, str, strlen(str), 0)
20
 
21
void ms_handle_socket(int sock) {
22
	sqlite3* db = cm_db_init();
23
	if(db == NULL) {
7 nishi 24
		strsend(sock, "DBERROR\n");
5 nishi 25
		return;
26
	}
7 nishi 27
	int bad = 0;
28
	char* line = malloc(1);
29
	line[0] = 0;
5 nishi 30
	struct pollfd pollfds[1];
31
	pollfds[0].fd = sock;
32
	pollfds[0].events = POLLIN | POLLPRI;
7 nishi 33
	strsend(sock, "READY\n");
5 nishi 34
	while(1) {
7 nishi 35
		int ret = poll(pollfds, 1, 5000);
5 nishi 36
		if(ret < 0) {
37
			break;
38
		} else if(ret == 0) {
7 nishi 39
			strsend(sock, "TIMEOUT\n");
5 nishi 40
			break;
41
		} else {
42
			int i;
43
			char buffer[512];
7 nishi 44
			char cbuf[2];
45
			cbuf[1] = 0;
5 nishi 46
			int len = recv(sock, buffer, 512, 0);
47
			for(i = 0; i < len; i++) {
7 nishi 48
				if(buffer[i] == '\n') {
49
					if(strcmp(line, "BYE") == 0) {
50
						goto brk;
51
					} else if(strcmp(line, "LIST-ML") == 0) {
52
						char** list = cm_list_ml(db);
53
						if(list != NULL) {
54
							strsend(sock, "BEGIN\n");
55
							strsend(sock, "END\n");
56
							int j;
57
							for(j = 0; list[j] != NULL; j++) free(list[j]);
58
							free(list);
59
						} else {
60
							strsend(sock, "DBERROR\n");
61
							goto nobye;
62
						}
63
					} else {
64
						strsend(sock, "SYNERR\n");
65
						bad++;
66
					}
67
					if(bad >= 3) {
68
						goto brk;
69
					}
70
					free(line);
71
					line = malloc(1);
72
					line[0] = 0;
73
				} else if(buffer[i] != '\r') {
74
					cbuf[0] = buffer[i];
75
					char* tmp = line;
76
					line = cm_strcat(tmp, cbuf);
77
					free(tmp);
78
				}
5 nishi 79
			}
80
		}
81
	}
7 nishi 82
brk:
83
	strsend(sock, "BYE\n");
84
nobye:
85
	free(line);
5 nishi 86
	sqlite3_close(db);
87
}
88
 
4 nishi 89
int ms_handle_server(int argc, char** argv, int start) {
90
	int sock = cm_ipc_create();
91
	if(sock == -1) {
92
		fprintf(stderr, "Failed to create the socket\n");
93
	}
5 nishi 94
	signal(SIGPIPE, SIG_IGN);
95
	signal(SIGCHLD, SIG_IGN);
96
	printf("MLServ server ready\n");
97
	struct pollfd pollfds[1];
98
	pollfds[0].fd = sock;
99
	pollfds[0].events = POLLIN | POLLPRI;
100
	while(1) {
101
		int ret = poll(pollfds, 1, 1000);
102
		if(ret < 0) {
103
			return 1;
104
		} else if(ret == 0) {
7 nishi 105
 
5 nishi 106
		} else if(ret > 0 && pollfds[0].revents & POLLIN) {
107
			struct sockaddr_un claddr;
108
			int clen = sizeof(claddr);
109
 
110
			int csock = accept(sock, (struct sockaddr*)&claddr, &clen);
111
			if(csock < 0) return 1;
112
 
113
			if(fork() == 0) {
114
				ms_handle_socket(csock);
115
				close(csock);
116
				_exit(0);
117
			} else {
118
				close(csock);
119
			}
120
		}
121
	}
4 nishi 122
	return 0;
123
}