1 | /*************************************** 2 | $Revision: 1.41 $ 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,2001,2002 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 | 34 | #include "rip.h" 35 | 36 | #include <sys/types.h> 37 | #include <sys/socket.h> 38 | #include <netinet/in.h> 39 | #include <arpa/inet.h> 40 | #include <fcntl.h> 41 | #include <signal.h> 42 | #include <sys/poll.h> 43 | 44 | 45 | /* here we store sockets for update threads */ 46 | /* they are from SV module */ 47 | extern int SV_update_sock[]; 48 | 49 | /* here is the shutdown pipe for update threads */ 50 | /* also from SV module (apologies for breaking encapsulation) */ 51 | extern int SV_shutdown_recv_fd; 52 | 53 | /* Response time to swtching updates on and off */ 54 | #define TIMEOUT 60 55 | 56 | /* timeout between successive attempts to establish connection with server */ 57 | #define PM_CONNECTION_TIMEOUT 10 58 | 59 | /* Maximum number of objects(serials) we can consume at a time */ 60 | #define SBUNCH 1000 61 | 62 | /* Timeout in seconds when reading (writing) from DBupdate */ 63 | #define STREAM_TIMEOUT 120 64 | 65 | /************************************************************ 66 | * int get_NRTM_fd() * 67 | * * 68 | * Gets the NRTM stream * 69 | * * 70 | * First tries to request the serials from the NRTM server * 71 | * If the name of the server appears to be not a network name* 72 | * it tries to open the file with this name * 73 | * * 74 | * nrtm - pointer to _nrtm structure * 75 | * upto_last - if==1 then requests to download serials using * 76 | * LAST keyword * 77 | * * 78 | * Returns: * 79 | * A file descriptor for a data stream * 80 | * -1 - error * 81 | * * 82 | ************************************************************/ 83 | int get_NRTM_fd(struct _nrtm *nrtm, int upto_last, char *source) 84 | { 85 | int sockfd; 86 | struct hostent *hptr; 87 | struct sockaddr_in serv_addr; 88 | struct in_addr *paddr; 89 | char host_info[STR_XXL]; 90 | GString *line_buff; 91 | int fd; 92 | int ret; 93 | struct hostent result; 94 | int error; 95 | int network; 96 | 97 | int so_keepalive =1; 98 | 99 | /* fprintf(stderr, "Making connection to NRTM server ...\n");*/ 100 | if ((sockfd=socket(AF_INET, SOCK_STREAM, 0))==-1){ 101 | ER_perror(FAC_UD, UD_FS, "cannot create socket"); 102 | return(-1); 103 | } 104 | 105 | /* set keepalive option so we can reconnect in case there was no connectivity */ 106 | /* with primary. See bug 100 for details. Default timeout is 2hours */ 107 | if ((error=setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &so_keepalive, sizeof(so_keepalive))) == -1){ 108 | ER_perror(FAC_UD, UD_FS, "cannot set KEEPALIVE socket option"); 109 | return(-1); 110 | } 111 | #ifdef __linux__ 112 | if(gethostbyname_r(nrtm->server, &result, host_info, sizeof(host_info), &hptr, &error)<0) hptr=NULL; 113 | #else/* default is Solaris implementation */ 114 | hptr=gethostbyname_r(nrtm->server, &result, host_info, sizeof(host_info), &error); 115 | #endif 116 | 117 | /* Check if it is a network stream or a file */ 118 | if (hptr) { /* this is a network stream*/ 119 | paddr=(struct in_addr *)hptr->h_addr; 120 | bzero(&serv_addr, sizeof(serv_addr)); 121 | serv_addr.sin_family=AF_INET; 122 | serv_addr.sin_port=nrtm->port; 123 | memcpy(&serv_addr.sin_addr, paddr, sizeof(struct in_addr)); 124 | /* fprintf(stderr,"Trying %s port %d\n", inet_ntoa(serv_addr.sin_addr), nrtm->port);*/ 125 | if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))==-1) { 126 | ER_perror(FAC_UD, UD_FS, "cannot connect, errno:%d", errno); 127 | close(sockfd); 128 | return(-1); 129 | } 130 | /* fprintf(stderr, "Sending Invitation\n"); */ 131 | 132 | /* Request all available serials (upto LAST), or SBUNCH of them */ 133 | line_buff = g_string_sized_new(STR_L); 134 | if(upto_last==1) 135 | g_string_sprintf(line_buff, "-g %s:%d:%ld-LAST\n", source, nrtm->version, nrtm->current_serial+1); 136 | else if(upto_last==-1) /* persistent mirroring */ 137 | g_string_sprintf(line_buff, "-k -g %s:%d:%ld-LAST\n", source, nrtm->version, nrtm->current_serial+1); 138 | else 139 | g_string_sprintf(line_buff, "-g %s:%d:%ld-%ld\n", source, nrtm->version, nrtm->current_serial+1, nrtm->current_serial+SBUNCH); 140 | ret=SK_write(sockfd, line_buff->str, line_buff->len, NULL, NULL ); 141 | g_string_free(line_buff, TRUE); 142 | if(ret != 1) { 143 | ER_perror(FAC_UD, UD_FS, "cannot write"); 144 | close(sockfd); 145 | return(-1); 146 | } 147 | fd=sockfd; 148 | network=1; 149 | /* fprintf(stderr, "Returning stream pointer\n"); */ 150 | } 151 | else { /* this is a file stream*/ 152 | network=0; 153 | close(sockfd); 154 | /* fprintf(stderr, "Trying file ...\n");*/ 155 | if((fd=open(nrtm->server, O_RDONLY, 0666))==-1) { 156 | ER_perror(FAC_UD, UD_FS, "cannot open"); 157 | return(-1); 158 | } 159 | } 160 | return(fd); 161 | } 162 | 163 | 164 | 165 | /************************************************************ 166 | * void UD_do_nrtm() * 167 | * * 168 | * Processes NRTM stream * 169 | * * 170 | * It cycles requesting objects from the NRTM server, * 171 | * processing them and then sleeping a specified amount of * 172 | * time. * 173 | * * 174 | * It starts by requesting SBUNCH number of serials and does * 175 | * so untill no serials are received (actually a warning * 176 | * is received saying that the requested range is invalid) * 177 | * This approach avoids excessive load on the NRTM server * 178 | * * 179 | * After that it requests serials using LAST keyward keeping * 180 | * almost in sync with the server * 181 | * * 182 | ************************************************************/ 183 | 184 | void UD_do_nrtm(void *arg) 185 | { 186 | int source = (int)arg; 187 | UD_stream_t ud_stream; 188 | struct _nrtm *nrtm; 189 | int nrtm_delay; 190 | int do_update=1; 191 | int do_server; 192 | int nrtm_fd; 193 | int num_ok; 194 | int upto_last; 195 | GString *ta_activity; 196 | ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source); 197 | char *db_host, *db_name, *db_user, *db_passwd; 198 | int db_port; 199 | /* get source we are going to mirror */ 200 | char *source_name = ca_get_srcname(source_hdl); 201 | 202 | { /* set up the lohgging path */ 203 | int res; 204 | char *er_ud_def = ca_get_er_ud_def; /* something like 'RIPUPDLOG basename' */ 205 | GString *er_def; 206 | char *erret = NULL; 207 | 208 | er_def = g_string_sized_new(256); 209 | g_string_sprintf(er_def, "%s %s", er_ud_def, source_name); 210 | fprintf(stderr, "[%s]\n", er_def->str); 211 | if( (res = ER_macro_spec(er_def->str, &erret)) != 0 ) { 212 | fputs(erret, stderr); 213 | die; 214 | /* or some other error handling */ 215 | } 216 | UT_free(erret); /* the response is allocated and must be freed */ 217 | g_string_free(er_def, TRUE); 218 | UT_free(er_ud_def); 219 | } 220 | 221 | /* load the dictionary */ 222 | rpsl_load_dictionary(RPSL_DICT_CORE); 223 | 224 | nrtm=UT_calloc(1, sizeof(struct _nrtm)); 225 | if(nrtm==NULL) { 226 | ER_perror(FAC_UD, UD_MEM, "cannot allocate memory"); 227 | die; 228 | } 229 | /* get mode of operation: protected/unprotected (dummy) */ 230 | memset(&ud_stream, 0, sizeof(ud_stream)); 231 | ud_stream.source_hdl=source_hdl; 232 | ud_stream.ud_mode=ca_get_srcmode(source_hdl); 233 | nrtm_delay=ca_get_srcnrtmdelay(source_hdl); 234 | /* Zero delay means persistent connection */ 235 | if (nrtm_delay==0) ud_stream.ud_mode |= B_PERSIST_MIRR; 236 | 237 | fprintf(stderr, "Mode of operation:\n"); 238 | if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n"); 239 | else fprintf(stderr, "* dummy not allowed\n"); 240 | 241 | if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n"); 242 | else if(IS_NRTM_CLNT(ud_stream.ud_mode)) { 243 | 244 | if(IS_PERSIST_MIRR(ud_stream.ud_mode))fprintf(stderr, "* NRTM: persistent conection\n"); 245 | else fprintf(stderr, "* NRTM\n"); 246 | } 247 | else fprintf(stderr, "* STATIC\n"); 248 | 249 | if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n"); 250 | else fprintf(stderr, "* running as a server\n"); 251 | 252 | if(IS_NO_NHR(ud_stream.ud_mode))fprintf(stderr, "* NHR is not maintained\n"); 253 | else fprintf(stderr, "* NHR is maintained\n"); 254 | 255 | 256 | /* get mirror server */ 257 | nrtm->server=ca_get_srcnrtmhost(source_hdl); 258 | 259 | 260 | /* get mirror port */ 261 | nrtm->port = htons(ca_get_srcnrtmport(source_hdl)); 262 | printf("XXX nrtm_port=%d\n", ntohs(nrtm->port)); 263 | 264 | /* get mirror version */ 265 | nrtm->version=ca_get_srcnrtmprotocolvers(source_hdl); 266 | 267 | 268 | /* get error log facility */ 269 | /* logfilename=ca_get_srcnrtmlog(source_hdl); */ 270 | 271 | db_host = ca_get_srcdbmachine(source_hdl); 272 | db_port = ca_get_srcdbport(source_hdl); 273 | db_name = ca_get_srcdbname(source_hdl); 274 | db_user = ca_get_srcdbuser(source_hdl); 275 | db_passwd = ca_get_srcdbpassword(source_hdl); 276 | 277 | /* Connect to the database */ 278 | ER_dbg_va(FAC_UD, ASP_UD_SQL, "%s making SQL connection to %s@%s ...", UD_TAG, db_name, db_host); 279 | ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd); 280 | 281 | 282 | if(! ud_stream.db_connection) { 283 | ER_perror(FAC_UD, UD_SQL, "no connection to SQL server"); 284 | die; 285 | } 286 | 287 | ud_stream.num_skip=0; 288 | ud_stream.load_pass=0; 289 | ud_stream.nrtm=nrtm; 290 | 291 | if(IS_PERSIST_MIRR(ud_stream.ud_mode))upto_last=-1; /* the faster the better */ 292 | else upto_last=0; /* let's start gradually if the backlog is > SBUNCH (1000) serials*/ 293 | 294 | /*+++ main cycle +++*/ 295 | 296 | do { 297 | do_update=CO_get_do_update(); 298 | if(do_update) { 299 | 300 | /* Check connection to the database and try to reconnect */ 301 | if(SQ_ping(ud_stream.db_connection)) { 302 | ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s connection to SQL server timed out - reistablishing", UD_TAG); 303 | } 304 | 305 | /* get current serial */ 306 | nrtm->current_serial=PM_get_current_serial(ud_stream.db_connection); 307 | 308 | if(nrtm->current_serial == -1) { 309 | ER_perror(FAC_UD, UD_SQL, "cannot obtain current serial: %ld", nrtm->current_serial); 310 | die; 311 | } 312 | 313 | ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s connecting to NRTM server [%s:%d] (current serial=%ld)", 314 | UD_TAG, nrtm->server, ntohs(nrtm->port), nrtm->current_serial); 315 | 316 | /* Get file descriptor of the data stream (RPSL format, use mirror reflector to convert if needed)*/ 317 | nrtm_fd=get_NRTM_fd(nrtm, upto_last, source_name); 318 | if (nrtm_fd==-1) { 319 | ER_inf_va(FAC_UD, ASP_UD_OBJ, "%s Cannot open data stream. Trying...", UD_TAG); 320 | SV_sleep(PM_CONNECTION_TIMEOUT); 321 | continue; 322 | } 323 | 324 | 325 | /* make a record for thread accounting */ 326 | TA_add(nrtm_fd, "nrtm_clnt"); 327 | ta_activity = g_string_sized_new(STR_M); 328 | g_string_sprintf(ta_activity, "[%s]%ld->", 329 | source_name, nrtm->current_serial); 330 | TA_setactivity(ta_activity->str); 331 | 332 | 333 | ud_stream.condat.sock = nrtm_fd; 334 | ud_stream.log.num_ok=0; 335 | ud_stream.log.num_failed=0; 336 | 337 | 338 | ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s starting processing stream", UD_TAG); 339 | 340 | /***************** process stream ****************/ 341 | 342 | num_ok=UD_process_stream(&ud_stream); 343 | 344 | /***************** process stream ****************/ 345 | 346 | ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s processing stream finished", UD_TAG); 347 | 348 | /* close the socket of the NRTM stream */ 349 | close(ud_stream.condat.sock); 350 | 351 | 352 | 353 | ER_inf_va(FAC_UD, ASP_UD_OBJ, "%s forwarded to serial:%ld", UD_TAG, (nrtm->current_serial+num_ok)); 354 | 355 | /* set activity for thread record */ 356 | g_string_sprintf(ta_activity, "[%s]->%ld", 357 | source_name, (nrtm->current_serial+num_ok)); 358 | TA_setactivity(ta_activity->str); 359 | g_string_free(ta_activity, TRUE); 360 | 361 | /* if we are NOT in persistent mode */ 362 | if(!IS_PERSIST_MIRR(ud_stream.ud_mode)) { 363 | /* Now we can process serials in normal way (upto LAST)*/ 364 | if(num_ok==0) upto_last=1; 365 | /* get delay */ 366 | nrtm_delay=ca_get_srcnrtmdelay(source_hdl); 367 | } else 368 | /* we need to delay the next attempt not to have a birst of requests */ 369 | nrtm_delay=TIMEOUT; 370 | /* sleep the delay seconds or untill the shutdown requested */ 371 | SV_sleep(nrtm_delay); 372 | 373 | } /* if do_updates */ 374 | else SV_sleep(TIMEOUT); 375 | 376 | 377 | TA_delete(); 378 | 379 | } while((do_server=CO_get_do_server())); /* main cycle */ 380 | 381 | /* fclose(ud_stream.log.logfile);*/ 382 | UT_free(source_name); 383 | /* free data associated with nrtm structure */ 384 | if(nrtm) { 385 | UT_free(nrtm->server); 386 | UT_free(nrtm); 387 | } 388 | 389 | /* That's all. Close connection to the DB */ 390 | SQ_close_connection(ud_stream.db_connection); 391 | UT_free(db_host); 392 | UT_free(db_name); 393 | UT_free(db_user); 394 | UT_free(db_passwd); 395 | 396 | ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s NRTM client stopped", UD_TAG); 397 | } /* UD_do_nrtm() */ 398 | 399 | /************************************************************ 400 | * void UD_do_updates() * 401 | * * 402 | * Processes updates * 403 | * * 404 | * It cycles accepting connections and processing them * 405 | * (interactive server). This assures that there is only * 406 | * one write thread per database/source. * 407 | * * 408 | ************************************************************/ 409 | 410 | void UD_do_updates(void *arg) 411 | { 412 | int source = (int)arg; 413 | int listening_socket = SV_update_sock[source]; 414 | int connected_socket; 415 | UD_stream_t ud_stream; 416 | int do_update=1; 417 | int num_ok; 418 | ca_dbSource_t *source_hdl = ca_get_SourceHandleByPosition(source); 419 | char *db_host, *db_name, *db_user, *db_passwd; 420 | int db_port; 421 | ip_addr_t address; 422 | char *source_name; 423 | struct pollfd pfd[2]; 424 | 425 | source_name = ca_get_srcname(source_hdl); 426 | 427 | { /* set up the lohgging path */ 428 | /* get source we are going to update */ 429 | int res; 430 | char *er_ud_def = ca_get_er_ud_def; /* something like 'RIPUPDLOG basename' */ 431 | GString *er_def; 432 | char *erret = NULL; 433 | 434 | 435 | er_def = g_string_sized_new(256); 436 | g_string_sprintf(er_def, "%s %s", er_ud_def, source_name); 437 | if( (res = ER_macro_spec(er_def->str, &erret)) != 0 ) { 438 | fputs(erret, stderr); 439 | die; 440 | /* or some other error handling */ 441 | } 442 | UT_free(erret); /* the response is allocated and must be freed */ 443 | g_string_free(er_def, TRUE); 444 | UT_free(er_ud_def); 445 | } 446 | 447 | /* load the dictionary */ 448 | rpsl_load_dictionary(RPSL_DICT_CORE); 449 | 450 | 451 | /* get mode of operation: protected/unprotected (dummy) */ 452 | memset(&ud_stream, 0, sizeof(ud_stream)); 453 | ud_stream.source_hdl=source_hdl; 454 | ud_stream.ud_mode=ca_get_srcmode(source_hdl); 455 | 456 | fprintf(stderr, "Mode of operation:\n"); 457 | if(IS_DUMMY_ALLOWED(ud_stream.ud_mode))fprintf(stderr, "* dummy allowed\n"); 458 | else fprintf(stderr, "* dummy not allowed\n"); 459 | if(IS_UPDATE(ud_stream.ud_mode))fprintf(stderr, "* DBupdate\n"); 460 | else fprintf(stderr, "* NRTM\n"); 461 | if(IS_STANDALONE(ud_stream.ud_mode))fprintf(stderr, "* running standalone\n"); 462 | else fprintf(stderr, "* running as a server\n"); 463 | 464 | 465 | /* get the database */ 466 | db_host = ca_get_srcdbmachine(source_hdl); 467 | db_port = ca_get_srcdbport(source_hdl); 468 | db_name = ca_get_srcdbname(source_hdl); 469 | db_user = ca_get_srcdbuser(source_hdl); 470 | db_passwd = ca_get_srcdbpassword(source_hdl); 471 | 472 | /* Connect to the database */ 473 | ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s making SQL connection to %s@%s ...", UD_TAG, db_name, db_host); 474 | ud_stream.db_connection=SQ_get_connection(db_host, db_port, db_name, db_user, db_passwd); 475 | 476 | if(! ud_stream.db_connection) { 477 | ER_perror(FAC_UD, UD_SQL, "no connection to SQL server\n"); 478 | die; 479 | } 480 | 481 | 482 | ud_stream.condat.rd_timeout.tv_sec=STREAM_TIMEOUT; 483 | ud_stream.num_skip=0; 484 | ud_stream.load_pass=0; 485 | ud_stream.nrtm=NULL; 486 | 487 | /* set up poll structure */ 488 | pfd[0].fd = listening_socket; 489 | pfd[0].events = POLLIN; 490 | pfd[1].fd = SV_shutdown_recv_fd; 491 | pfd[1].events = POLLIN; 492 | 493 | /*+++ main cycle +++*/ 494 | 495 | do { /* be alive while do_server is 1. do_server is turned off by SIGINT */ 496 | 497 | /* make a record for thread accounting */ 498 | TA_add(listening_socket, "update"); 499 | TA_setactivity("waiting"); 500 | 501 | /* check for input */ 502 | if (poll(pfd, 2, -1) == -1) { 503 | ER_perror(FAC_SV, 1, "UD_do_updates got error %d on poll; %s", 504 | errno, strerror(errno)); 505 | continue; 506 | } 507 | 508 | /* shutdown */ 509 | if (pfd[1].revents != 0) break; 510 | 511 | /* accept connection */ 512 | connected_socket = SK_accept_connection(listening_socket); 513 | if(connected_socket==-1) continue; 514 | 515 | /* check if the client is authorised to update */ 516 | SK_getpeerip(connected_socket, &address); 517 | if(!AA_can_ripupdate(&address, source_name)){ 518 | char *hostaddress; 519 | sk_conn_st condat; 520 | char buff[STR_L]; 521 | 522 | memset( &condat, 0, sizeof(sk_conn_st)); 523 | condat.wr_timeout.tv_sec=STREAM_TIMEOUT; 524 | condat.sock = connected_socket; 525 | SK_getpeerip(connected_socket, &(condat.rIP)); 526 | memcpy( &(condat.eIP), &(condat.rIP), sizeof(ip_addr_t)); 527 | hostaddress = SK_getpeername(connected_socket); 528 | condat.ip = hostaddress; 529 | 530 | ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "[%s] -- Not authorized to update the source %s", hostaddress, source_name); 531 | sprintf(buff, "\n%%ERROR:406: not authorized to update the database\n\n\n"); 532 | SK_cd_puts(&condat, buff); 533 | SK_cd_close(&(condat)); 534 | 535 | UT_free(hostaddress); 536 | /* start the next loop */ 537 | continue; 538 | } 539 | 540 | /* make a record for thread accounting */ 541 | TA_delete(); /* Delete 'waiting' record */ 542 | TA_add(connected_socket, "update"); 543 | 544 | 545 | ud_stream.condat.sock = connected_socket; 546 | ud_stream.condat.rtc = 0; 547 | 548 | 549 | ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s Connection accepted...", UD_TAG); 550 | 551 | ud_stream.log.num_ok=0; 552 | ud_stream.log.num_failed=0; 553 | 554 | 555 | while((do_update=CO_get_do_update())!=1) { 556 | TA_setactivity("suspended"); 557 | /* if shutdown was requested - break */ 558 | if(SV_sleep(3*TIME_SLICE)) break; 559 | } 560 | 561 | if(do_update) { 562 | /* Check connection to the database and try to reconnect*/ 563 | if(SQ_ping(ud_stream.db_connection)) { 564 | ER_perror(FAC_UD, UD_SQL, "%s", SQ_error(ud_stream.db_connection)); 565 | die; 566 | } 567 | 568 | ER_dbg_va(FAC_UD, ASP_UD_UPDLOG, "%s starting processing object", UD_TAG); 569 | 570 | /***************** process stream ****************/ 571 | 572 | num_ok=UD_process_stream(&ud_stream); 573 | 574 | /***************** process stream ****************/ 575 | 576 | ER_dbg_va(FAC_UD, ASP_UD_OBJ, "%s processing object finished", UD_TAG); 577 | 578 | /* close the socket of the NRTM stream */ 579 | close(ud_stream.condat.sock); 580 | 581 | } /* if do_update*/ 582 | 583 | 584 | TA_delete(); 585 | 586 | } while (CO_get_do_server()); /* main cycle */ 587 | 588 | /* fclose(ud_stream.log.logfile); */ 589 | /* That's all. Close connection to the DB */ 590 | SQ_close_connection(ud_stream.db_connection); 591 | UT_free(db_host); 592 | UT_free(db_name); 593 | UT_free(db_user); 594 | UT_free(db_passwd); 595 | UT_free(source_name); 596 | 597 | 598 | ER_inf_va(FAC_UD, ASP_UD_UPDLOG, "%s update server stopped", UD_TAG); 599 | } /* UD_do_update() */ 600 | 601 | 602 | 603 |