Changeset 352 in MondoRescue for branches/stable/monitas/server.c
- Timestamp:
- Jan 28, 2006, 6:41:40 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/monitas/server.c
r351 r352 3 3 4 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' 5 06/19 6 - fixed bugs in mondoarchive compare code 7 8 06/16 9 - every 15 seconds, update /var/spool/monitas/server-status.txt file 10 - added handle_progress_rpt() 11 - modify restore_path() to allow user to restore to another path 12 13 06/14 14 - added "2> /dev/null" to call to find /var/spool/monitas 15 - improved backup_client(), compare_client(), restore_client() 16 - pipe logs to logfile, not stdout 17 18 06/11 19 - moved register_pid(), set_signals(), termination_in_progress() to common.c 20 - commented code a bit 21 - improved backup_client(), compare_client(), restore_client() 22 23 06/10 24 - improved backup_client() 25 - discover whether mondoarchive returned error (ask client) 26 and act accordingly (i.e. drop archive) 27 28 06/09 29 - added /var/spool/monitas/input.dev FIFO to 30 let external programs instruct me to backup 31 or restore a given computer 32 - added signal trapping 33 34 06/07 35 - rename transmit_file... and move 36 to common.c, as transmit_file_to_socket() 37 - rename receive_file... and move to 38 common.c, as receive_file_from_socket() 39 40 05/27 41 - save bkps to /var/spool/monitas/123.456.789.012/[time] 42 43 05/23 44 - added elementary saving/storing of incoming data 45 from client backing itself up 46 47 05/21 48 - added backup_client, compare_client, restore_client 49 templates for triggers 17 50 18 51 05/11 … … 37 70 38 71 72 /*-----------------------------------------------------------*/ 73 74 75 39 76 #include "structs.h" 40 41 #define LOG_THESE_AND_HIGHER debug /* debug, info, warn, error, fatal */ 77 //#define LOG_THESE_AND_HIGHER debug 78 79 80 42 81 #define NOOF_THREADS 10 43 82 #define LOGFILE "/var/log/monitas-server.log" 83 #define log_it(x,y) { log_it_SUB(g_logfile,x,y); } 84 85 86 /* externs */ 87 88 extern bool does_file_exist(char*); 89 extern char *call_program_and_get_last_line_of_output(char*); 90 extern int call_program_and_log_output(char*); 91 extern int create_and_watch_fifo_for_commands(char*); 92 extern bool does_file_exist(char*); 93 extern void log_it_SUB(char*, t_loglevel, char *); 94 extern int make_hole_for_file (char *); 95 extern int read_block_from_fd(int socket_fd, char*buf, int len_to_read); 96 extern int receive_file_from_socket(FILE*, int); 97 extern void register_pid(pid_t, char*); 98 extern void set_signals(bool); 99 extern void termination_in_progress(int); 100 extern char *tmsg_to_string(t_msg); 101 extern int transmit_file_to_socket(FILE*,int); 44 102 45 103 … … 48 106 49 107 struct s_clientlist g_clientlist; /* FIXME - lock during login/logout, using mutexes */ 50 108 char g_command_fifo[MAX_STR_LEN+1]; // Device which server will monitor for incoming commands 109 pthread_t g_threadinfo[NOOF_THREADS]; // One thread per port, to watch for requests from clients 110 char g_logfile[MAX_STR_LEN+1] = "/var/log/monitas-server.log"; 111 char g_server_status_file[MAX_STR_LEN+1]; 51 112 52 113 … … 54 115 /* prototypes */ 55 116 56 int backup_client(int,char*); 117 int backup_client(char*, int, char*); 118 int compare_client(char*, int, char*); 57 119 int find_client_in_clientlist(char *); 120 int forcibly_logout_all_clients(void); 121 int forcibly_logout_client(int); 122 void* generate_server_status_file_regularly(void*); 58 123 int handle_incoming_message(int, struct sockaddr_in *, struct s_client2server_msg_record *); 59 124 int handle_login_request(int, struct s_client2server_msg_record *, char *); 60 125 int handle_logout_request(int, struct s_client2server_msg_record *, char *); 61 126 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); 127 int handle_progress_rpt(int, struct s_client2server_msg_record *, char *); 128 int handle_user_request(int, struct s_client2server_msg_record *, char *); 129 int process_incoming_command(char*); 130 int read_block_from_fd(int, char*, int); 131 int restore_client(char*, int, char*, char*); 132 int send_msg_to_client(struct s_server2client_msg_record *, char *, int, int*); 65 133 void start_threads_to_watch_ports_for_requests(void); 66 void interact_with_sysadm(void);134 void terminate_daemon(int); 67 135 char *tmsg_to_string(t_msg); 68 136 void* watch_port_for_requests_from_clients(void*); … … 70 138 71 139 72 /* subroutines */ 73 74 int backup_client(int clientno, char*path) 140 /*-----------------------------------------------------------*/ 141 142 143 144 int backup_client(char*ipaddr, int port, char*clientpath) 75 145 /* 76 146 Purpose:Backup the path of a specific client. Receive 77 147 the archives. Store them locally (on me, the server). 78 148 Params: clientno - client# in g_clientlist[] 79 149 clientpath - client's path to be backed up 80 150 Return: result (0=success, nonzero=failure) 81 151 */ 82 152 { 83 153 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); 154 int res=0, socket_fd, noof_archives, i, len; 155 char tmp[MAX_STR_LEN+1], outfile[MAX_STR_LEN+1]; 156 FILE*fout; 157 158 sprintf(tmp, "%s - backup of %s commencing", ipaddr, clientpath); 159 log_it(info, tmp); 160 sprintf(outfile, "/var/spool/monitas/%s/%s.dat", ipaddr, call_program_and_get_last_line_of_output("date +%s")); 161 if (does_file_exist(outfile)) { log_it(error, "Backup storage location exists already. That should be impossible."); return(1); } 162 if (make_hole_for_file(outfile)) 163 { res++; log_it(error, "Cannot write archive to spool dir"); } 164 else if (!(fout=fopen(outfile, "w"))) 165 { res++; log_it(fatal, "Failed to openout temp data file"); } 166 else 167 { 168 sprintf(tmp, "Backing up %s - archive=%s", ipaddr, outfile); 169 log_it(debug, tmp); 170 rec_to_client.msg_type = trigger_backup; 171 strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); 172 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 173 { log_it(error, "backup_client - failed to send msg to client"); return(1); } 174 res += receive_file_from_socket(fout, socket_fd); 175 len=read(socket_fd, (char*)&i, sizeof(i)); 176 if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondoarchive"); } 177 else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondoarchive"); } 178 else if (i) { res++; log_it(error, "Client said, mondoarchive returned an error."); } 179 else { log_it(debug, "Client said, mondoarchive returned OK"); } 180 fclose(fout); 181 close(socket_fd); 182 } 183 /* Shuffle older backups off the mortal coil. Leave maximum of 4 backup files in /var/spool/monitas/[ipaddr] */ 184 sprintf(tmp, "find /var/spool/monitas/%s -type f 2> /dev/null | grep -n \"\" | tail -n1 | cut -d':' -f1", ipaddr); 185 noof_archives = atoi(call_program_and_get_last_line_of_output(tmp)); 186 i = noof_archives - 3; 187 if (i>0) 188 { 189 sprintf(tmp, "rm -f `find /var/spool/monitas/%s -type f | sort | head -n%d`", ipaddr, i); 190 call_program_and_log_output(tmp); 191 } 192 /* Return success/failure value */ 193 if (res>0) 194 { 195 sprintf(tmp, "%s - error(s) occurred while backing up %s", ipaddr, clientpath); 196 log_it(error, tmp); 197 rec_to_client.msg_type = backup_fail; 198 sprintf(rec_to_client.body, "Failed to backup %s", clientpath); 199 log_it(debug, rec_to_client.body); 200 unlink(outfile); 201 } 202 else 203 { 204 sprintf(tmp, "%s - backed up %s ok", ipaddr, clientpath); 205 log_it(info, tmp); 206 rec_to_client.msg_type = backup_ok; 207 sprintf(rec_to_client.body, "%s - backed up ok", clientpath); 208 log_it(debug, rec_to_client.body); 209 } 210 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 211 { 212 res++; 213 sprintf(tmp, "Unable to notify %s of backup success/failure", ipaddr); 214 log_it(error, tmp); 215 i = find_client_in_clientlist(ipaddr); 216 if (i>=0) { forcibly_logout_client(i); } 217 log_it(info, "I'm assuming the backup was bad because the client cannot be reached."); 218 unlink(outfile); 219 } 220 return(res); 221 } 222 223 224 225 /*-----------------------------------------------------------*/ 226 227 228 229 int compare_client(char*ipaddr, int port, char*clientpath) 230 /* 231 Purpose:Compare the path of a specific client. Transmit 232 the archives from my (the server's) local storage loc. 233 Params: clientno - client# in g_clientlist[] 234 clientpath - client's path to be compared 235 Return: result (0=success, nonzero=failure) 236 */ 237 { 238 struct s_server2client_msg_record rec_to_client; 239 int res=0, socket_fd, len, i; 240 char tmp[MAX_STR_LEN+1], infile[MAX_STR_LEN+1]; 241 FILE*fin; 242 243 sprintf(tmp, "%s - comparison of %s commencing", ipaddr, clientpath); 244 log_it(info, tmp); 245 // FIXME - don't assume the latest backup contains the files we want ;) 246 sprintf(tmp, "find /var/spool/monitas/%s -type f | sort | tail -n1", ipaddr); 247 strcpy(infile, call_program_and_get_last_line_of_output(tmp)); 248 sprintf(tmp, "Comparing to data file '%s'", infile); 88 249 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); 250 if (!does_file_exist(infile)) { log_it(error, "Backup not found. That should be impossible."); return(1); } 251 sprintf(tmp, "Comparing %s - archive=%s", ipaddr, infile); 252 log_it(debug, tmp); 253 rec_to_client.msg_type = trigger_compare; 254 strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); 255 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 256 { log_it(error, "compare_client - failed to send msg to client"); return(1); } 257 if (!(fin=fopen(infile, "r"))) 258 { log_it(fatal, "Failed to openin temp data file"); } 259 res += transmit_file_to_socket(fin, socket_fd); 260 len=read(socket_fd, (char*)&i, sizeof(i)); 261 if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondoarchive"); } 262 else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondoarchive"); } 263 else if (i) { res++; log_it(error, "Client said, mondoarchive returned an error."); } 264 else { log_it(debug, "Client said, mondoarchive returned OK"); } 265 fclose(fin); 266 close(socket_fd); 267 if (res>0) 268 { 269 sprintf(tmp, "%s - error(s) occurred while comparing %s", ipaddr, clientpath); 270 log_it(error, tmp); 271 rec_to_client.msg_type = compare_fail; 272 sprintf(rec_to_client.body, "Failed to compare %s", clientpath); 273 log_it(debug, rec_to_client.body); 103 274 } 104 275 else 105 276 { 106 sprintf(tmp, "Backed up %s OK", g_clientlist.el[clientno].ipaddr); 107 log_it(error, tmp); 108 return(0); 109 } 110 } 277 sprintf(tmp, "%s - compared %s ok", ipaddr, clientpath); 278 log_it(info, tmp); 279 rec_to_client.msg_type = compare_ok; 280 sprintf(rec_to_client.body, "%s - compared ok", clientpath); 281 log_it(debug, rec_to_client.body); 282 } 283 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 284 { 285 sprintf(tmp, "Unable to notify %s of compare success/failure", ipaddr); 286 log_it(error, tmp); 287 i = find_client_in_clientlist(ipaddr); 288 if (i>=0) { forcibly_logout_client(i); } 289 } 290 return(res); 291 } 292 293 294 295 /*-----------------------------------------------------------*/ 296 111 297 112 298 … … 121 307 { 122 308 int i; 123 char tmp[MAX_STR_LEN ];309 char tmp[MAX_STR_LEN+1]; 124 310 125 311 for(i = 0; i < g_clientlist.items; i++) … … 132 318 return(-1); 133 319 } 320 321 322 323 /*-----------------------------------------------------------*/ 324 325 326 327 int forcibly_logout_all_clients() 328 /* 329 Purpose: Tell all clients to disconnect, right now. 330 Params: None 331 Returns: 0=success 332 */ 333 { 334 // FIXME - lock g_clientlist for duration of this function 335 while(g_clientlist.items>0) 336 { 337 forcibly_logout_client(0); 338 } 339 return(0); 340 } 341 342 343 344 /*-----------------------------------------------------------*/ 345 346 347 348 int forcibly_logout_client(int clientno) 349 /* 350 Purpose: Logout specific client(#) by force. 351 Params: Client# in g_clientlist[] array. 352 Returns: 0=success, nonzero=failure to get other end to hear me;) 353 NB: The client was definitely removed from our login table. 354 If the client got the message, return 0; else, nonzero. 355 */ 356 { 357 struct s_server2client_msg_record rec_to_client; 358 char tmp[MAX_STR_LEN+1]; 359 int res=0; 360 361 sprintf(tmp, "Forcibly logging %s out", g_clientlist.el[clientno].ipaddr); 362 log_it(info, tmp); 363 rec_to_client.msg_type = logout_ok; /* to confirm logout */ 364 strcpy(rec_to_client.body, "Server is shutting down. You are forced to logout"); 365 res=send_msg_to_client(&rec_to_client, g_clientlist.el[clientno].ipaddr, g_clientlist.el[clientno].port, NULL); 366 if (--g_clientlist.items > 0) 367 { 368 sprintf(tmp, "Moving clientlist[%d] to clientlist[%d]", clientno, g_clientlist.items); 369 log_it(debug, tmp); 370 sprintf(tmp, "Was ipaddr=%s; now is ipaddr=", g_clientlist.el[clientno].ipaddr); 371 memcpy((void*)&g_clientlist.el[clientno], (void*)&g_clientlist.el[g_clientlist.items], sizeof(struct s_registered_client_record)); 372 strcat(tmp, g_clientlist.el[clientno].ipaddr); 373 log_it(debug, tmp); 374 } 375 return(res); 376 } 377 378 379 380 /*-----------------------------------------------------------*/ 381 382 383 void* generate_server_status_file_regularly(void*inp) 384 { 385 int i; 386 FILE*fout; 387 388 strncpy(g_server_status_file, (char*)inp, MAX_STR_LEN); 389 for(;;) 390 { 391 if ((fout = fopen(g_server_status_file, "w"))) 392 { 393 // FIXME - lock g_clientlist 394 for(i=0; i<g_clientlist.items; i++) 395 { 396 fprintf(fout, "%s [%s] : %s\n", g_clientlist.el[i].ipaddr, g_clientlist.el[i].hostname_pretty, g_clientlist.el[i].last_progress_rpt); 397 } 398 fclose(fout); 399 } 400 sleep(1); 401 } 402 exit(0); 403 } 404 405 406 407 /*-----------------------------------------------------------*/ 134 408 135 409 … … 145 419 */ 146 420 { 147 char clientIP[MAX_STR_LEN], *ptr, tmp[MAX_STR_LEN]; 421 char clientIP[MAX_STR_LEN+1], tmp[MAX_STR_LEN+1]; 422 unsigned char *ptr; 148 423 int res=0; 149 424 … … 152 427 sprintf(clientIP, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); 153 428 sprintf(tmp, "clientIP = %s", clientIP); 429 log_it(debug, tmp); 430 sprintf(tmp, "%s message from %s [%s] (port %d)", tmsg_to_string(rec->msg_type), clientIP, rec->body, rec->port); 154 431 log_it(debug, tmp); 155 432 switch(rec->msg_type) … … 161 438 res=handle_ping_request(skt, rec, clientIP); 162 439 break; 440 case progress_rpt: 441 res=handle_progress_rpt(skt, rec, clientIP); 442 break; 163 443 case logout: 164 444 res=handle_logout_request(skt, rec, clientIP); 165 445 break; 446 case user_req: 447 res=handle_user_request(skt, rec, clientIP); 448 break; 166 449 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); 450 log_it(error, "...How do I handle it?"); 169 451 } 170 452 return(res); 171 453 } 454 455 456 457 /*-----------------------------------------------------------*/ 172 458 173 459 … … 185 471 struct s_server2client_msg_record rec_to_client; 186 472 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); 473 char tmp[MAX_STR_LEN+1]; 474 475 //FIXME - lock g_clientlist[] 191 476 clientno = find_client_in_clientlist(clientIP); 192 477 if (clientno>=0) 193 478 { 194 rec_to_client.msg_type = fail;479 rec_to_client.msg_type = login_fail; 195 480 sprintf(rec_to_client.body, "Sorry, you're already logged in!"); 196 481 sprintf(tmp, "Ignoring login rq from %s: he's already logged in.", clientIP); … … 210 495 strncpy(g_clientlist.el[clientno].ipaddr, clientIP, sizeof(g_clientlist.el[clientno].ipaddr)); 211 496 g_clientlist.el[clientno].port = rec_from_client->port; 497 g_clientlist.el[clientno].busy = false; 212 498 g_clientlist.items ++; 213 499 sprintf(tmp, "Login request from %s ACCEPTED", clientIP); 214 500 log_it(info, tmp); 215 } 216 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port); 501 strcpy(g_clientlist.el[clientno].last_progress_rpt, "Logged in"); 502 } 503 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); 217 504 return(0); 218 505 } 506 507 508 509 /*-----------------------------------------------------------*/ 219 510 220 511 … … 225 516 from client. 226 517 Params: skt - client's port to talk to 227 rec_from_client - log inrq record received from client518 rec_from_client - logout rq record received from client 228 519 clientIP - client's IP address, in string 229 520 Return: result (0=success, nonzero=failure) … … 232 523 struct s_server2client_msg_record rec_to_client; 233 524 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); 525 char tmp[MAX_STR_LEN+1]; 526 238 527 i = find_client_in_clientlist(clientIP); 239 528 if (i<0) … … 241 530 sprintf(rec_to_client.body, "Client is not logged in yet. How can I log him out?"); 242 531 log_it(error, rec_to_client.body); 243 rec_to_client.msg_type = fail; 532 rec_to_client.msg_type = logout_fail; 533 res=1; 534 } 535 else if (g_clientlist.el[i].busy) 536 { 537 sprintf(rec_to_client.body, "Client is working. I shouldn't log him out."); 538 log_it(error, rec_to_client.body); 539 rec_to_client.msg_type = logout_fail; 244 540 res=1; 245 541 } … … 257 553 log_it(info, tmp); 258 554 } 259 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port );555 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); 260 556 return(res); 261 557 } 558 559 560 561 /*-----------------------------------------------------------*/ 262 562 263 563 … … 268 568 from client. 269 569 Params: skt - client's port to talk to 270 rec_from_client - login rqrecord received from client570 rec_from_client - ping record received from client 271 571 clientIP - client's IP address, in string 272 572 Return: result (0=success, nonzero=failure) … … 275 575 struct s_server2client_msg_record rec_to_client; 276 576 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); 577 char tmp[MAX_STR_LEN+1]; 578 281 579 i = find_client_in_clientlist(clientIP); 282 580 if (i < 0) … … 289 587 rec_to_client.msg_type = pong; /* reply to ping */ 290 588 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 );589 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); 292 590 log_it(debug, rec_to_client.body); 293 591 } … … 297 595 298 596 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) 597 /*-----------------------------------------------------------*/ 598 599 600 601 int handle_progress_rpt(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP) 602 /* 603 Purpose:Handle a progress_rpt which has just been received 604 from client. 605 Params: skt - client's port to talk to 606 rec_from_client - user record received from client 607 clientIP - client's IP address, in string 608 Return: result (0=success, nonzero=failure) 609 */ 610 { 611 // struct s_server2client_msg_record rec_to_client; 612 int i, res=0; 613 char tmp[MAX_STR_LEN+1]; 614 615 i = find_client_in_clientlist(clientIP); 616 if (i < 0) 617 { 618 sprintf(tmp, "Hey, %s isn't logged in. I'm not going to deal with his progress_rpt.", clientIP); 619 log_it(error, tmp); 620 res++; 621 } 622 else 623 { 624 strcpy(g_clientlist.el[i].last_progress_rpt, rec_from_client->body); 625 } 626 return(res); 627 } 628 629 630 631 /*-----------------------------------------------------------*/ 632 633 634 635 int handle_user_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP) 636 /* 637 Purpose:Handle a user request which has just been received 638 from client. 639 Params: skt - client's port to talk to 640 rec_from_client - user record received from client 641 clientIP - client's IP address, in string 642 Return: result (0=success, nonzero=failure) 643 */ 644 { 645 // struct s_server2client_msg_record rec_to_client; 646 int i, res=0; 647 char tmp[MAX_STR_LEN+1], command[MAX_STR_LEN+1], first_half[MAX_STR_LEN+1], second_half[MAX_STR_LEN+1], *p; 648 649 i = find_client_in_clientlist(clientIP); 650 if (i < 0) 651 { 652 sprintf(tmp, "Hey, %s isn't logged in. I'm not going to deal with his request.", clientIP); 653 log_it(error, tmp); 654 res++; 655 } 656 else 657 { 658 strcpy(first_half, rec_from_client->body); 659 p = strchr(first_half, ' '); 660 if (!p) { second_half[0]='\0'; } else { strcpy(second_half, p); *p='\0'; } 661 sprintf(command, "echo \"%s %s%s\" > %s", first_half, clientIP, second_half, SERVER_COMDEV); 662 log_it(debug, command); 663 i = system(command); 664 if (i) { res++; log_it(error, "Failed to echo command to FIFO"); } 665 } 666 return(res); 667 } 668 669 670 671 /*-----------------------------------------------------------*/ 672 673 674 675 int process_incoming_command(char*incoming) 676 /* 677 Purpose:Process incoming command, presumably 678 read from FIFO and sent there by sysadm/user. 679 Params: incoming - raw command string itself 680 Return: result (0=success; nonzero=failure) 681 */ 682 { 683 int res=0, port; 684 int clientno; 685 char tmp[MAX_STR_LEN+1]; 686 int pos; 687 char command[MAX_STR_LEN+1], ipaddr[MAX_STR_LEN+1], 688 path[MAX_STR_LEN+1], aux[MAX_STR_LEN+1]; 689 690 // sprintf(tmp, "incoming = '%s'", incoming); 691 // log_it(debug, tmp); 692 pos=0; 693 sscanf(incoming, "%s %s %s", command, ipaddr, path); 694 if (!strcmp(command, "restore")) 695 { sscanf(incoming, "%s %s %s %s", command, ipaddr, path, aux); } 696 else 697 { aux[0] = '\0'; } 698 699 // for(i=0; i<strlen(command); i++) { command[i]=command[i]|0x60; } 700 sprintf(tmp, "cmd=%s ipaddr=%s path=%s", command, ipaddr, path); 701 log_it(debug, tmp); 702 sprintf(tmp, "%s of %s on %s <-- command received", command, path, ipaddr); 703 log_it(info, tmp); 704 if ((clientno = find_client_in_clientlist(ipaddr)) < 0) 349 705 { 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; } 706 sprintf(tmp, "%s not found in clientlist; so, %s failed.", ipaddr, command); 707 log_it(error, tmp); 708 } 709 else if (g_clientlist.el[clientno].busy == true) 710 { 711 sprintf(tmp, "%s is busy; so, %s failed.", ipaddr, command); 712 log_it(error, tmp); 354 713 } 355 714 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) 715 { 716 g_clientlist.el[clientno].busy = true; 717 port = g_clientlist.el[clientno].port; 718 if (!strcmp(command, "backup")) 719 { res = backup_client(ipaddr, port, path); } 720 else if (!strcmp(command, "compare")) 721 { res = compare_client(ipaddr, port, path); } 722 else if (!strcmp(command, "restore")) 723 { res = restore_client(ipaddr, port, path, aux); } 724 else 725 { 726 sprintf(tmp, "%s - cannot '%s'. Command unknown.", ipaddr, command); 727 log_it(error, tmp); 728 res=1; 729 } 730 g_clientlist.el[clientno].busy = false; 731 } 732 return(res); 733 } 734 735 736 737 /*-----------------------------------------------------------*/ 738 739 740 741 int restore_client(char*ipaddr, int port, char*clientpath, char*auxpath) 742 /* 743 Purpose:Restore the path of a specific client. Transmit 744 the archives from my (the server's) local storage loc. 745 Params: clientno - client# in g_clientlist[] 746 clientpath - client's path to be restored 747 Return: result (0=success, nonzero=failure) 748 */ 749 { 750 struct s_server2client_msg_record rec_to_client; 751 int res=0, socket_fd, len, i; 752 char tmp[MAX_STR_LEN+1], infile[MAX_STR_LEN+1]; 753 FILE*fin; 754 755 sprintf(tmp, "%s - restoration of %s commencing", ipaddr, clientpath); 756 log_it(info, tmp); 757 // FIXME - don't assume the latest backup contains the files we want ;) 758 sprintf(tmp, "find /var/spool/monitas/%s -type f | sort | tail -n1", ipaddr); 759 strcpy(infile, call_program_and_get_last_line_of_output(tmp)); 760 sprintf(tmp, "Restoring from data file '%s'", infile); 761 log_it(debug, tmp); 762 if (!does_file_exist(infile)) { log_it(error, "Backup not found. That should be impossible."); return(1); } 763 sprintf(tmp, "Restoring %s - archive=%s", ipaddr, infile); 764 log_it(debug, tmp); 765 rec_to_client.msg_type = trigger_restore; 766 strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); 767 strncpy(rec_to_client.bodyAux, auxpath, sizeof(rec_to_client.bodyAux)); 768 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 769 { log_it(error, "restore_client - failed to send msg to client"); return(1); } 770 if (!(fin=fopen(infile, "r"))) 771 { log_it(fatal, "Failed to openin temp data file"); } 772 res += transmit_file_to_socket(fin, socket_fd); 773 774 len=read(socket_fd, (char*)&i, sizeof(i)); 775 if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondorestore"); } 776 else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondorestore"); } 777 else if (i) { res++; log_it(error, "Client said, mondorestore returned an error."); } 778 else { log_it(debug, "Client said, mondorestore returned OK"); } 779 780 fclose(fin); 781 close(socket_fd); 782 if (res>0) 783 { 784 sprintf(tmp, "%s - error(s) occurred while restoring %s", ipaddr, clientpath); 785 log_it(error, tmp); 786 rec_to_client.msg_type = restore_fail; 787 sprintf(rec_to_client.body, "Failed to restore %s", clientpath); 788 log_it(debug, rec_to_client.body); 789 } 790 else 791 { 792 sprintf(tmp, "%s - restored %s ok", ipaddr, clientpath); 793 log_it(info, tmp); 794 rec_to_client.msg_type = restore_ok; 795 sprintf(rec_to_client.body, "%s - restored ok", clientpath); 796 log_it(debug, rec_to_client.body); 797 } 798 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 799 { 800 sprintf(tmp, "Unable to notify %s of restore success/failure", ipaddr); 801 log_it(error, tmp); 802 i = find_client_in_clientlist(ipaddr); 803 if (i>=0) { forcibly_logout_client(i); } 804 } 805 return(res); 806 } 807 808 809 /*-----------------------------------------------------------*/ 810 811 812 813 int send_msg_to_client(struct s_server2client_msg_record *rec, char *clientIP, int port, int *psocket) 401 814 /* 402 815 Purpose:Send a message from server to client. 403 404 405 406 816 A 'message' could be a response to a login/logout/ping 817 request or perhaps a 'trigger'. (A trigger is a message 818 from server to client intended to initiate a backup 819 or similar activity.) 407 820 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 } 821 clientIP - the xxx.yyy.zzz.aaa IP address of client 822 port - the client's port to send data to 823 psocket - returns the socket's file descriptor, left 824 open by me; or, if psocket==NULL, then socket is closed 825 by me before I return. 826 Return: result (0=success, nonzero=failure) 827 */ 828 { 829 struct hostent *hp; 830 struct sockaddr_in sin; 831 int s; 832 char tmp[MAX_STR_LEN+1]; 833 if ((hp = gethostbyname(clientIP)) == NULL) 834 { 835 sprintf(tmp, "send_msg_to_client: %s: unknown host", clientIP); 836 log_it(error, tmp); 837 return(1); 838 } 839 memset((void*)&sin, 0, sizeof(sin)); 840 memcpy((void*)&sin.sin_addr, hp->h_addr, hp->h_length); 841 sin.sin_family = AF_INET; 842 sin.sin_addr.s_addr = INADDR_ANY; 843 sin.sin_port = htons(port); 844 if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 845 { perror("socket"); log_it(error, "send_msg_to_client: SOCKET error"); return(1); } 846 if (connect(s, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) < 0) 847 { sprintf(tmp, "Failed to connect to client %s on port %d", clientIP, port); log_it(error, tmp); return(1); } 848 send(s, (char*)rec, sizeof(struct s_server2client_msg_record), 0); 849 if (psocket) { *psocket=s; } else { close(s); } 850 sprintf(tmp, "Sent %s msg [%s] to %s (port %d)", tmsg_to_string(rec->msg_type), rec->body, clientIP, port); 851 log_it(debug, tmp); 852 return(0); 853 } 854 855 856 857 /*-----------------------------------------------------------*/ 439 858 440 859 … … 450 869 { 451 870 int i, port, res; 452 pthread_t threadinfo[NOOF_THREADS]; 453 char tmp[MAX_STR_LEN]; 871 char tmp[MAX_STR_LEN+1]; 454 872 455 873 g_clientlist.items = 0; … … 458 876 port = 8700+i; 459 877 sprintf(tmp,"%d", port); 460 res = pthread_create(&( threadinfo[i]), NULL, watch_port_for_requests_from_clients, (void*)tmp);878 res = pthread_create(&(g_threadinfo[i]), NULL, watch_port_for_requests_from_clients, (void*)tmp); 461 879 if (res != 0) 462 880 { 463 881 perror("Thread creation failed"); 464 882 } 465 usleep( 80000);466 } 467 sprintf(tmp, " Threads are now running.");883 usleep(50000); 884 } 885 sprintf(tmp, "Now monitoring ports %d thru %d for requests from clients.", 8700, 8700+NOOF_THREADS-1); 468 886 log_it(info, tmp); 469 887 } … … 471 889 472 890 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 } 891 /*-----------------------------------------------------------*/ 892 893 894 895 void terminate_daemon(int sig) 896 /* 897 Purpose: Shut down the server in response to interrupt. 898 Params: Signal received. 899 Returns: None 900 */ 901 { 902 char command[MAX_STR_LEN+1]; 903 static bool logged_out_everyone=false; 904 905 set_signals(false); // termination in progress 906 log_it(info, "Abort signal caught by interrupt handler"); 907 if (!logged_out_everyone) 908 { 909 // FIXME - lock the var w/mutex 910 logged_out_everyone=true; 911 forcibly_logout_all_clients(); 912 } 913 /* 914 for(i=0; i<NOOF_THREADS; i--) 915 { 916 sprintf(tmp, "Terminating thread #%d", i); 917 log_it(debug, tmp); 918 pthread_join(g_threadinfo[i], NULL); 919 } 920 */ 921 forcibly_logout_all_clients(); 922 sprintf(command, "rm -f %s", g_command_fifo); 923 call_program_and_log_output(command); 924 // chmod(g_command_fifo, 0); 925 unlink(g_command_fifo); 926 unlink(g_server_status_file); 927 register_pid(0, "server"); 928 log_it(info, "---------- Monitas (server) has terminated ----------"); 929 exit(0); 930 } 931 932 933 934 /*-----------------------------------------------------------*/ 499 935 500 936 … … 514 950 int watch_port; 515 951 struct sockaddr_in sin; 516 char buf[MAX_STR_LEN+1], tmp[MAX_STR_LEN ];952 char buf[MAX_STR_LEN+1], tmp[MAX_STR_LEN+1]; 517 953 int len, s, new_s; 518 954 struct s_client2server_msg_record rec; 519 955 520 956 watch_port = atoi((char*)sz_watchport); 521 sprintf(tmp, "watch_port_for_requests_from_clients(%d) - starting", watch_port); 522 log_it(debug, tmp); 957 // sprintf(tmp, "watch_port_for_requests_from_clients(%d) - starting", watch_port); log_it(debug, tmp); 523 958 memset((void*)&sin, 0, sizeof(sin)); 524 959 sin.sin_family = AF_INET; … … 544 979 } 545 980 /* service incoming connections */ 546 sprintf(tmp, " Opened socket onport #%d OK", watch_port);547 log_it( info, tmp);981 sprintf(tmp, "Bound port #%d OK", watch_port); 982 log_it(debug, tmp); 548 983 while(true) 549 984 { … … 568 1003 569 1004 1005 /*-----------------------------------------------------------*/ 1006 1007 1008 570 1009 int main(int argc, char*argv[]) 571 1010 /* … … 575 1014 */ 576 1015 { 577 char tmp[MAX_STR_LEN]; 578 579 /* FIXME - add Ctrl-C / sigterm trapping */ 580 1016 pthread_t server_status_thread; 1017 1018 log_it(info, "---------- Monitas (server) by Hugo Rabson ----------"); 1019 register_pid(getpid(), "server"); 1020 set_signals(true); 581 1021 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); 1022 pthread_create(&server_status_thread, NULL, generate_server_status_file_regularly, (void*)SERVER_STATUS_FILE); 1023 create_and_watch_fifo_for_commands(SERVER_COMDEV); 1024 log_it(warn, "Execution should never reach this point"); 1025 exit(0); 590 1026 } 591 1027 /* end main() */
Note:
See TracChangeset
for help on using the changeset viewer.