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  | }