modules/sv/server.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. log_print
  2. radix_init
  3. main_loop
  4. SV_start
  5. SV_shutdown
  6. SV_sleep
  7. SV_signal_thread
  8. SV_concurrent_server
  9. SV_do_whois
  10. SV_do_mirror
  11. SV_do_config
  12. SV_watchdog
  13. do_watchdog

   1 /***************************************
   2   $Revision: 1.36 $
   3 
   4   Example code: A server for a client to connect to.
   5 
   6   Status: NOT REVUED, NOT TESTED
   7 
   8  Authors:       Chris Ottrey, Joao Damas
   9 
  10   +html+ <DL COMPACT>
  11   +html+ <DT>Online References:
  12   +html+ <DD><UL>
  13   +html+   <LI>Based on <A HREF="http://iii.ripe.net/dbase/coding/new.code/progress/ottrey/code/java/src/DBServer.java">DBServer.java</A>
  14   +html+ </UL>
  15   +html+ </DL>
  16  
  17   ******************/ /******************
  18   Modification History:
  19         ottrey (02/03/1999) Created.
  20         ottrey (08/03/1999) Modified.
  21         joao   (22/06/1999) Modified.
  22   ******************/ /******************
  23   Copyright (c) 1999                              RIPE NCC
  24  
  25   All Rights Reserved
  26   
  27   Permission to use, copy, modify, and distribute this software and its
  28   documentation for any purpose and without fee is hereby granted,
  29   provided that the above copyright notice appear in all copies and that
  30   both that copyright notice and this permission notice appear in
  31   supporting documentation, and that the name of the author not be
  32   used in advertising or publicity pertaining to distribution of the
  33   software without specific, written prior permission.
  34   
  35   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  36   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  37   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  38   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  39   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  40   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41  ***************************************/
  42 #include <sys/socket.h>
  43 #include <netinet/in.h>
  44 
  45 #include <sys/wait.h>
  46 #include <ctype.h>
  47 
  48 #include <sys/types.h>
  49 #include <sys/stat.h>
  50 
  51 #include "thread.h"
  52 #include "rxroutines.h"
  53 #include "socket.h"
  54 /*
  55 #include "objects.h"
  56 */
  57 #include "constants.h"
  58 
  59 #include "ca_configFns.h"
  60 #include "ca_dictSyms.h"
  61 #include "ca_macros.h"
  62 #include "ca_srcAttribs.h"
  63 
  64 #include "mysql_driver.h"
  65 #include "access_control.h"
  66 #include "ud.h"
  67 #include "server.h"
  68 
  69 #include "rp.h"
  70 #include "memwrap.h"
  71 
  72 #include "ta.h"
  73 
  74 #define RIPE_REG 17
  75 
  76 /*+ String sizes +*/
  77 #define STR_S   63
  78 #define STR_M   255
  79 #define STR_L   1023
  80 #define STR_XL  4095
  81 #define STR_XXL 16383
  82 
  83 
  84 /* Storage for descriptors of the read side of the pipe */
  85 int sv_lockfd[MAX_LOCKS];
  86 
  87 /* Listening sockets */
  88 int SV_whois_sock;
  89 int SV_config_sock;
  90 int SV_mirror_sock;
  91 
  92 /* each updatable source has its own update thread and its own socket */
  93 #define MAX_SOURCES 100
  94 int SV_update_sock[MAX_SOURCES];
  95 
  96 /*+ Mutex lock.  Used for synchronizing changes. +*/
  97 pthread_mutex_t   Whois_thread_count_lock;
  98 pthread_mutex_t   Config_thread_count_lock;
  99 pthread_mutex_t   Mirror_thread_count_lock;
 100 
 101 /*+ The number of threads. +*/
 102 int       Whois_thread_count;
 103 int       Config_thread_count;
 104 int       Mirror_thread_count;
 105 
 106 
 107 /*+ Server starting time +*/
 108 time_t SV_starttime;
 109 
 110 /* pthread_mutex_t radix_initializing_lock; */
 111 /* XXX this is a workaround of a problem with mysql - it prevents the
 112 update/nrtm threads from starting before the radix tree is loaded.
 113 
 114 Apparently, even LOCK TABLES doesn't prevent the program from locking up 
 115 */
 116 
 117 static void do_watchdog(void *arg);
 118 
 119 /* Logging results */
 120 static void log_print(const char *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 121   FILE *logf;
 122 
 123   if (CO_get_thread_logging() == 1) {
 124     if (strcmp(CO_get_thread_logfile(), "stdout") == 0) {
 125       printf(arg);
 126     }
 127     else {
 128       logf = fopen(CO_get_thread_logfile(), "a");
 129       fprintf(logf, arg);
 130       fclose(logf);
 131     }
 132   }
 133 
 134 } /* log_print() */
 135 
 136 
 137 void radix_init(void){
     /* [<][>][^][v][top][bottom][index][help] */
 138   int i;
 139   ca_dbSource_t *source_hdl;
 140 
 141   wr_log_set(0);
 142   /* this needs to be done in two loops, 
 143      because the trees must be created asap (first loop)
 144      and then locked until they are populated in the second loop
 145   */
 146   
 147   for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){   
 148     dieif( RP_init_trees( source_hdl ) != RP_OK );
 149   }
 150   
 151   for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){   
 152     dieif( RP_sql_load_reg( source_hdl ) != RP_OK ); 
 153   }
 154   
 155 #if 0
 156   {
 157       er_path_t erlogstr;
 158       
 159       erlogstr.fdes = stdout;
 160       erlogstr.asp  = 0xffff0000;
 161       erlogstr.fac  = 0; /* FAC_QI; */
 162       erlogstr.sev  = ER_SEV_D;
 163       erlogstr.mode = ER_M_SEVCHAR | ER_M_FACSYMB | ER_M_TEXTLONG;
 164       
 165       ER_setpath(& erlogstr);  
 166   }
 167 #endif
 168   wr_log_set(0); /* switch on/off the memory leak detector */
 169 /*  pthread_mutex_unlock( &radix_initializing_lock );  */
 170   
 171   pthread_exit((void *)0);
 172 }
 173 
 174 /* main_loop() */
 175 /*++++++++++++++++++++++++++++++++++++++
 176 
 177   Waits for an incoming connection on the and spawns a new thread to handle it.
 178 
 179   void *arg Pointer to a struct containing the socket to talk to the client and
 180             the function to call depending on the incoming connection.
 181 
 182   More:
 183   +html+ <PRE>
 184   Author:
 185         ottrey
 186         joao
 187         andrei (do_server)
 188   +html+ </PRE>
 189   ++++++++++++++++++++++++++++++++++++++*/
 190 static void  *main_loop(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 191   th_args *args = (th_args *)arg;
 192   int connected_socket;
 193   int do_server;
 194 
 195   while(do_server=CO_get_do_server()) {
 196 
 197     connected_socket = SK_accept_connection(args->sock);
 198     if(connected_socket==-1) break;
 199 
 200 
 201     ER_dbg_va(FAC_TH, ASP_TH_NEW, "Starting a new thread");
 202 
 203     /* Start a new thread. */
 204 
 205 
 206     TH_create((void *(*)(void *))(args->function), (void *)connected_socket);
 207 //      
 208 //    pthread_attr_init(&attr);    /* initialize attr with default attributes */
 209 //    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 210 //    pthread_create(&tid, &attr, (void *(*)(void *))(args->function), (void *)connected_socket); 
 211   }
 212 
 213    ER_dbg_va(FAC_TH, ASP_TH_NEW, "Exiting from the main loop");
 214 
 215 } /* main_loop() */
 216 
 217 
 218 /* SV_start() */
 219 /*++++++++++++++++++++++++++++++++++++++
 220 
 221   Start the server.
 222 
 223   More:
 224   +html+ <PRE>
 225   Authors:
 226         ottrey
 227         joao
 228   +html+ </PRE>
 229   +html+ Starts up the server.
 230   +html+ <OL>
 231   +html+   <LI> Create sockets on the necessary ports (whois, config and mirror)
 232   +html+   <LI> Start new threads for each service.
 233   +html+ </OL>
 234   +html+ <A HREF=".DBrc">.properties</A>
 235 
 236   ++++++++++++++++++++++++++++++++++++++*/
 237 void SV_start() {
     /* [<][>][^][v][top][bottom][index][help] */
 238   /* Make listening sockets global variables  */
 239   /*  int whois_sock,config_sock,mirror_sock,update_sock; */
 240   /* uint32_t whois_addr,sock_addr,mirror_addr; */
 241   int whois_port = -1;
 242   int config_port = -1;
 243   int mirror_port = -1; 
 244   int update_port = -1;
 245   int update_mode = 0;
 246   sigset_t sset;
 247   int fdes[2];
 248   struct timeval tval;
 249   ca_dbSource_t *source_hdl;
 250   char *source_name;
 251   int source;
 252 
 253   /* Store the starting time */
 254   gettimeofday(&tval, NULL);
 255   SV_starttime = tval.tv_sec;/* seconds since Jan. 1, 1970 */
 256   
 257   /* Create interrupt pipe */
 258   /* Writing to this pipe will cause sleeping threads */
 259   /* to wake up */
 260   fprintf(stderr, "Creating an interrupt pipe\n");
 261   if(pipe(fdes)==-1) {
 262    printf("Cannot open interrupt pipe\n");
 263    exit(-1);
 264   } 
 265   /* Save the pipe descriptors in sv_lock array */
 266   sv_lockfd[WLOCK_SHTDOWN]=fdes[0];
 267   sv_lockfd[LOCK_SHTDOWN]=fdes[1];
 268 
 269   
 270   /* Initialise the access control list. */
 271   AC_build();
 272   AC_acc_load();
 273   /* explicitly start the decay thread */
 274   TH_create((void *(*)(void *))AC_decay, NULL);
 275 
 276   /* Initialise the radix tree (separate thread[s])
 277      already can allow socket connections, because the trees will 
 278      be created locked, and will be unlocked when loaded */
 279 
 280 /*   pthread_mutex_lock( &radix_initializing_lock );  */
 281   TH_create((void *(*)(void *))radix_init, NULL);
 282 /*  pthread_mutex_lock( &radix_initializing_lock );  */
 283   
 284   
 285   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
 286   /* Get port information for each service */
 287   whois_port = SK_atoport(CO_get_whois_port(), "tcp");
 288   printf("XXX htons(whois_port)=%d\n", htons(whois_port));
 289   if(whois_port == -1) {
 290     printf("Invalid service/port: %d\n", htons(whois_port));
 291     exit(-1);
 292   }
 293 
 294   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
 295   config_port = SK_atoport(CO_get_config_port(), "tcp");
 296   printf("XXX htons(config_port)=%d\n", htons(config_port));
 297   if(config_port == -1) {
 298     printf("Invalid service/port: %d\n", htons(config_port));
 299     exit(-1); 
 300   }
 301   mirror_port = SK_atoport(CO_get_mirror_port(), "tcp");
 302   printf("XXX htons(mirror_port)=%d\n", htons(mirror_port));
 303   if(mirror_port == -1) {
 304     printf("Invalid service/port: %d\n", mirror_port);
 305     exit(-1);
 306   }
 307 
 308   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
 309 /*  update_port = SK_atoport(CO_get_update_port(), "tcp"); */
 310 /*  printf("XXX htons(update_port)=%d\n", htons(update_port)); */
 311 /*  if(update_port == -1) { */
 312 /*    printf("Invalid service/port: %d\n", htons(update_port)); */
 313 /*    exit(-1); */
 314 /*  } */
 315 
 316 
 317 
 318   /* 6. Create a socket on the necessary ports/addresses and bind to them. */
 319   /* whois socket */
 320   SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY);
 321 /* Currently binds to INADDR_ANY. Will need to get specific address */
 322 /*  SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */
 323   /* config interface socket */
 324   SV_config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY);
 325   /* nrt socket */
 326   SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port,INADDR_ANY);
 327   
 328   
 329   
 330   /* update interface socket */
 331   /* we need first to create and bind all of them */
 332   /* so that in case of failure we do not start any */
 333   /* update thread */
 334   for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 335      update_mode = ca_get_srcmode(source_hdl);
 336      if(IS_UPDATE(update_mode)) {
 337        /* update_port = SK_atoport(CO_get_update_port(), "tcp"); */
 338        update_port = htons(ca_get_srcupdateport(source_hdl)); 
 339        printf("XXX htons(update_port)=%d\n", htons(update_port));
 340        /* XXX ask AMRM to change the name of the function */
 341  
 342        SV_update_sock[source] = SK_getsock(SOCK_STREAM, update_port, INADDR_ANY);
 343      }
 344      else SV_update_sock[source] = 0;
 345   }   
 346   SV_update_sock[source+1]=-1; /* end of socket array */
 347    
 348   /* Now.... accept() calls block until they get a connection
 349      so to listen on more than one port we need more
 350      than one thread */
 351 
 352   /* Create master thread for whois threads */
 353    SV_concurrent_server(SV_whois_sock, SV_do_whois);
 354 
 355   /* Create master thread for config threads */
 356    SV_concurrent_server(SV_config_sock, SV_do_config);
 357   /* Create master thread for mirror threads */
 358    SV_concurrent_server(SV_mirror_sock, SV_do_mirror);
 359 
 360 /* Walk through the sources and */
 361 /* run update thread for every source with CANUPD == 'y' */
 362    
 363    for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
 364      update_mode = ca_get_srcmode(source_hdl);
 365      source_name= ca_get_srcname(source_hdl);
 366 
 367      if(IS_UPDATE(update_mode)) { 
 368      /* run RIPupdate thread */
 369        fprintf(stderr,"Source [%s] Mode UPDATE\n", source_name);
 370        TH_create((void *(*)(void *))UD_do_updates, (void *)source); 
 371      }
 372      else {
 373        /* start NRTM client */
 374        fprintf(stderr,"Source [%s] Mode NRTM\n", source_name);    
 375        TH_create((void *(*)(void *))UD_do_nrtm, (void *)source);
 376      }
 377      free(source_name); /* because ca_* functions return copies */   
 378    }    
 379 
 380    
 381 
 382   /* XXX Is this needed? */
 383   pthread_exit(NULL);
 384 
 385 } /* SV_start() */
 386 
 387 /* SV_shutdown() */
 388 /*++++++++++++++++++++++++++++++++++++++
 389 
 390   Shutdown the server.
 391 
 392   More:
 393   +html+ <PRE>
 394   Authors:
 395         andrei
 396   +html+ </PRE>
 397   +html+ Stops the server.
 398   +html+ <OL>
 399   +html+   <LI> Close listening sockets (whois, config, mirror and updates)
 400   +html+   <LI> Stop all threads by triggering do_server variable.
 401   +html+ </OL>
 402   +html+ <A HREF=".DBrc">.properties</A>
 403 
 404   ++++++++++++++++++++++++++++++++++++++*/
 405 void SV_shutdown() {
     /* [<][>][^][v][top][bottom][index][help] */
 406 char print_buf[STR_M];
 407 int source;
 408  
 409  sprintf(print_buf, "%d", 0);
 410  /* Stop updates */
 411  CO_set_const("UD.do_update", print_buf);
 412  /* Stop all servers */
 413  CO_set_const("SV.do_server", print_buf);
 414  sprintf(print_buf, "Stopping all servers\n");
 415  fprintf(stderr, print_buf);
 416  /*log_print(print_buf); */
 417  strcpy(print_buf, "");
 418  
 419  /* Wake up all sleeping threads */
 420  fprintf(stderr, "Going to wake sleeping threads up\n");
 421  write(sv_lockfd[WLOCK_SHTDOWN], " ", 1); 
 422 
 423  /* CLose all listening sockets, so accept call exits */
 424  close(SV_whois_sock);
 425  close(SV_config_sock);
 426  close(SV_mirror_sock);
 427  for (source=0; SV_update_sock[source]!=-1; source++)
 428          if(SV_update_sock[source]!=0)close(SV_update_sock[source]);
 429  
 430  
 431 } /* SV_shutdown() */
 432 
 433 
 434 /* SV_sleep() */
 435 /*++++++++++++++++++++++++++++++++++++++
 436 
 437   Sleep and wake up on special events.
 438 
 439   More:
 440   +html+ <PRE>
 441   Authors:
 442         andrei
 443   +html+ </PRE>
 444   +html+ Sleeps timeout but wakes up when an envent occures.
 445 
 446   ++++++++++++++++++++++++++++++++++++++*/
 447 int SV_sleep(int lock, int sleeptime) {
     /* [<][>][^][v][top][bottom][index][help] */
 448 struct timeval timeout;
 449 struct stat st;
 450 fd_set set;
 451 
 452  if (fstat(sv_lockfd[lock], &st) ==-1) {
 453   fprintf(stderr, "Error stat-ing the lock file\n");
 454   return(-1);
 455  } 
 456  
 457  timeout.tv_sec=sleeptime;
 458  timeout.tv_usec=0;
 459    
 460  FD_ZERO(&set);
 461  FD_SET(sv_lockfd[lock], &set);
 462  
 463  fprintf(stderr, "Going to sleep\n");
 464  select(sv_lockfd[lock]+1, &set, NULL, NULL, &timeout);
 465  
 466  fprintf(stderr, "Select returned\n");
 467       
 468  return(0);
 469 }
 470 
 471 /*++++++++++++++++++++++++++++++++++++++
 472 
 473   Handle signals.
 474   
 475   Changes the flags:
 476         do_nrtm
 477         do_update
 478         do_whoisd
 479 
 480   More:
 481   +html+ <PRE>
 482   Author:
 483         andrei
 484   +html+ </PRE>
 485   ++++++++++++++++++++++++++++++++++++++*/
 486 void *SV_signal_thread() {
     /* [<][>][^][v][top][bottom][index][help] */
 487 char print_buf[STR_M];
 488 sigset_t sset;
 489 int sigReceived;
 490 int do_update;
 491 
 492         sigemptyset(&sset);
 493         sigaddset(&sset, SIGTERM);
 494         sigaddset(&sset, SIGINT);
 495         sigaddset(&sset, SIGUSR1);
 496         /* This is a bit confusing, but is needed */
 497         /* For more information on signal handling in */
 498         /* threads see for example "Multithreading Programming */
 499         /* Techniques" by Shashi Prasad, ISBN 0-07-912250-7, pp. 94-101 */
 500         pthread_sigmask(SIG_BLOCK, &sset, NULL);
 501         /*      fprintf(stderr, "Signal handler installed\n");*/
 502 
 503         for(;;)
 504         {
 505          sigwait(&sset, &sigReceived);
 506          sprintf(print_buf, "Signal received [%d]\n", sigReceived);
 507          log_print(print_buf); strcpy(print_buf, "");
 508          /*      fprintf(stderr, "Signal received [%d]\n", sigReceived); */
 509          switch (sigReceived)
 510          {
 511            case SIGINT:
 512            /* SIGINT stops all servers */
 513                 SV_shutdown();
 514                 pthread_exit((void *)0);
 515                 break;
 516                 
 517            case SIGTERM:
 518            /* SIGTERM will switch the updates on and off */
 519                 do_update=CO_get_do_update();
 520                 if(do_update)do_update=0; else do_update=1;     
 521                 sprintf(print_buf, "%d", do_update);
 522                 CO_set_const("UD.do_update", print_buf); 
 523                 if(do_update)
 524                   sprintf(print_buf, "Starting updates\n");
 525                 else   
 526                   sprintf(print_buf, "Stopping updates\n");
 527                 log_print(print_buf); strcpy(print_buf, ""); 
 528                 /*              fprintf(stderr, "Stopping updates (SIGTERM received)\n"); */
 529                 break; 
 530          }       
 531         }
 532 } /* SV_signal_thread() */
 533 
 534 /* SV_concurrent_server() */
 535 /*++++++++++++++++++++++++++++++++++++++
 536 
 537   This is the routine that creates the main threads. 
 538 
 539   int     sock        The socket to connect to.
 540   void *  do_function The function to call for each type of service
 541 
 542   More:
 543   +html+ <PRE>
 544   Author:
 545         ottrey
 546         joao
 547   +html+ </PRE>
 548   ++++++++++++++++++++++++++++++++++++++*/
 549 void SV_concurrent_server(int sock, void *do_function(void *)) {
     /* [<][>][^][v][top][bottom][index][help] */
 550   th_args *args;
 551   pthread_t tid;
 552   pthread_attr_t attr;
 553 
 554   dieif( wr_calloc((void **)&args,1,sizeof(th_args)) != UT_OK);  
 555 
 556   args->function=(void *)do_function;
 557   args->sock=sock;
 558 
 559 /*  pthread_mutex_init(&Whois_thread_count_lock,NULL); */
 560 
 561   /* Start a new thread. */
 562 
 563   TH_create(main_loop, (void *)args);
 564 
 565   
 566     /* Start a new thread. */
 567 //  pthread_attr_init(&attr);     /* initialize attr with default attributes */
 568 //  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 569 //  pthread_create(&tid, &attr, main_thread, (void *)args);
 570 
 571 } /* TH_run() */
 572 
 573 /* SV_do_whois() */
 574 /*++++++++++++++++++++++++++++++++++++++
 575 
 576   Handle whois connections.
 577 
 578   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
 579 
 580   More:
 581   +html+ <PRE>
 582   Author:
 583         joao
 584   +html+ </PRE>
 585   ++++++++++++++++++++++++++++++++++++++*/
 586 void *SV_do_whois(void *arg) { 
     /* [<][>][^][v][top][bottom][index][help] */
 587   int sock = (int)arg;
 588 
 589   ER_dbg_va(FAC_TH, ASP_TH_NEW,
 590             "Whois: Child thread [%d]: Socket number = %d", 
 591             pthread_self(), sock);
 592 
 593   /* Use a mutex to update the global whois thread counter. */
 594   pthread_mutex_lock(&Whois_thread_count_lock);
 595   Whois_thread_count++;
 596   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 597             "Whois_thread_count++=%d", Whois_thread_count); 
 598   
 599   pthread_mutex_unlock(&Whois_thread_count_lock);
 600 
 601   TA_add(sock, "whois");
 602   PW_interact(sock);
 603   TA_delete();
 604 
 605   /* Use a mutex to update the global whois thread counter. */
 606   pthread_mutex_lock(&Whois_thread_count_lock);
 607   Whois_thread_count--;
 608   ER_dbg_va(FAC_TH, ASP_TH_NEW, 
 609             "Whois_thread_count--=%d", Whois_thread_count); 
 610   pthread_mutex_unlock(&Whois_thread_count_lock);
 611 
 612   pthread_exit((void *)0);
 613 
 614 } /* SV_do_whois() */
 615 
 616 /* SV_do_mirror() */
 617 /*++++++++++++++++++++++++++++++++++++++
 618 
 619   Handle NRTM connections.
 620 
 621   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
 622 
 623   More:
 624   +html+ <PRE>
 625   Author:
 626         joao
 627   +html+ </PRE>
 628   ++++++++++++++++++++++++++++++++++++++*/
 629 void *SV_do_mirror(void *arg) { 
     /* [<][>][^][v][top][bottom][index][help] */
 630   int sock = (int)arg;
 631   char print_buf[STR_M];
 632 
 633   sprintf(print_buf, "NRTM: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
 634 
 635   /* Use a mutex to update the global mirror thread counter. */
 636   pthread_mutex_lock(&Mirror_thread_count_lock);
 637   Mirror_thread_count++;
 638   sprintf(print_buf, "Mirror_thread_count++=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
 639   pthread_mutex_unlock(&Mirror_thread_count_lock);
 640 
 641   TA_add(sock, "mirror");
 642   PM_interact(sock);
 643   TA_delete();
 644 
 645   /* Use a mutex to update the global mirror thread counter. */
 646   pthread_mutex_lock(&Mirror_thread_count_lock);
 647   Mirror_thread_count--;
 648   sprintf(print_buf, "Mirror_thread_count--=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
 649   pthread_mutex_unlock(&Mirror_thread_count_lock);
 650 
 651   pthread_exit((void *)0);
 652 
 653 } /* SV_do_mirror() */
 654 
 655 /* SV_do_config() */
 656 /*++++++++++++++++++++++++++++++++++++++
 657 
 658   Handle config connections.
 659 
 660   void *arg The socket to connect to. (It has to be passed in this way for this
 661 thread routine.)
 662 
 663   More:
 664   +html+ <PRE>
 665   Author:
 666         joao
 667   +html+ </PRE>
 668   ++++++++++++++++++++++++++++++++++++++*/
 669 void *SV_do_config(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 670   int sock = (int)arg;
 671   char print_buf[STR_M];
 672 
 673   sprintf(print_buf, "Config: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
 674 
 675 /*
 676   printf("Hi there, there is nothing to configure yet\nBye..... :-)\n");
 677   fflush(NULL);
 678 
 679   SK_close(sock);
 680 */
 681   TA_add(sock, "config");
 682   PC_interact(sock);
 683   TA_delete();
 684 
 685   pthread_exit((void *)0);
 686 
 687 } /* SV_do_config() */
 688 
 689 
 690 /*++++++++++++++++++++++++++++++++++++++
 691 
 692   This is the routine that creates a watchdog thread. 
 693   
 694   The watchdog will cancel (pthread_cancel()) the calling thread in case the
 695   socket is closed by the client (its read-half is closed). The calling
 696   thread should make necessaruy preparations when calling the watchdog:
 697   
 698   - the socket should be connected
 699   - cancellation points and cleanup routines should be defined
 700   
 701   In case the connection is closed by the calling thread itself, the
 702   watchdog just exits and no action against the calling thread is performed.
 703 
 704   wd_args - a pointer to wd_args_t structure containing
 705             data about socket and thread ID
 706   
 707   More:
 708   +html+ <PRE>
 709   Author:
 710         ottrey
 711         joao
 712         andrei
 713   +html+ </PRE>
 714   ++++++++++++++++++++++++++++++++++++++*/
 715 
 716 void SV_watchdog(wd_args_t *wd_args) {
     /* [<][>][^][v][top][bottom][index][help] */
 717  pthread_t tid;
 718  pthread_attr_t attr;
 719  
 720  /* Start a new thread. */
 721  TH_create((void *(*)(void *))do_watchdog, (void *)wd_args);
 722  
 723 // pthread_attr_init(&attr);     /* initialize attr with default attributes */
 724 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 725 // pthread_create(&tid, &attr, (void *(*)(void *))do_watchdog, (void *)wd_args);
 726 
 727 }
 728 
 729 
 730 /*++++++++++++++++++++++++++++++++++++++
 731 
 732 The watchdog thread itself
 733 
 734 The watchdog thread makes select() on the connected socket waiting until it
 735 becomes readable. If this happens as a result of some input, it'll simply
 736 dump it. Otherwise, this indicates that the client has closed the
 737 connection. In this case watchdog will cancel (pthread_cancel()) the whois
 738 thread (which in its turn will kill (mysql_kill()) mysql thread as part of
 739 its cleanup routine).
 740 
 741 More:
 742 +html+ <PRE>
 743 Author:
 744       andrei
 745 +html+ </PRE>
 746 ++++++++++++++++++++++++++++++++++++++*/
 747 static void do_watchdog(void *arg) {
     /* [<][>][^][v][top][bottom][index][help] */
 748   wd_args_t *wd_args = (wd_args_t *)arg;
 749   int socket;
 750   pthread_t tid;
 751   int nready;
 752   int n;
 753   fd_set rset;
 754   char buff[STR_S];
 755   
 756   socket = wd_args->connected_socket;
 757   tid = wd_args->tid;
 758   
 759   
 760   FD_ZERO(&rset);
 761   FD_SET(socket, &rset);
 762   
 763   while ((nready=select(socket+1, &rset, NULL, NULL, NULL))!=-1) {
 764    
 765    /* There was some input or client half of connection was closed */
 766    /* Check for the latter */
 767    if (( n=read(socket, buff, sizeof(buff))) == 0) {
 768    /* Connection was closed by client */
 769    /* Now send a cancellation request to the whois thread. */
 770    /* mysql thread will be terminated by thread cleanup routine */
 771    
 772    /* The only possible error is ESRCH, so we do not care about */
 773    pthread_cancel(tid);
 774    
 775    /* Exit the watchdog thread, passing NULL as we don't expect pthread_join() */
 776    pthread_exit(NULL);
 777    }
 778    
 779    /* Otherwise dump input and continue */
 780   }
 781   
 782   /* the only reason that we are here is that the socket has been */
 783   /* closed by the whois thread and not valid. Just exit the watchdog, */
 784   /* passing NULL as we don't expect pthread_join() */
 785    pthread_exit(NULL);
 786   
 787 }  

/* [<][>][^][v][top][bottom][index][help] */