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