## 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.44 $
       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 "sk.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
     122   printf(arg);
     123
     124 } /* log_print() */
     125
     126
     127 void radix_init(void){
         /* [<][>][^][v][top][bottom][index][help] */
     128   int i;
     129   ca_dbSource_t *source_hdl;
     130
     131   wr_log_set(0);
     132   /* this needs to be done in two loops,
     133      because the trees must be created asap (first loop)
     134      and then locked until they are populated in the second loop
     135   */
     136
     137   for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){
     138     dieif( RP_init_trees( source_hdl ) != RP_OK );
     139   }
     140
     141   for(i=0; (source_hdl = ca_get_SourceHandleByPosition(i))!=NULL ; i++){
     142     dieif( RP_sql_load_reg( source_hdl ) != RP_OK );
     143   }
     144
     145   wr_log_set(0); /* switch on/off the memory leak detector */
     146 /*  pthread_mutex_unlock( &radix_initializing_lock );  */
     147
     148   pthread_exit((void *)0);
     149 }
     150
     151 /* main_loop() */
     152 /*++++++++++++++++++++++++++++++++++++++
     153
     154   Waits for an incoming connection on the and spawns a new thread to handle it.
     155
     156   void *arg Pointer to a struct containing the socket to talk to the client and
     157             the function to call depending on the incoming connection.
     158
     159   More:
     160   +html+ <PRE>
     161   Author:
     162         ottrey
     163         joao
     164         andrei (do_server)
     165   +html+ </PRE>
     166   ++++++++++++++++++++++++++++++++++++++*/
     167 static void  *main_loop(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     168   th_args *args = (th_args *)arg;
     169   int connected_socket;
     170   int do_server;
     171
     172   while(do_server=CO_get_do_server()) {
     173
     174     connected_socket = SK_accept_connection(args->sock);
     175     if(connected_socket==-1) break;
     176
     177
     178     ER_dbg_va(FAC_TH, ASP_TH_NEW, "Starting a new thread");
     179
     180     /* Start a new thread. */
     181
     182
     183     TH_create((void *(*)(void *))(args->function), (void *)connected_socket);
     184 //
     185 //    pthread_attr_init(&attr);    /* initialize attr with default attributes */
     186 //    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     187 //    pthread_create(&tid, &attr, (void *(*)(void *))(args->function), (void *)connected_socket);
     188   }
     189
     190    ER_dbg_va(FAC_TH, ASP_TH_NEW, "Exiting from the main loop");
     191
     192 } /* main_loop() */
     193
     194
     195 /* SV_start() */
     196 /*++++++++++++++++++++++++++++++++++++++
     197
     198   Start the server.
     199
     200   More:
     201   +html+ <PRE>
     202   Authors:
     203         ottrey
     204         joao
     205   +html+ </PRE>
     206   +html+ Starts up the server.
     207   +html+ <OL>
     208   +html+   <LI> Create sockets on the necessary ports (whois, config and mirror)
     209   +html+   <LI> Start new threads for each service.
     210   +html+ </OL>
     211   +html+ <A HREF=".DBrc">.properties</A>
     212
     213   ++++++++++++++++++++++++++++++++++++++*/
     214 void SV_start() {
         /* [<][>][^][v][top][bottom][index][help] */
     215   /* Make listening sockets global variables  */
     216   /*  int whois_sock,config_sock,mirror_sock,update_sock; */
     217   /* uint32_t whois_addr,sock_addr,mirror_addr; */
     218   int whois_port = -1;
     219   int config_port = -1;
     220   int mirror_port = -1;
     221   int update_port = -1;
     222   int update_mode = 0;
     223   sigset_t sset;
     224   int fdes[2];
     225   struct timeval tval;
     226   ca_dbSource_t *source_hdl;
     227   char *source_name;
     228   int source;
     229   char *db_host, *db_name, *db_user, *db_passwd;
     230   int db_port;
     231   SQ_connection_t *db_connection;
     232
     233   /* Store the starting time */
     234   gettimeofday(&tval, NULL);
     235   SV_starttime = tval.tv_sec;/* seconds since Jan. 1, 1970 */
     236
     237   /* Create interrupt pipe */
     238   /* Writing to this pipe will cause sleeping threads */
     239   /* to wake up */
     240   fprintf(stderr, "Creating an interrupt pipe\n");
     241   if(pipe(fdes)==-1) {
     242    printf("Cannot open interrupt pipe\n");
     243    exit(-1);
     244   }
     245   /* Save the pipe descriptors in sv_lock array */
     246   sv_lockfd[WLOCK_SHTDOWN]=fdes[0];
     247   sv_lockfd[LOCK_SHTDOWN]=fdes[1];
     248
     249   /* Initialise modules */
     250   SK_init();
     251
     252   /* Initialise the access control list. */
     253   AC_build();
     254   AC_acc_load();
     255   /* explicitly start the decay thread */
     256   TH_create((void *(*)(void *))AC_decay, NULL);
     257
     258
     259
     260   /* Get port information for each service */
     261   whois_port  = htons(ca_get_svwhois_port);
     262   ER_dbg_va(FAC_SV, ASP_SV_PORT, "whois port is %d", ca_get_svwhois_port);
     263
     264   config_port = htons(ca_get_svconfig_port);
     265   ER_dbg_va(FAC_SV, ASP_SV_PORT, "config port is %d", ca_get_svconfig_port);
     266
     267   mirror_port = htons(ca_get_svmirror_port);
     268   ER_dbg_va(FAC_SV, ASP_SV_PORT, "mirror port is %d", ca_get_svmirror_port);
     269
     270
     271   /* 6. Create a socket on the necessary ports/addresses and bind to them. */
     272   /* whois socket */
     273   SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY);
     274 /* Currently binds to INADDR_ANY. Will need to get specific address */
     275 /*  SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */
     276   /* config interface socket */
     277   SV_config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY);
     278   /* nrt socket */
     279   SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port,INADDR_ANY);
     280
     281   /* Check every Database and create sockets */
     282   /* we need first to create and bind all of them */
     283   /* so that in case of failure we do not start any */
     284   /* update thread */
     285   fprintf(stderr, "Check the DB\n");
     286   for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
     287      /* check for crash and recover if needed */
     288      /* make a connection to a database */
     289      db_host = ca_get_srcdbmachine(source_hdl);
     290      db_port = ca_get_srcdbport(source_hdl);
     291      db_name = ca_get_srcdbname(source_hdl);
     292      db_user = ca_get_srcdbuser(source_hdl);
     293      db_passwd = ca_get_srcdbpassword(source_hdl);
     294      db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd);
     295      /* now check TR record */
     296      TR_recover(db_connection);
     297      /* free resources */
     298      SQ_close_connection(db_connection);
     299      free(db_host);
     300      free(db_name);
     301      free(db_user);
     302      free(db_passwd);
     303
     304      update_mode = ca_get_srcmode(source_hdl);
     305      if(IS_UPDATE(update_mode)) {
     306        /* update_port = SK_atoport(CO_get_update_port(), "tcp"); */
     307        update_port = htons(ca_get_srcupdateport(source_hdl));
     308        printf("XXX htons(update_port)=%d\n", htons(update_port));
     309        /* XXX ask AMRM to change the name of the function */
     310
     311        SV_update_sock[source] = SK_getsock(SOCK_STREAM, update_port, INADDR_ANY);
     312      }
     313      else SV_update_sock[source] = 0;
     314   }
     315   SV_update_sock[source+1]=-1; /* end of socket array */
     316
     317    /* Initialise the radix tree (separate thread[s])
     318      already can allow socket connections, because the trees will
     319      be created locked, and will be unlocked when loaded */
     320
     321 /*   pthread_mutex_lock( &radix_initializing_lock );  */
     322   TH_create((void *(*)(void *))radix_init, NULL);
     323 /*  pthread_mutex_lock( &radix_initializing_lock );  */
     324
     325
     326   /* Now.... accept() calls block until they get a connection
     327      so to listen on more than one port we need more
     328      than one thread */
     329
     330   /* Create master thread for whois threads */
     331    SV_concurrent_server(SV_whois_sock, SV_do_whois);
     332
     333   /* Create master thread for config threads */
     334    SV_concurrent_server(SV_config_sock, SV_do_config);
     335   /* Create master thread for mirror threads */
     336    SV_concurrent_server(SV_mirror_sock, SV_do_mirror);
     337
     338 /* Walk through the sources and */
     339 /* run update thread for every source with CANUPD == 'y' */
     340
     341    for(source=0; (source_hdl = ca_get_SourceHandleByPosition(source))!=NULL ; source++){
     342      update_mode = ca_get_srcmode(source_hdl);
     343      source_name= ca_get_srcname(source_hdl);
     344
     345      if(IS_UPDATE(update_mode)) {
     346      /* run RIPupdate thread */
     347        fprintf(stderr,"Source [%s] Mode UPDATE\n", source_name);
     348        TH_create((void *(*)(void *))UD_do_updates, (void *)source);
     349      }
     350      else if(IS_NRTM_CLNT(update_mode)){
     351        /* start NRTM client */
     352        fprintf(stderr,"Source [%s] Mode NRTM\n", source_name);
     353        TH_create((void *(*)(void *))UD_do_nrtm, (void *)source);
     354      }
     355      else fprintf(stderr,"Source [%s] Mode STATIC\n", source_name);
     356      free(source_name); /* because ca_* functions return copies */
     357    }
     358
     359   pthread_exit(NULL);
     360
     361 } /* SV_start() */
     362
     363 /* SV_shutdown() */
     364 /*++++++++++++++++++++++++++++++++++++++
     365
     366   Shutdown the server.
     367
     368   More:
     369   +html+ <PRE>
     370   Authors:
     371         andrei
     372   +html+ </PRE>
     373   +html+ Stops the server.
     374   +html+ <OL>
     375   +html+   <LI> Close listening sockets (whois, config, mirror and updates)
     376   +html+   <LI> Stop all threads by triggering do_server variable.
     377   +html+ </OL>
     378   +html+ <A HREF=".DBrc">.properties</A>
     379
     380   ++++++++++++++++++++++++++++++++++++++*/
     381 void SV_shutdown() {
         /* [<][>][^][v][top][bottom][index][help] */
     382 char print_buf[STR_M];
     383 int source;
     384
     385  sprintf(print_buf, "%d", 0);
     386  /* Stop updates */
     387  CO_set_const("UD.do_update", print_buf);
     388  /* Stop all servers */
     389  CO_set_const("SV.do_server", print_buf);
     390  sprintf(print_buf, "Stopping all servers\n");
     391  fprintf(stderr, print_buf);
     392  /*log_print(print_buf); */
     393  strcpy(print_buf, "");
     394
     395  /* Wake up all sleeping threads */
     396  fprintf(stderr, "Going to wake sleeping threads up\n");
     397  write(sv_lockfd[WLOCK_SHTDOWN], " ", 1);
     398
     399  /* CLose all listening sockets, so accept call exits */
     400  close(SV_whois_sock);
     401  close(SV_config_sock);
     402  close(SV_mirror_sock);
     403  for (source=0; SV_update_sock[source]!=-1; source++)
     404          if(SV_update_sock[source]!=0)close(SV_update_sock[source]);
     405
     406
     407 } /* SV_shutdown() */
     408
     409 /************************************************************
     410 *  int SV_sleep()                                           *
     411 *                                                           *
     412 * sleeps till shutdown request comes                        *
     413 * but at most <delay> seconds                               *
     414 *                                                           *
     415 * Returns:                                                  *
     416 * 1 - timeout                                               *
     417 * 0 - shutdown                                              *
     418 *                                                           *
     419 ************************************************************/
     420
     421 int SV_sleep(int delay)
         /* [<][>][^][v][top][bottom][index][help] */
     422 {
     423  int do_server;
     424  int elapsed_time=0;
     425
     426  while((do_server=CO_get_do_server()) && (elapsed_time<delay))
     427  {
     428   sleep(TIME_SLICE);
     429   elapsed_time+=TIME_SLICE;
     430  }
     431  if(elapsed_time<delay)return(1); else return(0);
     432 }
     433
     434 /*++++++++++++++++++++++++++++++++++++++
     435
     436   Handle signals.
     437
     438   Changes the flags:
     439         do_nrtm
     440         do_update
     441         do_whoisd
     442
     443   More:
     444   +html+ <PRE>
     445   Author:
     446         andrei
     447   +html+ </PRE>
     448   ++++++++++++++++++++++++++++++++++++++*/
     449 void *SV_signal_thread() {
         /* [<][>][^][v][top][bottom][index][help] */
     450 char print_buf[STR_M];
     451 sigset_t sset;
     452 int sigReceived;
     453 int do_update;
     454
     455         sigemptyset(&sset);
     456         sigaddset(&sset, SIGTERM);
     457         sigaddset(&sset, SIGINT);
     458         sigaddset(&sset, SIGUSR1);
     459         /* This is a bit confusing, but is needed */
     460         /* For more information on signal handling in */
     461         /* threads see for example "Multithreading Programming */
     462         /* Techniques" by Shashi Prasad, ISBN 0-07-912250-7, pp. 94-101 */
     463         pthread_sigmask(SIG_BLOCK, &sset, NULL);
     464         /*      fprintf(stderr, "Signal handler installed\n");*/
     465
     466         for(;;)
     467         {
     468          sigwait(&sset, &sigReceived);
     469          sprintf(print_buf, "Signal received [%d]\n", sigReceived);
     470          log_print(print_buf); strcpy(print_buf, "");
     471          /*      fprintf(stderr, "Signal received [%d]\n", sigReceived); */
     472          switch (sigReceived)
     473          {
     474            case SIGINT:
     475            /* SIGINT stops all servers */
     476                 SV_shutdown();
     477                 pthread_exit((void *)0);
     478                 break;
     479
     480            case SIGTERM:
     481            /* SIGTERM will switch the updates on and off */
     482                 do_update=CO_get_do_update();
     483                 if(do_update)do_update=0; else do_update=1;
     484                 sprintf(print_buf, "%d", do_update);
     485                 CO_set_const("UD.do_update", print_buf);
     486                 if(do_update)
     487                   sprintf(print_buf, "Starting updates\n");
     488                 else
     489                   sprintf(print_buf, "Stopping updates\n");
     490                 log_print(print_buf); strcpy(print_buf, "");
     491                 /*              fprintf(stderr, "Stopping updates (SIGTERM received)\n"); */
     492                 break;
     493          }
     494         }
     495 } /* SV_signal_thread() */
     496
     497 /* SV_concurrent_server() */
     498 /*++++++++++++++++++++++++++++++++++++++
     499
     500   This is the routine that creates the main threads.
     501
     502   int     sock        The socket to connect to.
     503   void *  do_function The function to call for each type of service
     504
     505   More:
     506   +html+ <PRE>
     507   Author:
     508         ottrey
     509         joao
     510   +html+ </PRE>
     511   ++++++++++++++++++++++++++++++++++++++*/
     512 void SV_concurrent_server(int sock, void *do_function(void *)) {
         /* [<][>][^][v][top][bottom][index][help] */
     513   th_args *args;
     514   pthread_t tid;
     515   pthread_attr_t attr;
     516
     517   dieif( wr_calloc((void **)&args,1,sizeof(th_args)) != UT_OK);
     518
     519   args->function=(void *)do_function;
     520   args->sock=sock;
     521
     522 /*  pthread_mutex_init(&Whois_thread_count_lock,NULL); */
     523
     524   /* Start a new thread. */
     525
     526   TH_create(main_loop, (void *)args);
     527
     528
     529     /* Start a new thread. */
     530 //  pthread_attr_init(&attr);     /* initialize attr with default attributes */
     531 //  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     532 //  pthread_create(&tid, &attr, main_thread, (void *)args);
     533
     534 } /* TH_run() */
     535
     536 /* SV_do_whois() */
     537 /*++++++++++++++++++++++++++++++++++++++
     538
     539   Handle whois connections.
     540
     541   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
     542
     543   More:
     544   +html+ <PRE>
     545   Author:
     546         joao
     547   +html+ </PRE>
     548   ++++++++++++++++++++++++++++++++++++++*/
     549 void *SV_do_whois(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     550   int sock = (int)arg;
     551
     552   ER_dbg_va(FAC_TH, ASP_TH_NEW,
     553             "Whois: Child thread [%d]: Socket number = %d",
     554             pthread_self(), sock);
     555
     556   /* Use a mutex to update the global whois thread counter. */
     557   pthread_mutex_lock(&Whois_thread_count_lock);
     558   Whois_thread_count++;
     559   ER_dbg_va(FAC_TH, ASP_TH_NEW,
     560             "Whois_thread_count++=%d", Whois_thread_count);
     561
     562   pthread_mutex_unlock(&Whois_thread_count_lock);
     563
     564   TA_add(sock, "whois");
     565   PW_interact(sock);
     566   close(sock);
     567   TA_delete();
     568
     569   /* Use a mutex to update the global whois thread counter. */
     570   pthread_mutex_lock(&Whois_thread_count_lock);
     571   Whois_thread_count--;
     572   ER_dbg_va(FAC_TH, ASP_TH_NEW,
     573             "Whois_thread_count--=%d", Whois_thread_count);
     574   pthread_mutex_unlock(&Whois_thread_count_lock);
     575
     576   pthread_exit((void *)0);
     577
     578 } /* SV_do_whois() */
     579
     580 /* SV_do_mirror() */
     581 /*++++++++++++++++++++++++++++++++++++++
     582
     583   Handle NRTM connections.
     584
     585   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
     586
     587   More:
     588   +html+ <PRE>
     589   Author:
     590         joao
     591   +html+ </PRE>
     592   ++++++++++++++++++++++++++++++++++++++*/
     593 void *SV_do_mirror(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     594   int sock = (int)arg;
     595   char print_buf[STR_M];
     596
     597   sprintf(print_buf, "NRTM: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
     598
     599   /* Use a mutex to update the global mirror thread counter. */
     600   pthread_mutex_lock(&Mirror_thread_count_lock);
     601   Mirror_thread_count++;
     602   sprintf(print_buf, "Mirror_thread_count++=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
     603   pthread_mutex_unlock(&Mirror_thread_count_lock);
     604
     605   TA_add(sock, "mirror");
     606   PM_interact(sock);
     607   TA_delete();
     608
     609   /* Use a mutex to update the global mirror thread counter. */
     610   pthread_mutex_lock(&Mirror_thread_count_lock);
     611   Mirror_thread_count--;
     612   sprintf(print_buf, "Mirror_thread_count--=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
     613   pthread_mutex_unlock(&Mirror_thread_count_lock);
     614
     615   pthread_exit((void *)0);
     616
     617 } /* SV_do_mirror() */
     618
     619 /* SV_do_config() */
     620 /*++++++++++++++++++++++++++++++++++++++
     621
     622   Handle config connections.
     623
     624   void *arg The socket to connect to. (It has to be passed in this way for this
     625 thread routine.)
     626
     627   More:
     628   +html+ <PRE>
     629   Author:
     630         joao
     631   +html+ </PRE>
     632   ++++++++++++++++++++++++++++++++++++++*/
     633 void *SV_do_config(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     634   int sock = (int)arg;
     635   char print_buf[STR_M];
     636
     637   sprintf(print_buf, "Config: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
     638
     639 /*
     640   printf("Hi there, there is nothing to configure yet\nBye..... :-)\n");
     641   fflush(NULL);
     642
     643   SK_close(sock);
     644 */
     645   TA_add(sock, "config");
     646   PC_interact(sock);
     647   TA_delete();
     648
     649   pthread_exit((void *)0);
     650
     651 } /* SV_do_config() */
     652
     653
     654 /*++++++++++++++++++++++++++++++++++++++
     655
     656   This is the routine that creates a watchdog thread.
     657
     658   The watchdog will cancel (pthread_cancel()) the calling thread in case the
     659   socket is closed by the client (its read-half is closed). The calling
     660   thread should make necessaruy preparations when calling the watchdog:
     661
     662   - the socket should be connected
     663   - cancellation points and cleanup routines should be defined
     664
     665   In case the connection is closed by the calling thread itself, the
     666   watchdog just exits and no action against the calling thread is performed.
     667
     668   wd_args - a pointer to wd_args_t structure containing
     669             data about socket and thread ID
     670
     671   More:
     672   +html+ <PRE>
     673   Author:
     674         ottrey
     675         joao
     676         andrei
     677   +html+ </PRE>
     678   ++++++++++++++++++++++++++++++++++++++*/
     679
     680 void SV_watchdog(wd_args_t *wd_args) {
         /* [<][>][^][v][top][bottom][index][help] */
     681  pthread_t tid;
     682  pthread_attr_t attr;
     683
     684  /* Start a new thread. */
     685  TH_create((void *(*)(void *))do_watchdog, (void *)wd_args);
     686
     687 // pthread_attr_init(&attr);     /* initialize attr with default attributes */
     688 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     689 // pthread_create(&tid, &attr, (void *(*)(void *))do_watchdog, (void *)wd_args);
     690
     691 }
     692
     693
     694 /*++++++++++++++++++++++++++++++++++++++
     695
     696 The watchdog thread itself
     697
     698 The watchdog thread makes select() on the connected socket waiting until it
     699 becomes readable. If this happens as a result of some input, it'll simply
     700 dump it. Otherwise, this indicates that the client has closed the
     701 connection. In this case watchdog will cancel (pthread_cancel()) the whois
     702 thread (which in its turn will kill (mysql_kill()) mysql thread as part of
     703 its cleanup routine).
     704
     705 More:
     706 +html+ <PRE>
     707 Author:
     708       andrei
     709 +html+ </PRE>
     710 ++++++++++++++++++++++++++++++++++++++*/
     711 static void do_watchdog(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     712   wd_args_t *wd_args = (wd_args_t *)arg;
     713   int socket;
     714   pthread_t tid;
     715   int nready;
     716   int n;
     717   fd_set rset;
     718   char buff[STR_S];
     719
     720   socket = wd_args->connected_socket;
     721   tid = wd_args->tid;
     722
     723
     724   FD_ZERO(&rset);
     725   FD_SET(socket, &rset);
     726
     727   while ((nready=select(socket+1, &rset, NULL, NULL, NULL))!=-1) {
     728
     729    /* There was some input or client half of connection was closed */
     730    /* Check for the latter */
     731    if (( n=read(socket, buff, sizeof(buff))) == 0) {
     732    /* Connection was closed by client */
     733    /* Now send a cancellation request to the whois thread. */
     734    /* mysql thread will be terminated by thread cleanup routine */
     735
     736    /* The only possible error is ESRCH, so we do not care about */
     737    pthread_cancel(tid);
     738
     739    /* Exit the watchdog thread, passing NULL as we don't expect pthread_join() */
     740    pthread_exit(NULL);
     741    }
     742
     743    /* Otherwise dump input and continue */
     744   }
     745
     746   /* the only reason that we are here is that the socket has been */
     747   /* closed by the whois thread and not valid. Just exit the watchdog, */
     748   /* passing NULL as we don't expect pthread_join() */
     749    pthread_exit(NULL);
     750
     751 }

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