1 | /* server.c
|
---|
2 |
|
---|
3 |
|
---|
4 |
|
---|
5 | SERVER
|
---|
6 |
|
---|
7 |
|
---|
8 | FIXME
|
---|
9 | - when sysadm requests it:-
|
---|
10 | - connect to relevant port of client
|
---|
11 | - send trigger_backup msg
|
---|
12 | - receive file(s)
|
---|
13 | - close client's port
|
---|
14 |
|
---|
15 | 05/20
|
---|
16 | - changed 'clientname' to 'clientIP'
|
---|
17 |
|
---|
18 | 05/11
|
---|
19 | - clarified structures & their names
|
---|
20 | - improved login/logout OK/fail feedback
|
---|
21 |
|
---|
22 | 05/10
|
---|
23 | - made main loop multithreaded (replaced multiple forks)
|
---|
24 | - thanks to the move from forks to threads, clientlist
|
---|
25 | is now shared between processes automatically
|
---|
26 | - replaced printf()'s and fprintf()'s with log_it() function
|
---|
27 | and levels debug/info/warn/error/fatal
|
---|
28 |
|
---|
29 | 05/08
|
---|
30 | - got down to some housecleaning
|
---|
31 | - added comments; removed strcpy()'s
|
---|
32 | - replaced silly exit()'s with return()'s
|
---|
33 |
|
---|
34 | */
|
---|
35 |
|
---|
36 |
|
---|
37 |
|
---|
38 |
|
---|
39 | #include "structs.h"
|
---|
40 |
|
---|
41 | #define LOG_THESE_AND_HIGHER debug /* debug, info, warn, error, fatal */
|
---|
42 | #define NOOF_THREADS 10
|
---|
43 |
|
---|
44 |
|
---|
45 |
|
---|
46 |
|
---|
47 | /* global vars */
|
---|
48 |
|
---|
49 | struct s_clientlist g_clientlist; /* FIXME - lock during login/logout, using mutexes */
|
---|
50 |
|
---|
51 |
|
---|
52 |
|
---|
53 |
|
---|
54 | /* prototypes */
|
---|
55 |
|
---|
56 | int backup_client(int,char*);
|
---|
57 | int find_client_in_clientlist(char *);
|
---|
58 | int handle_incoming_message(int, struct sockaddr_in *, struct s_client2server_msg_record *);
|
---|
59 | int handle_login_request(int, struct s_client2server_msg_record *, char *);
|
---|
60 | int handle_logout_request(int, struct s_client2server_msg_record *, char *);
|
---|
61 | int handle_ping_request(int, struct s_client2server_msg_record *, char *);
|
---|
62 | void log_it(t_loglevel, char *);
|
---|
63 | int restore_client(int,char*);
|
---|
64 | int send_msg_to_client(struct s_server2client_msg_record *, char *, int);
|
---|
65 | void start_threads_to_watch_ports_for_requests(void);
|
---|
66 | void interact_with_sysadm(void);
|
---|
67 | char *tmsg_to_string(t_msg);
|
---|
68 | void* watch_port_for_requests_from_clients(void*);
|
---|
69 |
|
---|
70 |
|
---|
71 |
|
---|
72 | /* subroutines */
|
---|
73 |
|
---|
74 | int backup_client(int clientno, char*path)
|
---|
75 | /*
|
---|
76 | Purpose:Backup the path of a specific client. Receive
|
---|
77 | the archives. Store them locally (on me, the server).
|
---|
78 | Params: clientno - client# in g_clientlist[]
|
---|
79 | path - client's path to be backed up
|
---|
80 | Return: result (0=success, nonzero=failure)
|
---|
81 | */
|
---|
82 | {
|
---|
83 | struct s_server2client_msg_record rec_to_client;
|
---|
84 | int i, res=0;
|
---|
85 | char tmp[MAX_STR_LEN];
|
---|
86 |
|
---|
87 | sprintf(tmp, "Client# = %d", clientno);
|
---|
88 | log_it(debug, tmp);
|
---|
89 | if (clientno >= g_clientlist.items)
|
---|
90 | { log_it(fatal, "backup_client: clientno>=g_clientlist.items"); }
|
---|
91 | sprintf(tmp, "Backing up %s - path=%s", g_clientlist.el[clientno].ipaddr, path);
|
---|
92 | log_it(info, tmp);
|
---|
93 | rec_to_client.msg_type = trigger_backup;
|
---|
94 | strncpy(rec_to_client.body, path, sizeof(rec_to_client.body));
|
---|
95 | if (send_msg_to_client(&rec_to_client, g_clientlist.el[clientno].ipaddr, g_clientlist.el[clientno].port))
|
---|
96 | { log_it(error, "backup_client - failed to send msg to client"); return(1); }
|
---|
97 |
|
---|
98 | if (res)
|
---|
99 | {
|
---|
100 | sprintf(tmp, "Error(s) occurred while backing up %s", g_clientlist.el[clientno].ipaddr);
|
---|
101 | log_it(error, tmp);
|
---|
102 | return(1);
|
---|
103 | }
|
---|
104 | else
|
---|
105 | {
|
---|
106 | sprintf(tmp, "Backed up %s OK", g_clientlist.el[clientno].ipaddr);
|
---|
107 | log_it(error, tmp);
|
---|
108 | return(0);
|
---|
109 | }
|
---|
110 | }
|
---|
111 |
|
---|
112 |
|
---|
113 |
|
---|
114 | int find_client_in_clientlist(char *clientIP)
|
---|
115 | /*
|
---|
116 | Purpose:Find a client in the clientlist (list of logged-in
|
---|
117 | clients).
|
---|
118 | Params: clientIP - IP address of client
|
---|
119 | Return: result (<0=not found, 0+=found in element N)
|
---|
120 | */
|
---|
121 | {
|
---|
122 | int i;
|
---|
123 | char tmp[MAX_STR_LEN];
|
---|
124 |
|
---|
125 | for(i = 0; i < g_clientlist.items; i++)
|
---|
126 | {
|
---|
127 | if (!strcmp(clientIP, g_clientlist.el[i].ipaddr))
|
---|
128 | { return(i); }
|
---|
129 | sprintf(tmp, "find_client_in_clientlist: Compared %s to clientlist[%d]=%s; failed\n", clientIP, i, g_clientlist.el[i].ipaddr);
|
---|
130 | log_it(debug, tmp);
|
---|
131 | }
|
---|
132 | return(-1);
|
---|
133 | }
|
---|
134 |
|
---|
135 |
|
---|
136 |
|
---|
137 | int handle_incoming_message(int skt, struct sockaddr_in *sin, struct s_client2server_msg_record *rec)
|
---|
138 | /*
|
---|
139 | Purpose:Process message which has just arrived from client.
|
---|
140 | A 'message' could be a login/logout request or a ping.
|
---|
141 | Params: skt - client's port to respond to
|
---|
142 | sin - client's IP address, in sockaddr_in structure
|
---|
143 | rec - data received from client
|
---|
144 | Return: result (0=success, nonzero=failure)
|
---|
145 | */
|
---|
146 | {
|
---|
147 | char clientIP[MAX_STR_LEN], *ptr, tmp[MAX_STR_LEN];
|
---|
148 | int res=0;
|
---|
149 |
|
---|
150 | // echo_ipaddr_to_screen(&sin->sin_addr);
|
---|
151 | ptr = (unsigned char*)(&sin->sin_addr);
|
---|
152 | sprintf(clientIP, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
|
---|
153 | sprintf(tmp, "clientIP = %s", clientIP);
|
---|
154 | log_it(debug, tmp);
|
---|
155 | switch(rec->msg_type)
|
---|
156 | {
|
---|
157 | case login:
|
---|
158 | res=handle_login_request(skt, rec, clientIP);
|
---|
159 | break;
|
---|
160 | case ping:
|
---|
161 | res=handle_ping_request(skt, rec, clientIP);
|
---|
162 | break;
|
---|
163 | case logout:
|
---|
164 | res=handle_logout_request(skt, rec, clientIP);
|
---|
165 | break;
|
---|
166 | default:
|
---|
167 | sprintf(tmp, "%s request from %s [%s] (port %d) - how do I handle it?", tmsg_to_string(rec->msg_type), clientIP, rec->body, rec->port);
|
---|
168 | log_it(error, tmp);
|
---|
169 | }
|
---|
170 | return(res);
|
---|
171 | }
|
---|
172 |
|
---|
173 |
|
---|
174 |
|
---|
175 | int handle_login_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP)
|
---|
176 | /*
|
---|
177 | Purpose:Handle a login request which has just been received
|
---|
178 | from client.
|
---|
179 | Params: skt - client's port to talk to
|
---|
180 | rec_from_client - login rq record received from client
|
---|
181 | clientIP - client's IP address, in string
|
---|
182 | Return: result (0=success, nonzero=failure)
|
---|
183 | */
|
---|
184 | {
|
---|
185 | struct s_server2client_msg_record rec_to_client;
|
---|
186 | int clientno;
|
---|
187 | char tmp[MAX_STR_LEN];
|
---|
188 |
|
---|
189 | sprintf(tmp, "Login request from %s [%s] (port %d)", clientIP, rec_from_client->body, rec_from_client->port);
|
---|
190 | log_it(info, tmp);
|
---|
191 | clientno = find_client_in_clientlist(clientIP);
|
---|
192 | if (clientno>=0)
|
---|
193 | {
|
---|
194 | rec_to_client.msg_type = fail;
|
---|
195 | sprintf(rec_to_client.body, "Sorry, you're already logged in!");
|
---|
196 | sprintf(tmp, "Ignoring login rq from %s: he's already logged in.", clientIP);
|
---|
197 | log_it(error, tmp);
|
---|
198 | /* FIXME - ping client (which will have a child watching for incoming
|
---|
199 | packets by now - you didn't forget to do that, did you? :)) - to find out
|
---|
200 | if client is still running. If it's not then say OK, forget it, I'll kill
|
---|
201 | that old connection and log you in anew. If it _is_ then say hey, you're
|
---|
202 | already logged in; either you're an idiot or you're a hacker. */
|
---|
203 | }
|
---|
204 | else
|
---|
205 | {
|
---|
206 | rec_to_client.msg_type = login_ok; /* to confirm login */
|
---|
207 | sprintf(rec_to_client.body, "Thanks for logging in.");
|
---|
208 | clientno = g_clientlist.items;
|
---|
209 | strncpy(g_clientlist.el[clientno].hostname_pretty, rec_from_client->body, sizeof(g_clientlist.el[clientno].hostname_pretty));
|
---|
210 | strncpy(g_clientlist.el[clientno].ipaddr, clientIP, sizeof(g_clientlist.el[clientno].ipaddr));
|
---|
211 | g_clientlist.el[clientno].port = rec_from_client->port;
|
---|
212 | g_clientlist.items ++;
|
---|
213 | sprintf(tmp, "Login request from %s ACCEPTED", clientIP);
|
---|
214 | log_it(info, tmp);
|
---|
215 | }
|
---|
216 | send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port);
|
---|
217 | return(0);
|
---|
218 | }
|
---|
219 |
|
---|
220 |
|
---|
221 |
|
---|
222 | int handle_logout_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP)
|
---|
223 | /*
|
---|
224 | Purpose:Handle a logout request which has just been received
|
---|
225 | from client.
|
---|
226 | Params: skt - client's port to talk to
|
---|
227 | rec_from_client - login rq record received from client
|
---|
228 | clientIP - client's IP address, in string
|
---|
229 | Return: result (0=success, nonzero=failure)
|
---|
230 | */
|
---|
231 | {
|
---|
232 | struct s_server2client_msg_record rec_to_client;
|
---|
233 | int i, res=0;
|
---|
234 | char tmp[MAX_STR_LEN];
|
---|
235 |
|
---|
236 | sprintf(tmp, "Logout request from %s [%s] (port %d)", clientIP, rec_from_client->body, rec_from_client->port);
|
---|
237 | log_it(info, tmp);
|
---|
238 | i = find_client_in_clientlist(clientIP);
|
---|
239 | if (i<0)
|
---|
240 | {
|
---|
241 | sprintf(rec_to_client.body, "Client is not logged in yet. How can I log him out?");
|
---|
242 | log_it(error, rec_to_client.body);
|
---|
243 | rec_to_client.msg_type = fail;
|
---|
244 | res=1;
|
---|
245 | }
|
---|
246 | else
|
---|
247 | {
|
---|
248 | sprintf(rec_to_client.body, "Removed client#%d from login table. Thanks for logging out.", i);
|
---|
249 | for(; i<g_clientlist.items; i++)
|
---|
250 | {
|
---|
251 | memcpy((char*)(&g_clientlist.el[i]), (char*)(&g_clientlist.el[i+1]), sizeof(struct s_registered_client_record));
|
---|
252 | }
|
---|
253 | strncpy(g_clientlist.el[i].hostname_pretty, "WTF? Someone teach Hugo to handle pointers properly, please!", sizeof(g_clientlist.el[i].hostname_pretty));
|
---|
254 | g_clientlist.items--;
|
---|
255 | rec_to_client.msg_type = logout_ok; /* to confirm logout */
|
---|
256 | sprintf(tmp, "Logout request from %s ACCEPTED", clientIP);
|
---|
257 | log_it(info, tmp);
|
---|
258 | }
|
---|
259 | send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port);
|
---|
260 | return(res);
|
---|
261 | }
|
---|
262 |
|
---|
263 |
|
---|
264 |
|
---|
265 | int handle_ping_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP)
|
---|
266 | /*
|
---|
267 | Purpose:Handle a ping request which has just been received
|
---|
268 | from client.
|
---|
269 | Params: skt - client's port to talk to
|
---|
270 | rec_from_client - login rq record received from client
|
---|
271 | clientIP - client's IP address, in string
|
---|
272 | Return: result (0=success, nonzero=failure)
|
---|
273 | */
|
---|
274 | {
|
---|
275 | struct s_server2client_msg_record rec_to_client;
|
---|
276 | int i;
|
---|
277 | char tmp[MAX_STR_LEN];
|
---|
278 |
|
---|
279 | sprintf(tmp, "ping request from port %d --- %s", rec_from_client->port, rec_from_client->body);
|
---|
280 | log_it(info, tmp);
|
---|
281 | i = find_client_in_clientlist(clientIP);
|
---|
282 | if (i < 0)
|
---|
283 | {
|
---|
284 | sprintf(tmp, "Hey, %s isn't logged in. I'm not going to pong him.", clientIP);
|
---|
285 | log_it(error, tmp);
|
---|
286 | }
|
---|
287 | else
|
---|
288 | {
|
---|
289 | rec_to_client.msg_type = pong; /* reply to ping */
|
---|
290 | sprintf(rec_to_client.body, "Hey, I'm replying to client#%d's ping. Pong! (re: %s", i, rec_from_client->body);
|
---|
291 | send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port);
|
---|
292 | log_it(debug, rec_to_client.body);
|
---|
293 | }
|
---|
294 | return(0);
|
---|
295 | }
|
---|
296 |
|
---|
297 |
|
---|
298 |
|
---|
299 | void interact_with_sysadm()
|
---|
300 | /*
|
---|
301 | Purpose:Tell sysadm about users logged in, etc. in
|
---|
302 | response to keypresses (1=users, ENTER=exit)
|
---|
303 | Params: none
|
---|
304 | Return: none
|
---|
305 | NB: Called by main()
|
---|
306 | */
|
---|
307 | {
|
---|
308 | char tmp[MAX_STR_LEN];
|
---|
309 | int i;
|
---|
310 | bool done;
|
---|
311 |
|
---|
312 | for(done=false; !done; )
|
---|
313 | {
|
---|
314 | printf("Type 1 to list clients\n");
|
---|
315 | printf("Type 2 to backup a client\n");
|
---|
316 | printf("Type 3 to restore a client\n");
|
---|
317 | printf("Type ENTER to quit.\n");
|
---|
318 | fgets(tmp, sizeof(tmp), stdin);
|
---|
319 | if (!strcmp(tmp, "1\n"))
|
---|
320 | {
|
---|
321 | printf("g_clientlist.items is %d\n", g_clientlist.items);
|
---|
322 | printf("List of %d clients:-\n", g_clientlist.items);
|
---|
323 | printf("\tClient# Port# IP address Client name\n");
|
---|
324 | for(i=0; i<g_clientlist.items; i++)
|
---|
325 | {
|
---|
326 | printf("\t%d\t%4d %-16s %-20s \n", i, g_clientlist.el[i].port, g_clientlist.el[i].ipaddr, g_clientlist.el[i].hostname_pretty);
|
---|
327 | }
|
---|
328 | printf("<End of list>\n\n");
|
---|
329 | }
|
---|
330 | else if (!strcmp(tmp, "2\n"))
|
---|
331 | {
|
---|
332 | if (g_clientlist.items!=1) { printf("Forget it\n"); }
|
---|
333 | else
|
---|
334 | {
|
---|
335 | backup_client(0, "/usr/local");
|
---|
336 | }
|
---|
337 | }
|
---|
338 | else if (!strcmp(tmp, "3\n"))
|
---|
339 | {
|
---|
340 | if (g_clientlist.items!=1) { printf("Forget it\n"); }
|
---|
341 | else
|
---|
342 | {
|
---|
343 | restore_client(0, "/usr/local");
|
---|
344 | }
|
---|
345 | }
|
---|
346 | else if (!strcmp(tmp, "\n"))
|
---|
347 | {
|
---|
348 | if (g_clientlist.items > 0)
|
---|
349 | {
|
---|
350 | printf("There are %d users logged in. Are you sure you want to quit? ", g_clientlist.items);
|
---|
351 | fgets(tmp, sizeof(tmp), stdin);
|
---|
352 | if (tmp[0]=='Y' || tmp[0]=='y')
|
---|
353 | { done=true; }
|
---|
354 | }
|
---|
355 | else
|
---|
356 | { done=true; }
|
---|
357 | if (done)
|
---|
358 | { log_it(info, "OK, you've chosen to shutdown server."); }
|
---|
359 | else
|
---|
360 | { log_it(info, "Shutdown canceled."); }
|
---|
361 | }
|
---|
362 | }
|
---|
363 | }
|
---|
364 |
|
---|
365 |
|
---|
366 |
|
---|
367 | void log_it(t_loglevel level, char *sz_message)
|
---|
368 | {
|
---|
369 | char sz_outstr[MAX_STR_LEN], sz_level[MAX_STR_LEN], sz_time[MAX_STR_LEN];
|
---|
370 | time_t time_rec;
|
---|
371 |
|
---|
372 | time(&time_rec);
|
---|
373 | switch(level)
|
---|
374 | {
|
---|
375 | case debug: strcpy(sz_level, "DEBUG"); break;
|
---|
376 | case info: strcpy(sz_level, "INFO "); break;
|
---|
377 | case warn: strcpy(sz_level, "WARN "); break;
|
---|
378 | case error: strcpy(sz_level, "ERROR"); break;
|
---|
379 | case fatal: strcpy(sz_level, "FATAL"); break;
|
---|
380 | default: strcpy(sz_level, "UNKWN"); break;
|
---|
381 | }
|
---|
382 | sprintf(sz_time, ctime(&time_rec));
|
---|
383 | sz_time[strlen(sz_time)-6] = '\0';
|
---|
384 | sprintf(sz_outstr, "%s %s: %s", sz_time+11, sz_level, sz_message);
|
---|
385 | if ((int)level >= LOG_THESE_AND_HIGHER)
|
---|
386 | {
|
---|
387 | fprintf(stderr, "%s\n",sz_outstr);
|
---|
388 | }
|
---|
389 | if (level==fatal) { fprintf(stderr,"Aborting now."); exit(1); }
|
---|
390 | }
|
---|
391 |
|
---|
392 |
|
---|
393 |
|
---|
394 |
|
---|
395 | int restore_client(int clientno, char*path)
|
---|
396 | {
|
---|
397 | }
|
---|
398 |
|
---|
399 |
|
---|
400 | int send_msg_to_client(struct s_server2client_msg_record *rec, char *clientIP, int port)
|
---|
401 | /*
|
---|
402 | Purpose:Send a message from server to client.
|
---|
403 | A 'message' could be a response to a login/logout/ping
|
---|
404 | request or perhaps a 'trigger'. (A trigger is a message
|
---|
405 | from server to client intended to initiate a backup
|
---|
406 | or similar activity.)
|
---|
407 | Params: rec - record containing the data to be sent to client
|
---|
408 | clientIP - the xxx.yyy.zzz.aaa IP address of client
|
---|
409 | port - the client's port to send data to
|
---|
410 | Return: result (0=success, nonzero=failure)
|
---|
411 | */
|
---|
412 | {
|
---|
413 | struct hostent *hp;
|
---|
414 | struct sockaddr_in sin;
|
---|
415 | int s;
|
---|
416 | char tmp[MAX_STR_LEN];
|
---|
417 |
|
---|
418 | if ((hp = gethostbyname(clientIP)) == NULL)
|
---|
419 | {
|
---|
420 | sprintf(tmp, "send_msg_to_client: %s: unknown host\n", clientIP);
|
---|
421 | log_it(error, tmp);
|
---|
422 | return(1);
|
---|
423 | }
|
---|
424 | memset((void*)&sin, 0, sizeof(sin));
|
---|
425 | memcpy((void*)&sin.sin_addr, hp->h_addr, hp->h_length);
|
---|
426 | sin.sin_family = AF_INET;
|
---|
427 | sin.sin_addr.s_addr = INADDR_ANY;
|
---|
428 | sin.sin_port = htons(port);
|
---|
429 | if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
---|
430 | { perror("socket"); log_it(error, "send_msg_to_client: SOCKET error"); return(1); }
|
---|
431 | if (connect(s, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) < 0)
|
---|
432 | { sprintf(tmp, "Failed to connect to client %s on port %d", clientIP, port); log_it(error, tmp); return(1); }
|
---|
433 | send(s, (char*)rec, sizeof(struct s_server2client_msg_record), 0);
|
---|
434 | close(s);
|
---|
435 | sprintf(tmp, "Sent %s msg to %s (port %d)", tmsg_to_string(rec->msg_type), clientIP, port);
|
---|
436 | log_it(debug, tmp);
|
---|
437 | return(0);
|
---|
438 | }
|
---|
439 |
|
---|
440 |
|
---|
441 |
|
---|
442 | void start_threads_to_watch_ports_for_requests()
|
---|
443 | /*
|
---|
444 | Purpose:Start the threads that watch the 'incoming' ports
|
---|
445 | for messages from clients.
|
---|
446 | Params: none
|
---|
447 | Return: none
|
---|
448 | NB: Called by main()
|
---|
449 | */
|
---|
450 | {
|
---|
451 | int i, port, res;
|
---|
452 | pthread_t threadinfo[NOOF_THREADS];
|
---|
453 | char tmp[MAX_STR_LEN];
|
---|
454 |
|
---|
455 | g_clientlist.items = 0;
|
---|
456 | for(i=0; i<NOOF_THREADS; i++)
|
---|
457 | {
|
---|
458 | port = 8700+i;
|
---|
459 | sprintf(tmp,"%d", port);
|
---|
460 | res = pthread_create(&(threadinfo[i]), NULL, watch_port_for_requests_from_clients, (void*)tmp);
|
---|
461 | if (res != 0)
|
---|
462 | {
|
---|
463 | perror("Thread creation failed");
|
---|
464 | }
|
---|
465 | usleep(80000);
|
---|
466 | }
|
---|
467 | sprintf(tmp, "Threads are now running.");
|
---|
468 | log_it(info, tmp);
|
---|
469 | }
|
---|
470 |
|
---|
471 |
|
---|
472 |
|
---|
473 | char *tmsg_to_string(t_msg msg_type)
|
---|
474 | /*
|
---|
475 | Purpose:Return a string/name of the msg of type msg_type
|
---|
476 | Params: msg_type - type of message (enum typedef)
|
---|
477 | Return: pointer to static string {name of msg)
|
---|
478 | */
|
---|
479 | {
|
---|
480 | static char sz_msg[MAX_STR_LEN];
|
---|
481 | switch(msg_type)
|
---|
482 | {
|
---|
483 | case unused : strcpy(sz_msg, "unused"); break;
|
---|
484 | case login : strcpy(sz_msg, "login"); break;
|
---|
485 | case logout : strcpy(sz_msg, "logout"); break;
|
---|
486 | case login_ok:strcpy(sz_msg, "login_ok"); break;
|
---|
487 | case logout_ok:strcpy(sz_msg, "logout_ok"); break;
|
---|
488 | case ping : strcpy(sz_msg, "ping"); break;
|
---|
489 | case pong : strcpy(sz_msg, "pong"); break;
|
---|
490 | case fail : strcpy(sz_msg, "fail"); break;
|
---|
491 | case trigger_backup: strcpy(sz_msg, "trigger_backup"); break;
|
---|
492 | case trigger_restore: strcpy(sz_msg, "trigger_restore"); break;
|
---|
493 | case begin_stream: strcpy(sz_msg, "begin_stream"); break;
|
---|
494 | case end_stream: strcpy(sz_msg, "end_stream"); break;
|
---|
495 | default: strcpy(sz_msg, "(Fix tmsg_to_string please)"); break;
|
---|
496 | }
|
---|
497 | return(sz_msg);
|
---|
498 | }
|
---|
499 |
|
---|
500 |
|
---|
501 |
|
---|
502 | void* watch_port_for_requests_from_clients(void*sz_watchport)
|
---|
503 | /*
|
---|
504 | Purpose:Watch a port for incoming messages from clients.
|
---|
505 | A 'message' could be a request to login/logout or
|
---|
506 | a ping, or perhaps a request to backup/restore data.
|
---|
507 | Params: sz_watchport - the port to watch for incoming messages
|
---|
508 | from clients
|
---|
509 | Return: result (0=success, nonzero=failure)
|
---|
510 | NB: Function will return nonzero if error occurs during
|
---|
511 | setup but will otherwise run forever, or until killed.
|
---|
512 | */
|
---|
513 | {
|
---|
514 | int watch_port;
|
---|
515 | struct sockaddr_in sin;
|
---|
516 | char buf[MAX_STR_LEN+1], tmp[MAX_STR_LEN];
|
---|
517 | int len, s, new_s;
|
---|
518 | struct s_client2server_msg_record rec;
|
---|
519 |
|
---|
520 | watch_port = atoi((char*)sz_watchport);
|
---|
521 | sprintf(tmp, "watch_port_for_requests_from_clients(%d) - starting", watch_port);
|
---|
522 | log_it(debug, tmp);
|
---|
523 | memset((void*)&sin, 0, sizeof(sin));
|
---|
524 | sin.sin_family = AF_INET;
|
---|
525 | sin.sin_addr.s_addr = INADDR_ANY;
|
---|
526 | sin.sin_port = htons(watch_port);
|
---|
527 | if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
---|
528 | {
|
---|
529 | sprintf(tmp, "Unable to open socket on port #%d", watch_port);
|
---|
530 | log_it(error, tmp);
|
---|
531 | return((void*)-1);
|
---|
532 | }
|
---|
533 | if (bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
---|
534 | {
|
---|
535 | sprintf(tmp, "Cannot bind %d - %s\n", watch_port, strerror(errno));
|
---|
536 | log_it(error, tmp);
|
---|
537 | return((void*)-1);
|
---|
538 | }
|
---|
539 | if (listen(s, MAX_PENDING) < 0)
|
---|
540 | {
|
---|
541 | sprintf(tmp, "Cannot setup listen (%d) - %s\n", watch_port, strerror(errno));
|
---|
542 | log_it(error, tmp);
|
---|
543 | return((void*)-1);
|
---|
544 | }
|
---|
545 | /* service incoming connections */
|
---|
546 | sprintf(tmp, "Opened socket on port #%d OK", watch_port);
|
---|
547 | log_it(info, tmp);
|
---|
548 | while(true)
|
---|
549 | {
|
---|
550 | len = sizeof(sin);
|
---|
551 | if ((new_s = accept(s, (struct sockaddr *)&sin, (unsigned int*)&len)) < 0)
|
---|
552 | {
|
---|
553 | sleep(1);
|
---|
554 | continue;
|
---|
555 | }
|
---|
556 | while ((len = recv(new_s, buf, sizeof(buf), 0)) > 0)
|
---|
557 | {
|
---|
558 | if (len > MAX_STR_LEN) { len = MAX_STR_LEN; }
|
---|
559 | buf[len] = '\0';
|
---|
560 | memcpy((char*)&rec, buf, sizeof(rec));
|
---|
561 | handle_incoming_message(new_s, &sin, &rec);
|
---|
562 | }
|
---|
563 | close(new_s);
|
---|
564 | }
|
---|
565 | return(NULL);
|
---|
566 | }
|
---|
567 |
|
---|
568 |
|
---|
569 |
|
---|
570 | int main(int argc, char*argv[])
|
---|
571 | /*
|
---|
572 | Purpose: main subroutine
|
---|
573 | Parameters: none
|
---|
574 | Return: result (0=success, nonzero=failure)
|
---|
575 | */
|
---|
576 | {
|
---|
577 | char tmp[MAX_STR_LEN];
|
---|
578 |
|
---|
579 | /* FIXME - add Ctrl-C / sigterm trapping */
|
---|
580 |
|
---|
581 | start_threads_to_watch_ports_for_requests();
|
---|
582 | interact_with_sysadm(); /* report on users logged in, etc.; return after a while... */
|
---|
583 | if (g_clientlist.items != 0)
|
---|
584 | { fprintf(stderr, "Ruh-roh! Some users are still logged in. Oh well...\n"); }
|
---|
585 | /* FIXME - force clients to log off */
|
---|
586 | /* FIXME - send signal to threads, telling them to terminate */
|
---|
587 | sprintf(tmp, "Done. Server is exiting now.");
|
---|
588 | log_it(info, tmp);
|
---|
589 | return(0);
|
---|
590 | }
|
---|
591 | /* end main() */
|
---|
592 |
|
---|
593 |
|
---|