1 | /*************************************** 2 | $Revision: 1.26 $ 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 | #include "mysql_driver.h" 59 | #include "access_control.h" 60 | #include "ud.h" 61 | #include "server.h" 62 | 63 | #define RIPE_REG 17 64 | 65 | /*+ String sizes +*/ 66 | #define STR_S 63 67 | #define STR_M 255 68 | #define STR_L 1023 69 | #define STR_XL 4095 70 | #define STR_XXL 16383 71 | 72 | 73 | /* Storage for descriptors of the read side of the pipe */ 74 | int sv_lockfd[MAX_LOCKS]; 75 | 76 | /* Listening sockets */ 77 | int SV_whois_sock; 78 | int SV_config_sock; 79 | int SV_mirror_sock; 80 | int SV_update_sock; 81 | 82 | void radix_init(void){ 83 | dieif( RP_init_trees( RIPE_REG ) != RP_OK ); 84 | dieif( RP_sql_load_reg(RIPE_REG) != RP_OK ); 85 | } 86 | 87 | /* SV_start() */ 88 | /*++++++++++++++++++++++++++++++++++++++ 89 | 90 | Start the server. 91 | 92 | More: 93 | +html+ <PRE> 94 | Authors: 95 | ottrey 96 | joao 97 | +html+ </PRE> 98 | +html+ Starts up the server. 99 | +html+ <OL> 100 | +html+ <LI> Create sockets on the necessary ports (whois, config and mirror) 101 | +html+ <LI> Start new threads for each service. 102 | +html+ </OL> 103 | +html+ <A HREF=".DBrc">.properties</A> 104 | 105 | ++++++++++++++++++++++++++++++++++++++*/ 106 | void SV_start() { 107 | /* Make listening sockets global variables */ 108 | /* int whois_sock,config_sock,mirror_sock,update_sock; */ 109 | /* uint32_t whois_addr,sock_addr,mirror_addr; */ 110 | int whois_port = -1; 111 | int config_port = -1; 112 | int mirror_port = -1; 113 | int update_port = -1; 114 | int update_mode; 115 | sigset_t sset; 116 | int fdes[2]; 117 | 118 | /* Create interrupt pipe */ 119 | /* Writing to this pipe will cause sleeping threads */ 120 | /* to wake up */ 121 | fprintf(stderr, "Creating an interrupt pipe\n"); 122 | if(pipe(fdes)==-1) { 123 | printf("Cannot open interrupt pipe\n"); 124 | exit(-1); 125 | } 126 | /* Save the pipe descriptors in sv_lock array */ 127 | sv_lockfd[WLOCK_SHTDOWN]=fdes[0]; 128 | sv_lockfd[LOCK_SHTDOWN]=fdes[1]; 129 | 130 | 131 | /* Initialise the access control list. */ 132 | AC_build(); 133 | AC_acc_load(); 134 | /* explicitly start the decay thread */ 135 | TH_run2((void *(*)(void *))AC_decay); 136 | 137 | /* Initialise the radix tree (separate thread[s]) 138 | already can allow socket connections, because the trees will 139 | be created locked, and will be unlocked when loaded */ 140 | TH_run2((void *(*)(void *)) radix_init ); 141 | 142 | /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */ 143 | /* Get port information for each service */ 144 | whois_port = SK_atoport(CO_get_whois_port(), "tcp"); 145 | printf("XXX htons(whois_port)=%d\n", htons(whois_port)); 146 | if(whois_port == -1) { 147 | printf("Invalid service/port: %d\n", htons(whois_port)); 148 | exit(-1); 149 | } 150 | 151 | /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */ 152 | config_port = SK_atoport(CO_get_config_port(), "tcp"); 153 | printf("XXX htons(config_port)=%d\n", htons(config_port)); 154 | if(config_port == -1) { 155 | printf("Invalid service/port: %d\n", htons(config_port)); 156 | exit(-1); 157 | } 158 | mirror_port = SK_atoport(CO_get_mirror_port(), "tcp"); 159 | printf("XXX htons(mirror_port)=%d\n", htons(mirror_port)); 160 | if(mirror_port == -1) { 161 | printf("Invalid service/port: %d\n", mirror_port); 162 | exit(-1); 163 | } 164 | 165 | /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */ 166 | update_port = SK_atoport(CO_get_update_port(), "tcp"); 167 | printf("XXX htons(update_port)=%d\n", htons(update_port)); 168 | if(update_port == -1) { 169 | printf("Invalid service/port: %d\n", htons(update_port)); 170 | exit(-1); 171 | } 172 | 173 | 174 | 175 | /* 6. Create a socket on the necessary ports/addresses and bind to them. */ 176 | /* whois socket */ 177 | SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY); 178 | /* Currently binds to INADDR_ANY. Will need to get specific address */ 179 | /* SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */ 180 | /* config interface socket */ 181 | SV_config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY); 182 | /* nrt socket */ 183 | SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port,INADDR_ANY); 184 | /* update interface socket */ 185 | SV_update_sock = SK_getsock(SOCK_STREAM, update_port, INADDR_ANY); 186 | 187 | 188 | /* Now.... accept() calls block until they get a connection 189 | so to listen on more than one port we need more 190 | than one thread */ 191 | 192 | /* Create master thread for whois threads */ 193 | TH_run(SV_whois_sock, TH_do_whois); 194 | 195 | /* Create master thread for config threads */ 196 | TH_run(SV_config_sock, TH_do_config); 197 | /* Create master thread for mirror threads */ 198 | TH_run(SV_mirror_sock, TH_do_mirror); 199 | 200 | /* Get the mode of operation of the update layer */ 201 | update_mode=CO_get_update_mode(); 202 | if(IS_UPDATE(update_mode)) { 203 | /* we will play with dbupdate */ 204 | fprintf(stderr,"UPDATE mode\n"); 205 | TH_run1(SV_update_sock, (void *)UD_do_updates); 206 | } 207 | else { 208 | /* start NRTM client */ 209 | fprintf(stderr,"NRTM mode\n"); 210 | TH_run2((void *)UD_do_nrtm); 211 | } 212 | 213 | /* XXX Is this needed? */ 214 | pthread_exit(NULL); 215 | 216 | } /* SV_start() */ 217 | 218 | /* SV_shutdown() */ 219 | /*++++++++++++++++++++++++++++++++++++++ 220 | 221 | Shutdown the server. 222 | 223 | More: 224 | +html+ <PRE> 225 | Authors: 226 | andrei 227 | +html+ </PRE> 228 | +html+ Stops the server. 229 | +html+ <OL> 230 | +html+ <LI> Close listening sockets (whois, config, mirror and updates) 231 | +html+ <LI> Stop all threads by triggering do_server variable. 232 | +html+ </OL> 233 | +html+ <A HREF=".DBrc">.properties</A> 234 | 235 | ++++++++++++++++++++++++++++++++++++++*/ 236 | void SV_shutdown() { 237 | char print_buf[STR_M]; 238 | 239 | sprintf(print_buf, "%d", 0); 240 | /* Stop updates */ 241 | CO_set_const("UD.do_update", print_buf); 242 | /* Stop all servers */ 243 | CO_set_const("SV.do_server", print_buf); 244 | sprintf(print_buf, "Stopping all servers\n"); 245 | fprintf(stderr, print_buf); 246 | /*log_print(print_buf); */ 247 | strcpy(print_buf, ""); 248 | 249 | /* Wake up all sleeping threads */ 250 | fprintf(stderr, "Going to wake sleeping threads up\n"); 251 | write(sv_lockfd[WLOCK_SHTDOWN], " ", 1); 252 | 253 | /* CLose all listening sockets, so accept call exits */ 254 | close(SV_whois_sock); 255 | close(SV_config_sock); 256 | close(SV_mirror_sock); 257 | close(SV_update_sock); 258 | 259 | 260 | } /* SV_shutdown() */ 261 | 262 | 263 | /* SV_sleep() */ 264 | /*++++++++++++++++++++++++++++++++++++++ 265 | 266 | Sleep and wake up on special events. 267 | 268 | More: 269 | +html+ <PRE> 270 | Authors: 271 | andrei 272 | +html+ </PRE> 273 | +html+ Sleeps timeout but wakes up when an envent occures. 274 | 275 | ++++++++++++++++++++++++++++++++++++++*/ 276 | int SV_sleep(int lock, int sleeptime) { 277 | struct timeval timeout; 278 | struct stat st; 279 | fd_set set; 280 | 281 | if (fstat(sv_lockfd[lock], &st) ==-1) { 282 | fprintf(stderr, "Error stat-ing the lock file\n"); 283 | return(-1); 284 | } 285 | 286 | timeout.tv_sec=sleeptime; 287 | timeout.tv_usec=0; 288 | 289 | FD_ZERO(&set); 290 | FD_SET(sv_lockfd[lock], &set); 291 | 292 | fprintf(stderr, "Going to sleep\n"); 293 | select(sv_lockfd[lock]+1, &set, NULL, NULL, &timeout); 294 | 295 | fprintf(stderr, "Select returned\n"); 296 | 297 | return(0); 298 | }