Subversion Repositories MLServ

Rev

Rev 7 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 nishi 1
/* $Id: server.c 9 2024-09-25 01:17:09Z 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");
9 nishi 40
			goto nobye;
5 nishi 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);
9 nishi 47
			if(len <= 0) break;
5 nishi 48
			for(i = 0; i < len; i++) {
7 nishi 49
				if(buffer[i] == '\n') {
50
					if(strcmp(line, "BYE") == 0) {
51
						goto brk;
52
					} else if(strcmp(line, "LIST-ML") == 0) {
53
						char** list = cm_list_ml(db);
54
						if(list != NULL) {
9 nishi 55
							int j;
7 nishi 56
							strsend(sock, "BEGIN\n");
9 nishi 57
							for(j = 0; list[j] != NULL; j += 2) {
58
								strsend(sock, list[j + 0]);
59
								strsend(sock, "\t");
60
								strsend(sock, list[j + 1]);
61
								strsend(sock, "\n");
62
								free(list[j + 0]);
63
								free(list[j + 1]);
64
							}
7 nishi 65
							strsend(sock, "END\n");
66
							free(list);
67
						} else {
68
							strsend(sock, "DBERROR\n");
69
							goto nobye;
70
						}
71
					} else {
72
						strsend(sock, "SYNERR\n");
73
						bad++;
74
					}
75
					if(bad >= 3) {
76
						goto brk;
77
					}
78
					free(line);
79
					line = malloc(1);
80
					line[0] = 0;
81
				} else if(buffer[i] != '\r') {
82
					cbuf[0] = buffer[i];
83
					char* tmp = line;
84
					line = cm_strcat(tmp, cbuf);
85
					free(tmp);
86
				}
5 nishi 87
			}
88
		}
89
	}
7 nishi 90
brk:
91
	strsend(sock, "BYE\n");
92
nobye:
93
	free(line);
5 nishi 94
	sqlite3_close(db);
95
}
96
 
4 nishi 97
int ms_handle_server(int argc, char** argv, int start) {
98
	int sock = cm_ipc_create();
99
	if(sock == -1) {
100
		fprintf(stderr, "Failed to create the socket\n");
101
	}
5 nishi 102
	signal(SIGPIPE, SIG_IGN);
103
	signal(SIGCHLD, SIG_IGN);
104
	printf("MLServ server ready\n");
105
	struct pollfd pollfds[1];
106
	pollfds[0].fd = sock;
107
	pollfds[0].events = POLLIN | POLLPRI;
108
	while(1) {
109
		int ret = poll(pollfds, 1, 1000);
110
		if(ret < 0) {
111
			return 1;
112
		} else if(ret == 0) {
7 nishi 113
 
5 nishi 114
		} else if(ret > 0 && pollfds[0].revents & POLLIN) {
115
			struct sockaddr_un claddr;
116
			int clen = sizeof(claddr);
117
 
118
			int csock = accept(sock, (struct sockaddr*)&claddr, &clen);
119
			if(csock < 0) return 1;
120
 
121
			if(fork() == 0) {
122
				ms_handle_socket(csock);
123
				close(csock);
124
				_exit(0);
125
			} else {
126
				close(csock);
127
			}
128
		}
129
	}
4 nishi 130
	return 0;
131
}