1 | /***************************************
2 | $Revision: 1.12 $
3 |
4 | Wrapper for NRTM client
5 |
6 | Status: NOT REVUED, NOT TESTED
7 |
8 | Author(s): Andrei Robachevsky
9 |
10 | ******************/ /******************
11 | Modification History:
12 | andrei (17/01/2000) Created.
13 | ******************/ /******************
14 | Copyright (c) 2000 RIPE NCC
15 |
16 | All Rights Reserved
17 |
18 | Permission to use, copy, modify, and distribute this software and its
19 | documentation for any purpose and without fee is hereby granted,
20 | provided that the above copyright notice appear in all copies and that
21 | both that copyright notice and this permission notice appear in
22 | supporting documentation, and that the name of the author not be
23 | used in advertising or publicity pertaining to distribution of the
24 | software without specific, written prior permission.
25 |
26 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 | AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 | DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 | ***************************************/
33 | #include <sys/types.h>
34 | #include <fcntl.h>
35 | #include <signal.h>
36 | #include "ud.h"
37 | #include "ud_int.h"
38 | #include "constants.h"
39 | #include "server.h"
40 | #include "protocol_mirror.h"
41 |
42 |
43 | /* Response time to swtching updates on and off */
44 | #define TIMEOUT 60
45 |
46 |
47 | int get_current_serial()
48 | {
49 | int fd;
50 | char buff[64];
51 | const char *filename;
52 |
53 | filename=CO_get_nrtm_cserialfile();
54 | fd=open(filename, O_RDONLY, (mode_t)0);
55 | if (fd < 0) { fprintf(stderr, "cannot open %s\n", filename); return(-1); }
56 | read(fd, buff, sizeof(buff));
57 | close(fd);
58 | return(atoi(buff));
59 | }
60 |
61 | int set_current_serial(int current_serial)
62 | {
63 | FILE *file;
64 | const char *filename;
65 |
66 | filename=CO_get_nrtm_cserialfile();
67 | file=fopen(filename, "w+");
68 | if (file==NULL) { fprintf(stderr, "cannot open %s\n", filename); return(-1); }
69 | fprintf(file,"%d\n", current_serial);
70 | fflush(file);
71 | fclose(file);
72 | return(current_serial);
73 | }
74 |
75 |
76 | /*************************************
77 | *
78 | *
79 | **************************************/
80 |
81 | void UD_do_nrtm()
82 | {
83 | UD_stream_t ud_stream;
84 | struct _nrtm *nrtm;
85 | /*int dummy_allowed;*/
86 | int delay;
87 | int do_update=1;
88 | int do_server;
89 | const char *logfilename;
90 | FILE *file;
91 | int num_ok;
92 | int upto_last;
93 | int current_serial;
94 |
95 | nrtm=calloc(1, sizeof(struct _nrtm));
96 | if(nrtm==NULL) {
97 | printf("Cannot allocate memory\n");
98 | die;
99 | }
100 | /* get mode of operation: protected/unprotected (dummy) */
101 | ud_stream.ud_mode=CO_get_update_mode();
102 |
103 | fprintf(stderr, "Mode of operation:\n");
104 | if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
105 | else fprintf(stderr, "* dummy not allowed\n");
106 | if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
107 | else fprintf(stderr, "* NRTM\n");
108 | if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
109 | else fprintf(stderr, "* running as a server\n");
110 |
111 | /* get mirror server */
112 | nrtm->server=CO_get_nrtm_host();
113 |
114 | /* get mirror port */
115 | nrtm->port = SK_atoport(CO_get_nrtm_port(), "tcp");
116 | printf("XXX nrtm_port=%d\n", nrtm->port);
117 | if(nrtm->port == -1) {
118 | printf("Invalid service/port: %d\n", nrtm->port);
119 | return;
120 | }
121 |
122 | /* get mirror version */
123 | nrtm->version=CO_get_nrtm_version();
124 |
125 | /* get error log facility */
126 | logfilename=CO_get_nrtm_logfile();
127 |
128 | /* Connect to the database */
129 | fprintf(stderr, "D: Making SQL connection to %s@%s ...", CO_get_database(), CO_get_host());
130 |
131 | ud_stream.db_connection=SQ_get_connection2();
132 |
133 | if(! ud_stream.db_connection) {
134 | fprintf(stderr, "D: ERROR: no SQL connection\n");
135 | return;
136 | }
137 |
138 | fprintf(stderr, "OK\n");
139 |
140 |
141 |
142 | /* ud_stream.dummy_allowed=dummy_allowed;*/
143 | ud_stream.num_skip=0;
144 | ud_stream.load_pass=0;
145 | ud_stream.nrtm=nrtm;
146 |
147 | upto_last=0; /* let's start gradually if the backlog is > SBUNCH (1000) serials*/
148 |
149 | /*+++ main cycle +++*/
150 |
151 | do {
152 | do_update=CO_get_do_update();
153 | if(do_update) {
154 |
155 |
156 | /* get current serial */
157 | current_serial=get_current_serial();
158 | nrtm->current_serial=PM_get_current_serial(ud_stream.db_connection);
159 |
160 | if(nrtm->current_serial == -1) {
161 | printf("Error obtaining current serial: %ld(%d)\n", nrtm->current_serial, current_serial);
162 | return;
163 | }
164 |
165 | fprintf(stderr, "current_serial:\t%ld(%d)\n", nrtm->current_serial, current_serial);
166 | fprintf(stderr, "conecting to server...\n");
167 |
168 |
169 | file = get_NRTM_stream(nrtm, upto_last);
170 | fprintf(stderr, "OK\n");
171 | printf("OK\n");
172 |
173 |
174 | if (file==NULL) {
175 | fprintf(stderr, "Cannot open data stream. Trying...\n");
176 | sleep(100);
177 | continue;
178 | }
179 |
180 |
181 | ud_stream.stream=file;
182 | ud_stream.log.logfile = fopen(logfilename, "a+");
183 | ud_stream.log.num_ok=0;
184 | ud_stream.log.num_failed=0;
185 |
186 |
187 | fprintf(stderr, "starting processing stream\n");
188 |
189 | num_ok=UD_process_stream(&ud_stream);
190 |
191 |
192 | /*Check for errors */
193 | if(num_ok<0) {
194 | fprintf(stderr, "processing stream failed\n");
195 | do_server=0;
196 | break;
197 | }
198 | else fprintf(stderr, "processing stream finished\n");
199 |
200 | /* Now we can process serials in normal way (upto LAST)*/
201 | if(num_ok==0) upto_last=1;
202 |
203 | /* This is for test purposes, just to know if we are out of sync */
204 | set_current_serial((int)(current_serial+num_ok));
205 | fprintf(ud_stream.log.logfile, "forwarded to serial:\t%ld(%d)\n", (nrtm->current_serial+num_ok), current_serial+num_ok);
206 | fclose(ud_stream.log.logfile);
207 | fprintf(stderr, "forwarded to serial:\t%ld(%d)\n", (nrtm->current_serial+num_ok), current_serial+num_ok);
208 | printf("Objects received: %d\n-----------\n", num_ok);
209 |
210 | /* get delay */
211 | delay=CO_get_nrtm_delay();
212 | SV_sleep(LOCK_SHTDOWN, delay);
213 | }
214 | else SV_sleep(LOCK_SHTDOWN, TIMEOUT);
215 |
216 | do_server=CO_get_do_server();
217 |
218 | } while(do_server); /* main cycle */
219 |
220 | if(nrtm) free(nrtm);
221 | /* That's all. Close connection to the DB */
222 | SQ_close_connection(ud_stream.db_connection);
223 | fprintf(stderr, "NRTM stopped\n");
224 |
225 | } /* UD_do_nrtm() */
226 |
227 |
228 |
229 |
230 | /*************************************
231 | *
232 | *
233 | **************************************/
234 |
235 | void UD_do_updates(void *arg)
236 | {
237 | int listening_socket = (int)arg;
238 | int connected_socket;
239 | UD_stream_t ud_stream;
240 | int do_update=1;
241 | int do_server;
242 | const char *logfilename;
243 | FILE *file, *file_ack;
244 | int num_ok;
245 |
246 |
247 | /* get mode of operation: protected/unprotected (dummy) */
248 | ud_stream.ud_mode=CO_get_update_mode();
249 |
250 | fprintf(stderr, "Mode of operation:\n");
251 | if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n");
252 | else fprintf(stderr, "* dummy not allowed\n");
253 | if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n");
254 | else fprintf(stderr, "* NRTM\n");
255 | if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n");
256 | else fprintf(stderr, "* running as a server\n");
257 |
258 |
259 |
260 |
261 | /* get error log facility */
262 | logfilename=CO_get_nrtm_logfile();
263 |
264 | /* Connect to the database */
265 | fprintf(stderr, "D: Making SQL connection to %s@%s ...", CO_get_database(), CO_get_host());
266 |
267 | ud_stream.db_connection=SQ_get_connection2();
268 |
269 | if(! ud_stream.db_connection) {
270 | fprintf(stderr, "D: ERROR: no SQL connection\n");
271 | return;
272 | }
273 |
274 | fprintf(stderr, "OK\n");
275 |
276 | ud_stream.num_skip=0;
277 | ud_stream.load_pass=0;
278 | ud_stream.nrtm=NULL;
279 |
280 | /*+++ main cycle +++*/
281 |
282 | do { /* be alive while do_server is 1. do_server is turned off by SIGINT */
283 |
284 | /* accept connection */
285 | connected_socket = SK_accept_connection(listening_socket);
286 | if(connected_socket==-1) break;
287 |
288 | file=fdopen(connected_socket, "r");
289 | file_ack=fdopen(connected_socket, "w");
290 |
291 | do_update=CO_get_do_update();
292 | if(do_update) {
293 |
294 | fprintf(stderr, "Connection accepted...\n");
295 |
296 | if ((file==NULL) || (file_ack==NULL)) {
297 | fprintf(stderr, "Cannot open data stream. Closing connction\n");
298 | return;
299 | }
300 | fprintf(stderr, "Connection accepted...\n");
301 |
302 | ud_stream.stream=file;
303 | ud_stream.log.logfile = fopen(logfilename, "a+");
304 | ud_stream.log.num_ok=0;
305 | ud_stream.log.num_failed=0;
306 |
307 |
308 | fprintf(stderr, "starting processing object\n");
309 |
310 | num_ok=UD_process_stream(&ud_stream);
311 |
312 | fprintf(stderr, "processing object finished\n");
313 |
314 | if(num_ok==1) {
315 | fprintf(file_ack, "%%ERROR 0\n");
316 | fprintf(stderr, "%%ERROR 0\n");
317 | }
318 | else {
319 | num_ok=(-1)*num_ok;
320 | fprintf(file_ack, "%%ERROR %d\n",num_ok);
321 | fprintf(stderr, "%%ERROR %d\n",num_ok);
322 | fprintf(file_ack, "Transaction had the following problems:\n");
323 | if(num_ok & ERROR_U_MEM) fprintf(file_ack, "Memory allocation error\n");
324 | /* if(num_ok & ERROR_U_DBS) fprintf(file_ack, "Database (SQL) error\n");*/
325 | /* if(num_ok & ERROR_U_OBJ) fprintf(file_ack, "Object (RF) error\n");*/
326 | /* if(num_ok & ERROR_U_AUT) fprintf(file_ack, "Object authentication error\n");*/
327 | if(num_ok & ERROR_U_BADOP) fprintf(file_ack, "Bad operation\n");
328 | if(num_ok & ERROR_U_COP) fprintf(file_ack, "Conflicting operation\n");
329 | if(num_ok & ERROR_U_NSUP) fprintf(file_ack, "Object of this type is not supported\n");
330 | if(num_ok & ERROR_U_BUG) fprintf(file_ack, "Software bug - report to <ripe-dbm@ripe.net>\n");
331 | }
332 | if(ud_stream.error_script)fprintf(file_ack, "%s\n", ud_stream.error_script);
333 |
334 | if(ud_stream.error_script) free(ud_stream.error_script);
335 | fclose(file_ack);
336 | fclose(file);
337 | fclose(ud_stream.log.logfile);
338 |
339 | } /* if do_update*/
340 | else { /* Otherwise print a message*/
341 | fprintf(file_ack, "%%ERROR 1000\n%%Updates are suspended\n");
342 | fclose(file_ack);
343 | fclose(file);
344 | }
345 |
346 | do_server=CO_get_do_server();
347 |
348 | } while (do_server); /* main cycle */
349 |
350 | /* That's all. Close connection to the DB */
351 | SQ_close_connection(ud_stream.db_connection);
352 |
353 | fprintf(stderr, "server stopped\n");
354 |
355 | } /* UD_do_update() */
356 |
357 |
358 |
359 |