File: RELATIVE:/../../../mfix.git/model/socket.c
1
2
3
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <netdb.h>
13
14 #include <sys/select.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <err.h>
18 #include <errno.h>
19 #include <signal.h>
20
21 extern void handle_command(char*, char*, ssize_t*);
22
23 extern void flush_err_msg_gui(char*);
24
25 void die(const char *msg)
26 {
27 perror(msg);
28 exit(EXIT_FAILURE);
29 }
30
31
32
33
34
35 int cmd_sockfd, cmd_maxfd;
36 int log_sockfd, log_maxfd;
37 fd_set cmd_master, cmd_readfds;
38 fd_set log_master, log_readfds;
39
40 struct timeval timeout;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 void init_log_socket(char* port) {
62
63 struct addrinfo *res0, *res, hints;
64 int error;
65 int on = 1;
66
67 (void)memset(&hints, '\0', sizeof(struct addrinfo));
68
69 hints.ai_family = AF_INET;
70 hints.ai_socktype = SOCK_STREAM;
71 hints.ai_protocol = IPPROTO_TCP;
72 hints.ai_flags = AI_PASSIVE;
73
74 if(0 != (error = getaddrinfo(NULL, port, &hints, &res0)))
75 errx(EXIT_FAILURE, "%s", gai_strerror(error));
76
77 for(res = res0; res; res = res->ai_next)
78 {
79 if(-1 == (log_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)))
80 {
81 perror("socket()");
82 continue;
83 }
84
85 if(-1 == (setsockopt(log_sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(int))))
86 {
87 perror("setsockopt()");
88 continue;
89 }
90
91 if(-1 == (bind(log_sockfd, res->ai_addr, res->ai_addrlen)))
92 {
93 perror("bind");
94 continue;
95 }
96
97 break;
98
99 }
100
101 if(-1 == log_sockfd)
102 exit(EXIT_FAILURE);
103
104 freeaddrinfo(res0);
105
106 if(-1 == (listen(log_sockfd, 32)))
107 die("listen()");
108
109 if(-1 == (fcntl(log_sockfd, F_SETFD, O_NONBLOCK)))
110 die("fcntl()");
111
112 FD_ZERO(&log_master);
113 FD_ZERO(&log_readfds);
114
115 FD_SET(log_sockfd, &log_master);
116
117 log_maxfd = log_sockfd;
118
119 timeout.tv_sec = 0;
120 timeout.tv_usec = 0;
121
122 signal(SIGPIPE, SIG_IGN);
123
124 }
125
126 void init_cmd_socket(char* port) {
127
128 struct addrinfo *res0, *res, hints;
129 int error;
130 int on = 1;
131
132 (void)memset(&hints, '\0', sizeof(struct addrinfo));
133
134 hints.ai_family = AF_INET;
135 hints.ai_socktype = SOCK_STREAM;
136 hints.ai_protocol = IPPROTO_TCP;
137 hints.ai_flags = AI_PASSIVE;
138
139 if(0 != (error = getaddrinfo(NULL, port, &hints, &res0)))
140 errx(EXIT_FAILURE, "%s", gai_strerror(error));
141
142 for(res = res0; res; res = res->ai_next)
143 {
144 if(-1 == (cmd_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)))
145 {
146 perror("socket()");
147 continue;
148 }
149
150 if(-1 == (setsockopt(cmd_sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(int))))
151 {
152 perror("setsockopt()");
153 continue;
154 }
155
156 if(-1 == (bind(cmd_sockfd, res->ai_addr, res->ai_addrlen)))
157 {
158 perror("bind");
159 continue;
160 }
161
162 break;
163
164 }
165
166 if(-1 == cmd_sockfd)
167 exit(EXIT_FAILURE);
168
169 freeaddrinfo(res0);
170
171 if(-1 == (listen(cmd_sockfd, 32)))
172 die("listen()");
173
174 if(-1 == (fcntl(cmd_sockfd, F_SETFD, O_NONBLOCK)))
175 die("fcntl()");
176
177 FD_ZERO(&cmd_master);
178 FD_ZERO(&cmd_readfds);
179
180 FD_SET(cmd_sockfd, &cmd_master);
181
182 cmd_maxfd = cmd_sockfd;
183
184 timeout.tv_sec = 0;
185 timeout.tv_usec = 0;
186
187 signal(SIGPIPE, SIG_IGN);
188
189 }
190
191
192
193
194
195 void check_sockets() {
196
197 int nready;
198 int new;
199
200 memcpy(&cmd_readfds, &cmd_master, sizeof(cmd_master));
201 memcpy(&log_readfds, &log_master, sizeof(log_master));
202
203 if(-1 == (nready = select(log_maxfd+1, &log_readfds, NULL, NULL, &timeout)))
204 die("select()");
205
206 for(int ii=0; ii<=log_maxfd && nready>0; ii++) {
207 if(FD_ISSET(ii, &log_readfds)) {
208 nready--;
209
210 if(ii == log_sockfd) {
211 if(-1 == (new = accept(log_sockfd, NULL, NULL))) {
212 if(EWOULDBLOCK != errno)
213 perror("accept()");
214
215 break;
216 } else {
217 if(-1 == (fcntl(new, F_SETFD, O_NONBLOCK)))
218 die("fcntl()");
219
220 FD_SET(new, &log_master);
221
222 if(log_maxfd < new)
223 log_maxfd = new;
224 }
225 } else {
226 char outbuffer[BUFSIZ];
227 flush_err_msg_gui(outbuffer);
228
229 ssize_t nbytes;
230 if ((nbytes = send(ii, outbuffer, strlen(outbuffer), 0)) == -1) {
231
232 ("send");
233 close(ii);
234 FD_CLR(ii, &log_master);
235 }
236 }
237 }
238 }
239
240 if(-1 == (nready = select(cmd_maxfd+1, &cmd_readfds, NULL, NULL, &timeout)))
241 die("select()");
242
243 for(int ii=0; ii<=cmd_maxfd && nready>0; ii++) {
244 if(FD_ISSET(ii, &cmd_readfds)) {
245 nready--;
246
247 if(ii == cmd_sockfd) {
248 if(-1 == (new = accept(cmd_sockfd, NULL, NULL))) {
249 if(EWOULDBLOCK != errno)
250 perror("accept()");
251
252 break;
253 } else {
254 if(-1 == (fcntl(new, F_SETFD, O_NONBLOCK)))
255 die("fcntl()");
256
257 FD_SET(new, &cmd_master);
258
259 if(cmd_maxfd < new)
260 cmd_maxfd = new;
261 }
262 } else {
263 char buffer[BUFSIZ];
264 char outbuffer[BUFSIZ];
265
266 ssize_t nbytes;
267 if ((nbytes = recv(ii, buffer, strlen(buffer), 0)) == -1) {
268 if(nbytes <= 0) {
269 if(EWOULDBLOCK != errno)
270 die("recv()");
271
272 break;
273 }
274 }
275
276 handle_command(outbuffer, buffer, &nbytes);
277
278 if ((nbytes = send(ii, outbuffer, strlen(outbuffer), 0)) == -1) {
279
280 ("send");
281 close(ii);
282 FD_CLR(ii, &cmd_master);
283 }
284 }
285 }
286 }
287
288 }
289