modules/sv/server.c

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

FUNCTIONS

This source file includes following functions.
  1. radix_init
  2. SV_start
  3. SV_shutdown
  4. SV_sleep

/***************************************
  $Revision: 1.26 $

  Example code: A server for a client to connect to.

  Status: NOT REVUED, NOT TESTED

 Authors:       Chris Ottrey, Joao Damas

  +html+ <DL COMPACT>
  +html+ <DT>Online References:
  +html+ <DD><UL>
  +html+   <LI>Based on <A HREF="http://iii.ripe.net/dbase/coding/new.code/progress/ottrey/code/java/src/DBServer.java">DBServer.java</A>
  +html+ </UL>
  +html+ </DL>
 
  ******************/ /******************
  Modification History:
        ottrey (02/03/1999) Created.
        ottrey (08/03/1999) Modified.
        joao   (22/06/1999) Modified.
  ******************/ /******************
  Copyright (c) 1999                              RIPE NCC
 
  All Rights Reserved
  
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose and without fee is hereby granted,
  provided that the above copyright notice appear in all copies and that
  both that copyright notice and this permission notice appear in
  supporting documentation, and that the name of the author not be
  used in advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.
  
  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 ***************************************/
#include <sys/socket.h>
#include <netinet/in.h>

#include <sys/wait.h>
#include <ctype.h>

#include <sys/types.h>
#include <sys/stat.h>

#include "thread.h"
#include "rxroutines.h"
#include "socket.h"
/*
#include "objects.h"
*/
#include "constants.h"
#include "mysql_driver.h"
#include "access_control.h"
#include "ud.h"
#include "server.h"

#define RIPE_REG 17

/*+ String sizes +*/
#define STR_S   63
#define STR_M   255
#define STR_L   1023
#define STR_XL  4095
#define STR_XXL 16383


/* Storage for descriptors of the read side of the pipe */
int sv_lockfd[MAX_LOCKS];

/* Listening sockets */
int SV_whois_sock;
int SV_config_sock;
int SV_mirror_sock;
int SV_update_sock;

void radix_init(void){
/* [<][>][^][v][top][bottom][index][help] */
  dieif( RP_init_trees( RIPE_REG ) != RP_OK );
  dieif( RP_sql_load_reg(RIPE_REG) != RP_OK );
}

/* SV_start() */
/*++++++++++++++++++++++++++++++++++++++

  Start the server.

  More:
  +html+ <PRE>
  Authors:
        ottrey
        joao
  +html+ </PRE>
  +html+ Starts up the server.
  +html+ <OL>
  +html+   <LI> Create sockets on the necessary ports (whois, config and mirror)
  +html+   <LI> Start new threads for each service.
  +html+ </OL>
  +html+ <A HREF=".DBrc">.properties</A>

  ++++++++++++++++++++++++++++++++++++++*/
void SV_start() {
/* [<][>][^][v][top][bottom][index][help] */
  /* Make listening sockets global variables  */
  /*  int whois_sock,config_sock,mirror_sock,update_sock; */
  /* uint32_t whois_addr,sock_addr,mirror_addr; */
  int whois_port = -1;
  int config_port = -1;
  int mirror_port = -1; 
  int update_port = -1;
  int update_mode;
  sigset_t sset;
  int fdes[2];

  /* Create interrupt pipe */
  /* Writing to this pipe will cause sleeping threads */
  /* to wake up */
  fprintf(stderr, "Creating an interrupt pipe\n");
  if(pipe(fdes)==-1) {
   printf("Cannot open interrupt pipe\n");
   exit(-1);
  } 
  /* Save the pipe descriptors in sv_lock array */
  sv_lockfd[WLOCK_SHTDOWN]=fdes[0];
  sv_lockfd[LOCK_SHTDOWN]=fdes[1];

  
  /* Initialise the access control list. */
  AC_build();
  AC_acc_load();
  /* explicitly start the decay thread */
  TH_run2((void *(*)(void *))AC_decay);

  /* Initialise the radix tree (separate thread[s])
     already can allow socket connections, because the trees will 
     be created locked, and will be unlocked when loaded */
  TH_run2((void *(*)(void *)) radix_init );
  
  /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
  /* Get port information for each service */
  whois_port = SK_atoport(CO_get_whois_port(), "tcp");
  printf("XXX htons(whois_port)=%d\n", htons(whois_port));
  if(whois_port == -1) {
    printf("Invalid service/port: %d\n", htons(whois_port));
    exit(-1);
  }

  /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
  config_port = SK_atoport(CO_get_config_port(), "tcp");
  printf("XXX htons(config_port)=%d\n", htons(config_port));
  if(config_port == -1) {
    printf("Invalid service/port: %d\n", htons(config_port));
    exit(-1); 
  }
  mirror_port = SK_atoport(CO_get_mirror_port(), "tcp");
  printf("XXX htons(mirror_port)=%d\n", htons(mirror_port));
  if(mirror_port == -1) {
    printf("Invalid service/port: %d\n", mirror_port);
    exit(-1);
  }

  /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
  update_port = SK_atoport(CO_get_update_port(), "tcp");
  printf("XXX htons(update_port)=%d\n", htons(update_port));
  if(update_port == -1) {
    printf("Invalid service/port: %d\n", htons(update_port));
    exit(-1); 
  }



  /* 6. Create a socket on the necessary ports/addresses and bind to them. */
  /* whois socket */
  SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY);
/* Currently binds to INADDR_ANY. Will need to get specific address */
/*  SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */
  /* config interface socket */
  SV_config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY);
  /* nrt socket */
  SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port,INADDR_ANY);
  /* update interface socket */
  SV_update_sock = SK_getsock(SOCK_STREAM, update_port, INADDR_ANY);


  /* Now.... accept() calls block until they get a connection
     so to listen on more than one port we need more
     than one thread */

  /* Create master thread for whois threads */
   TH_run(SV_whois_sock, TH_do_whois);

  /* Create master thread for config threads */
   TH_run(SV_config_sock, TH_do_config);
  /* Create master thread for mirror threads */
   TH_run(SV_mirror_sock, TH_do_mirror);

/* Get the mode of operation of the update layer */
    update_mode=CO_get_update_mode();
    if(IS_UPDATE(update_mode)) {
    /* we will play with dbupdate */
    fprintf(stderr,"UPDATE mode\n");
     TH_run1(SV_update_sock, (void *)UD_do_updates);
    }
    else {
   /* start NRTM client */
    fprintf(stderr,"NRTM mode\n");    
    TH_run2((void *)UD_do_nrtm);
    }

  /* XXX Is this needed? */
  pthread_exit(NULL);

} /* SV_start() */

/* SV_shutdown() */
/*++++++++++++++++++++++++++++++++++++++

  Shutdown the server.

  More:
  +html+ <PRE>
  Authors:
        andrei
  +html+ </PRE>
  +html+ Stops the server.
  +html+ <OL>
  +html+   <LI> Close listening sockets (whois, config, mirror and updates)
  +html+   <LI> Stop all threads by triggering do_server variable.
  +html+ </OL>
  +html+ <A HREF=".DBrc">.properties</A>

  ++++++++++++++++++++++++++++++++++++++*/
void SV_shutdown() {
/* [<][>][^][v][top][bottom][index][help] */
char print_buf[STR_M];
 
 sprintf(print_buf, "%d", 0);
 /* Stop updates */
 CO_set_const("UD.do_update", print_buf);
 /* Stop all servers */
 CO_set_const("SV.do_server", print_buf);
 sprintf(print_buf, "Stopping all servers\n");
 fprintf(stderr, print_buf);
 /*log_print(print_buf); */
 strcpy(print_buf, "");
 
 /* Wake up all sleeping threads */
 fprintf(stderr, "Going to wake sleeping threads up\n");
 write(sv_lockfd[WLOCK_SHTDOWN], " ", 1); 

 /* CLose all listening sockets, so accept call exits */
 close(SV_whois_sock);
 close(SV_config_sock);
 close(SV_mirror_sock);
 close(SV_update_sock);
 
 
} /* SV_shutdown() */


/* SV_sleep() */
/*++++++++++++++++++++++++++++++++++++++

  Sleep and wake up on special events.

  More:
  +html+ <PRE>
  Authors:
        andrei
  +html+ </PRE>
  +html+ Sleeps timeout but wakes up when an envent occures.

  ++++++++++++++++++++++++++++++++++++++*/
int SV_sleep(int lock, int sleeptime) {
/* [<][>][^][v][top][bottom][index][help] */
struct timeval timeout;
struct stat st;
fd_set set;

 if (fstat(sv_lockfd[lock], &st) ==-1) {
  fprintf(stderr, "Error stat-ing the lock file\n");
  return(-1);
 } 
 
 timeout.tv_sec=sleeptime;
 timeout.tv_usec=0;
   
 FD_ZERO(&set);
 FD_SET(sv_lockfd[lock], &set);
 
 fprintf(stderr, "Going to sleep\n");
 select(sv_lockfd[lock]+1, &set, NULL, NULL, &timeout);
 
 fprintf(stderr, "Select returned\n");
      
 return(0);
}

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