0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <stdio.h>
0037 #include <stdlib.h>
0038 #include <errno.h>
0039 #include <fcntl.h>
0040
0041 #include <ndrstandard.h>
0042 #include <ndebug.h>
0043 #include <utlist.h>
0044 #include <string.h>
0045 #include <unistd.h>
0046 #include <tperror.h>
0047
0048 #include <atmi.h>
0049 #include "srv_int.h"
0050 #include "userlog.h"
0051 #include <atmi_int.h>
0052 #include <typed_buf.h>
0053 #include <atmi_tls.h>
0054 #include <nstd_int.h>
0055
0056
0057
0058
0059
0060 #define REALLOC_CLOPT_STEP 10
0061 #define REALLOC_CLOPT alloc_args+=REALLOC_CLOPT_STEP; \
0062 if (NULL==argv) \
0063 argv = NDRX_MALLOC(sizeof(char *)*alloc_args); \
0064 else \
0065 argv = NDRX_REALLOC(argv, sizeof(char *)*alloc_args); \
0066 if (NULL==argv) \
0067 {\
0068 int err = errno;\
0069 fprintf(stderr, "%s: failed to realloc %ld bytes: %s\n", __func__, \
0070 (long)sizeof(char *)*alloc_args, strerror(err));\
0071 userlog("%s: failed to realloc %ld bytes: %s\n", __func__, \
0072 (long)sizeof(char *)*alloc_args, strerror(err));\
0073 exit(1);\
0074 }
0075
0076
0077
0078
0079 srv_conf_t G_server_conf={.service_array=NULL};
0080
0081
0082
0083
0084 ndrx_svchash_t *ndrx_G_svchash_skip = NULL;
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 ndrx_svchash_t *ndrx_G_svchash_funcs = NULL;
0095
0096
0097
0098
0099
0100 exprivate ndrx_tpacall_defer_t *M_deferred_tpacalls = NULL;
0101
0102
0103
0104 exprivate int ndrx_tpacall_noservice_hook_defer(char *svc, char *data, long len, long flags);
0105
0106
0107
0108
0109
0110
0111 expublic int ndrx_svchash_add(ndrx_svchash_t **hash, char *svc_nm)
0112 {
0113 int ret = EXSUCCEED;
0114 ndrx_svchash_t *el = NULL;
0115
0116 if (NULL==(el = NDRX_MALLOC(sizeof(ndrx_svchash_t))))
0117 {
0118 NDRX_LOG(log_error, "%s: Failed to malloc: %s",
0119 __func__, strerror(errno));
0120 userlog("%s: Failed to malloc: %s",
0121 __func__, strerror(errno));
0122 EXFAIL_OUT(ret);
0123 }
0124
0125 NDRX_STRCPY_SAFE(el->svc_nm, svc_nm);
0126 EXHASH_ADD_STR( *hash, svc_nm, el);
0127
0128 out:
0129 return ret;
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 expublic int ndrx_svchash_chk(ndrx_svchash_t **hash, char *svc_nm)
0141 {
0142 ndrx_svchash_t *el = NULL;
0143 char tmp[XATMI_SERVICE_NAME_LENGTH+1];
0144 char *p;
0145
0146 NDRX_STRCPY_SAFE(tmp, svc_nm);
0147
0148 p = strchr(tmp, NDRX_SYS_SVC_PFXC);
0149
0150 if (NULL!=p)
0151 {
0152 *p=EXEOS;
0153 }
0154
0155
0156 EXHASH_FIND_STR( *hash, tmp, el);
0157
0158 if (NULL!=el)
0159 {
0160 return EXTRUE;
0161 }
0162
0163 return EXFALSE;
0164 }
0165
0166
0167
0168
0169
0170 expublic void ndrx_svchash_cleanup(ndrx_svchash_t **hash)
0171 {
0172 ndrx_svchash_t *el = NULL, *elt = NULL;
0173
0174 EXHASH_ITER(hh, *hash, el, elt)
0175 {
0176 EXHASH_DEL(*hash, el);
0177 NDRX_FREE(el);
0178 }
0179 }
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193 expublic int ndrx_parse_svc_arg_cmn(char *msg1,
0194 svc_entry_t **root_svc_list, char *arg, int usegrp)
0195 {
0196 char alias_name[XATMI_SERVICE_NAME_LENGTH+1]={EXEOS};
0197 char grpsvc[MAXTIDENT*2]={EXEOS};
0198 char *p;
0199 svc_entry_t *entry=NULL;
0200 char *grparr[3]={NULL, NULL, NULL};
0201 int i;
0202 int len;
0203
0204 NDRX_LOG(log_debug, "Parsing %s entry: [%s]", msg1, arg);
0205
0206 if (NULL!=(p=strchr(arg, ':')))
0207 {
0208 NDRX_LOG(log_debug, "Aliasing requested");
0209
0210 NDRX_STRCPY_SAFE(alias_name, p+1);
0211
0212 *p=EXEOS;
0213 }
0214
0215
0216
0217
0218 p = strtok(arg, ",/");
0219 while (NULL!=p)
0220 {
0221 grparr[0]=p;
0222 if (usegrp && G_atmi_env.rtgrp[0])
0223 {
0224 NDRX_STRCPY_SAFE(grpsvc, p);
0225 NDRX_STRCAT_S(grpsvc, sizeof(grpsvc), NDRX_SYS_SVC_PFX);
0226 NDRX_STRCAT_S(grpsvc, sizeof(grpsvc), G_atmi_env.rtgrp);
0227 grparr[1]=grpsvc;
0228 }
0229 else
0230 {
0231 grparr[1]=NULL;
0232 }
0233
0234 for (i=0; NULL!=grparr[i]; i++)
0235 {
0236 len = strlen(grparr[i]);
0237 if (len>XATMI_SERVICE_NAME_LENGTH)
0238 {
0239 ndrx_TPset_error_fmt(TPEINVAL,
0240 "Invalid service name [%s] too long %d, max allowed %d",
0241 grparr[i], len, XATMI_SERVICE_NAME_LENGTH);
0242 return EXFAIL;
0243 }
0244
0245
0246 if ( (entry = (svc_entry_t*)NDRX_MALLOC(sizeof(svc_entry_t))) == NULL)
0247 {
0248 ndrx_TPset_error_fmt(TPEOS,
0249 "Failed to allocate %d bytes while parsing -s",
0250 sizeof(svc_entry_t));
0251 return EXFAIL;
0252 }
0253
0254 NDRX_STRCPY_SAFE(entry->svc_nm, grparr[i]);
0255 entry->svc_aliasof[0]=EXEOS;
0256
0257 if (EXEOS!=alias_name[0])
0258 {
0259 NDRX_STRCPY_SAFE(entry->svc_aliasof, alias_name);
0260 }
0261
0262
0263
0264
0265 DL_APPEND((*root_svc_list), entry);
0266
0267 NDRX_LOG(log_debug, "%s [%s]:[%s]", msg1, entry->svc_nm, entry->svc_aliasof);
0268 }
0269
0270 p = strtok(NULL, ",/");
0271 }
0272
0273 return EXSUCCEED;
0274 }
0275
0276
0277
0278
0279
0280
0281 expublic int ndrx_parse_svc_arg(char *arg)
0282 {
0283 return ndrx_parse_svc_arg_cmn("-s", &G_server_conf.svc_list, arg, EXTRUE);
0284 }
0285
0286
0287
0288
0289
0290
0291
0292
0293 expublic int ndrx_parse_func_arg(char *arg)
0294 {
0295 return ndrx_parse_svc_arg_cmn("-S", &G_server_conf.funcsvc_list, arg, EXFALSE);
0296 }
0297
0298
0299
0300
0301 expublic long ndrx_xcvt_lookup(char *fn_nm)
0302 {
0303 xbufcvt_entry_t *entry=NULL;
0304
0305 EXHASH_FIND_STR( G_server_conf.xbufcvt_tab, fn_nm, entry);
0306
0307 if (NULL!=entry)
0308 {
0309 return entry->xcvtflags;
0310 }
0311
0312 return 0;
0313 }
0314
0315
0316
0317
0318
0319
0320 int ndrx_parse_xcvt_arg(char *arg)
0321 {
0322 char cvtfunc[XATMI_SERVICE_NAME_LENGTH+1]={EXEOS};
0323 char *p;
0324 xbufcvt_entry_t *entry=NULL;
0325 int ret = EXSUCCEED;
0326 long flags = 0;
0327 NDRX_LOG(log_debug, "Parsing function buffer convert entry: [%s]", arg);
0328
0329 if (NULL!=(p=strchr(arg, ':')))
0330 {
0331
0332 NDRX_STRCPY_SAFE(cvtfunc, p+1);
0333 *p=EXEOS;
0334
0335
0336 if (0==strcmp(cvtfunc, BUF_CVT_INCOMING_JSON2UBF_STR))
0337 {
0338 flags|=SYS_SRV_CVT_JSON2UBF;
0339 }
0340 else if (0==strcmp(cvtfunc, BUF_CVT_INCOMING_UBF2JSON_STR))
0341 {
0342 flags|=SYS_SRV_CVT_UBF2JSON;
0343 }
0344 if (0==strcmp(cvtfunc, BUF_CVT_INCOMING_JSON2VIEW_STR))
0345 {
0346 flags|=SYS_SRV_CVT_JSON2VIEW;
0347 }
0348 else if (0==strcmp(cvtfunc, BUF_CVT_INCOMING_VIEW2JSON_STR))
0349 {
0350 flags|=SYS_SRV_CVT_VIEW2JSON;
0351 }
0352
0353 if (0==flags)
0354 {
0355 NDRX_LOG(log_error, "Invalid automatic buffer conversion function (%s)!",
0356 cvtfunc);
0357 EXFAIL_OUT(ret);
0358 }
0359 }
0360 else
0361 {
0362 NDRX_LOG(log_error, "Invalid argument for -x (%s) missing `:'", arg);
0363 EXFAIL_OUT(ret);
0364 }
0365
0366 p = strtok(arg, ",");
0367 while (NULL!=p)
0368 {
0369
0370 if ( (entry = (xbufcvt_entry_t*)NDRX_MALLOC(sizeof(xbufcvt_entry_t))) == NULL)
0371 {
0372 ndrx_TPset_error_fmt(TPMINVAL, "Failed to allocate %d bytes while parsing -s",
0373 sizeof(svc_entry_t));
0374 return EXFAIL;
0375 }
0376
0377 NDRX_STRCPY_SAFE(entry->fn_nm, p);
0378 entry->xcvtflags = flags;
0379
0380
0381 NDRX_LOG(log_debug, "Added have automatic convert option [%s] "
0382 "for function [%s] (-x)", cvtfunc, entry->fn_nm);
0383
0384 EXHASH_ADD_STR( G_server_conf.xbufcvt_tab, fn_nm, entry );
0385
0386 p = strtok(NULL, ",");
0387 }
0388
0389 out:
0390 return ret;
0391 }
0392
0393
0394
0395
0396
0397 exprivate void configure_outputs(void)
0398 {
0399 FILE *f_stderr = NULL;
0400 FILE *f_stdout = NULL;
0401 int stdout_ok = EXFALSE;
0402 long sync_flags = NDRX_LOG_FSYNCSTDERR;
0403
0404
0405 if (EXEOS!=G_server_conf.std_output[0] &&
0406 NULL!=(f_stdout=NDRX_FOPEN(G_server_conf.std_output, "a")))
0407 {
0408 if (EXSUCCEED!=fcntl(fileno(f_stdout), F_SETFD, FD_CLOEXEC))
0409 {
0410 userlog("WARNING: Failed to set FD_CLOEXEC (1): %s",
0411 strerror(errno));
0412 }
0413
0414 if (EXFAIL==dup2(fileno(f_stdout), STDOUT_FILENO))
0415 {
0416 userlog("%s: Failed to dup2(1): %s", __func__, strerror(errno));
0417 }
0418 else
0419 {
0420 stdout_ok=EXTRUE;
0421 }
0422
0423 if (0==strcmp(G_server_conf.std_output, G_server_conf.err_output))
0424 {
0425 sync_flags |= NDRX_LOG_FSYNCSTDOUT;
0426 }
0427 }
0428 else if (EXEOS!=G_server_conf.std_output[0])
0429 {
0430 userlog("Failed to open stdout file [%s]: %s",
0431 G_server_conf.std_output, strerror(errno));
0432 }
0433
0434
0435
0436 if (EXEOS!=G_server_conf.err_output[0] &&
0437 NULL!=(f_stderr=NDRX_FOPEN(G_server_conf.err_output, "a")))
0438 {
0439
0440 if (EXSUCCEED!=fcntl(fileno(f_stderr), F_SETFD, FD_CLOEXEC))
0441 {
0442 userlog("WARNING: Failed to set FD_CLOEXEC (2): %s",
0443 strerror(errno));
0444 }
0445
0446 if (!stdout_ok)
0447 {
0448 if (EXFAIL==dup2(fileno(f_stderr), STDOUT_FILENO))
0449 {
0450 userlog("%s: Failed to dup2(1): %s", __func__, strerror(errno));
0451 }
0452 else
0453 {
0454 sync_flags |= NDRX_LOG_FSYNCSTDOUT;
0455 }
0456 }
0457
0458 if (EXFAIL==dup2(fileno(f_stderr), STDERR_FILENO))
0459 {
0460 userlog("%s: Failed to dup2(2): %s", __func__, strerror(errno));
0461 }
0462
0463
0464
0465
0466
0467
0468
0469
0470 if (ndrx_debug_is_proc_stderr())
0471 {
0472
0473 if (EXSUCCEED!=tplogconfig(LOG_CODE_UBF|LOG_CODE_NDRX|LOG_CODE_TP, EXFAIL,
0474 NULL, NULL, G_server_conf.err_output))
0475 {
0476 NDRX_LOG(log_debug, "Failed to re-open logger");
0477 }
0478 else
0479 {
0480 ndrx_debug_proc_link_ndrx(sync_flags);
0481 }
0482 }
0483 }
0484 else if (EXEOS!=G_server_conf.err_output[0])
0485 {
0486 userlog("Failed to open error file [%s]: %s", G_server_conf.err_output, strerror(errno));
0487 }
0488
0489 if (NULL!=f_stderr)
0490 {
0491 NDRX_FCLOSE(f_stderr);
0492 }
0493
0494 if (NULL!=f_stdout)
0495 {
0496 NDRX_FCLOSE(f_stdout);
0497 }
0498 }
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509 expublic int ndrx_init(int argc, char** argv)
0510 {
0511 int ret=EXSUCCEED;
0512 int c;
0513 int dbglev;
0514 char *p;
0515 char key[NDRX_MAX_KEY_SIZE]={EXEOS};
0516 char rqaddress[NDRX_MAX_Q_SIZE+1] = "";
0517 char tmp[NDRX_MAX_Q_SIZE+1];
0518 int was_grp_used=EXFALSE;
0519
0520
0521
0522
0523
0524 string_list_t *svcalias=NULL, *svciter;
0525
0526
0527 ATMI_TLS_ENTRY;
0528
0529
0530 memset(&G_server_conf, 0, sizeof(G_server_conf));
0531 G_shutdown_req=EXFALSE;
0532
0533 G_server_conf.advertise_all = 1;
0534 G_server_conf.time_out = EXFAIL;
0535 G_server_conf.mindispatchthreads = 1;
0536 G_server_conf.maxdispatchthreads = 1;
0537
0538
0539 if (EXSUCCEED!=ndrx_load_common_env())
0540 {
0541 NDRX_LOG(log_error, "Failed to load common env");
0542 ret=EXFAIL;
0543 goto out;
0544 }
0545
0546 #ifdef __GNU_LIBRARY__
0547 optind=0;
0548 #else
0549 optind=1;
0550 #endif
0551
0552
0553 while ((c = getopt(argc, argv, "h?:D:i:k:e:R:rs:t:x:Nn:S:g:GBo:--")) != EXFAIL)
0554 {
0555 switch(c)
0556 {
0557 case 'g':
0558
0559
0560 if (EXEOS!=G_atmi_env.rtgrp[0])
0561 {
0562 was_grp_used=EXTRUE;
0563 }
0564
0565 NDRX_STRCPY_SAFE(G_atmi_env.rtgrp, optarg);
0566 NDRX_LOG(log_info, "Routing group %s to [%s]",
0567 (was_grp_used?"cli override":"set"), G_atmi_env.rtgrp);
0568 break;
0569 case 'G':
0570
0571 G_server_conf.ddr_keep_grp=EXTRUE;
0572 NDRX_LOG(log_info, "Keeping DDR group name in service names");
0573 break;
0574 case 'k':
0575
0576 NDRX_STRCPY_SAFE(key, optarg);
0577 break;
0578 case 'R':
0579
0580
0581 if (NDRX_SYS_SVC_PFXC==optarg[0])
0582 {
0583 NDRX_LOG(log_error, "-R request address cannot start with [%c]",
0584 NDRX_SYS_SVC_PFXC);
0585 userlog("-R request address cannot start with [%c]",
0586 NDRX_SYS_SVC_PFXC);
0587 ndrx_TPset_error_fmt(TPEINVAL, "-R request address cannot start with [%c]",
0588 NDRX_SYS_SVC_PFXC);
0589 EXFAIL_OUT(ret);
0590 }
0591
0592 NDRX_STRCPY_SAFE(rqaddress, optarg);
0593 break;
0594
0595 case 's':
0596
0597 if (EXSUCCEED!=ndrx_string_list_add(&svcalias, optarg))
0598 {
0599
0600 NDRX_LOG(log_error, "Failed to populate svcalias list");
0601 EXFAIL_OUT(ret);
0602 }
0603
0604 break;
0605 case 'S':
0606 ret=ndrx_parse_func_arg(optarg);
0607 break;
0608
0609 case 'x':
0610 ret=ndrx_parse_xcvt_arg(optarg);
0611 break;
0612 case 'D':
0613 dbglev = atoi(optarg);
0614 tplogconfig(LOG_FACILITY_NDRX, dbglev, NULL, NULL, NULL);
0615 break;
0616 case 'i':
0617
0618 G_server_conf.srv_id = atoi(optarg);
0619 break;
0620 case 'N':
0621
0622 G_server_conf.advertise_all = 0;
0623 break;
0624 case 'B':
0625
0626
0627
0628 G_server_conf.no_built_advertise = EXTRUE;
0629 break;
0630 case 'n':
0631
0632 if (EXSUCCEED!=ndrx_svchash_add(&ndrx_G_svchash_skip, optarg))
0633 {
0634 ndrx_TPset_error_msg(TPESYSTEM, "Malloc failed");
0635 EXFAIL_OUT(ret);
0636 }
0637 break;
0638 case 'r':
0639
0640 G_server_conf.log_work = 1;
0641 break;
0642 case 'e':
0643 NDRX_STRCPY_SAFE(G_server_conf.err_output, optarg);
0644 break;
0645 case 'o':
0646 NDRX_STRCPY_SAFE(G_server_conf.std_output, optarg);
0647 break;
0648 case 't':
0649
0650
0651
0652 G_server_conf.time_out = atoi(optarg);
0653 break;
0654 case 'h': case '?':
0655 fprintf(stderr, "usage: %s [-D dbglev] -i server_id [-N - do "
0656 "not advertise servers]"
0657 " [-sSERVER:ALIAS] [-sSERVER]\n",
0658 argv[0]);
0659 goto out;
0660 break;
0661
0662 }
0663 }
0664
0665 configure_outputs();
0666
0667
0668 LL_FOREACH(svcalias, svciter)
0669 {
0670 if (EXSUCCEED!=ndrx_parse_svc_arg(svciter->qname))
0671 {
0672 EXFAIL_OUT(ret);
0673 }
0674 }
0675
0676
0677 if (EXFAIL==G_server_conf.time_out)
0678 {
0679
0680 if (NULL!=(p=getenv(CONF_NDRX_TOUT)))
0681 {
0682 G_server_conf.time_out = atoi(p);
0683 }
0684 else
0685 {
0686 ndrx_TPset_error_msg(TPEINVAL, "Error: Missing evn param: NDRX_TOUT, "
0687 "cannot determine default timeout!");
0688 ret=EXFAIL;
0689 goto out;
0690 }
0691 }
0692
0693 NDRX_LOG(log_debug, "Using comms timeout: %d",
0694 G_server_conf.time_out);
0695
0696
0697 if (G_server_conf.srv_id<1)
0698 {
0699 ndrx_TPset_error_msg(TPEINVAL, "Error: server ID (-i) must be >= 1");
0700 ret=EXFAIL;
0701 goto out;
0702 }
0703
0704
0705
0706
0707 p=strrchr(argv[0], '/');
0708 if (NULL!=p)
0709 {
0710 NDRX_STRCPY_SAFE(G_server_conf.binary_name, p+1);
0711 }
0712 else
0713 {
0714 NDRX_STRCPY_SAFE(G_server_conf.binary_name, argv[0]);
0715 }
0716
0717
0718
0719
0720 if (NULL==(p=getenv(CONF_NDRX_QPREFIX)))
0721 {
0722 ndrx_TPset_error_fmt(TPEINVAL, "Env [%s] not set", CONF_NDRX_QPREFIX);
0723 ret=EXFAIL;
0724 goto out;
0725 }
0726 else
0727 {
0728 NDRX_STRCPY_SAFE(G_server_conf.q_prefix, p);
0729 }
0730
0731
0732 if (NULL==(p=getenv(CONF_NDRX_QPREFIX)))
0733 {
0734 ndrx_TPset_error_fmt(TPEINVAL, "Env [%s] not set", CONF_NDRX_QPREFIX);
0735 ret=EXFAIL;
0736 goto out;
0737 }
0738 else
0739 {
0740 NDRX_STRCPY_SAFE(G_server_conf.q_prefix, p);
0741 }
0742
0743 if (NULL!=(p=getenv(CONF_NDRX_MINDISPATCHTHREADS)))
0744 {
0745 G_server_conf.mindispatchthreads = atoi(p);
0746 }
0747
0748 if (NULL!=(p=getenv(CONF_NDRX_MAXDISPATCHTHREADS)))
0749 {
0750 G_server_conf.maxdispatchthreads = atoi(p);
0751 }
0752
0753 if (G_server_conf.maxdispatchthreads < G_server_conf.mindispatchthreads)
0754 {
0755 NDRX_LOG(log_error, "Error ! MAXDISPATCHTHREADS(=%d) < MINDISPATCHTHREADS(=%d)",
0756 G_server_conf.maxdispatchthreads,
0757 G_server_conf.mindispatchthreads
0758 );
0759 userlog("Error ! MAXDISPATCHTHREADS(=%d) < MINDISPATCHTHREADS(=%d)",
0760 G_server_conf.maxdispatchthreads,
0761 G_server_conf.mindispatchthreads);
0762
0763 ndrx_TPset_error_fmt(TPEINVAL, "Error ! MAXDISPATCHTHREADS(=%d) < MINDISPATCHTHREADS(=%d)",
0764 G_server_conf.maxdispatchthreads,
0765 G_server_conf.mindispatchthreads);
0766 EXFAIL_OUT(ret);
0767 }
0768
0769
0770 if (!_tmbuilt_with_thread_option && G_server_conf.maxdispatchthreads > 1)
0771 {
0772 NDRX_LOG(log_error, "Warning ! Server not built for multi-threading, "
0773 "but MINDISPATCHTHREADS=%d MAXDISPATCHTHREADS=%d, falling back to single thread mode",
0774 G_server_conf.mindispatchthreads,
0775 G_server_conf.maxdispatchthreads
0776 );
0777 userlog("Warning ! Server not built for multi-threading, "
0778 "but MINDISPATCHTHREADS=%d MAXDISPATCHTHREADS=%d, falling back to single thread mode",
0779 G_server_conf.mindispatchthreads,
0780 G_server_conf.maxdispatchthreads);
0781 }
0782
0783 if (G_server_conf.mindispatchthreads <=0 )
0784 {
0785 NDRX_LOG(log_error, "Error ! MINDISPATCHTHREADS(=%d) <=0",
0786 G_server_conf.mindispatchthreads);
0787 userlog("Error ! MINDISPATCHTHREADS(=%d) <=0",
0788 G_server_conf.mindispatchthreads);
0789 ndrx_TPset_error_fmt(TPEINVAL, "Error ! MINDISPATCHTHREADS(=%d) <=0",
0790 G_server_conf.mindispatchthreads);
0791 EXFAIL_OUT(ret);
0792 }
0793
0794 if (G_server_conf.maxdispatchthreads <=0)
0795 {
0796 NDRX_LOG(log_error, "Error ! MAXDISPATCHTHREADS(=%d) <=0",
0797 G_server_conf.maxdispatchthreads);
0798 userlog("Error ! MAXDISPATCHTHREADS(=%d) <=0",
0799 G_server_conf.maxdispatchthreads);
0800 ndrx_TPset_error_fmt(TPEINVAL, "Error ! MAXDISPATCHTHREADS(=%d) <=0",
0801 G_server_conf.maxdispatchthreads);
0802 EXFAIL_OUT(ret);
0803 }
0804
0805
0806
0807
0808
0809 if (G_server_conf.maxdispatchthreads > 1 && _tmbuilt_with_thread_option)
0810 {
0811 G_server_conf.is_threaded = EXTRUE;
0812 NDRX_SPIN_INIT_V(G_server_conf.mt_lock);
0813 }
0814
0815 G_srv_id = G_server_conf.srv_id;
0816
0817
0818 G_server_conf.max_events = 1;
0819
0820 #ifdef EX_USE_SYSVQ
0821
0822 if (EXEOS==rqaddress[0])
0823 {
0824
0825 snprintf(rqaddress, sizeof(rqaddress), NDRX_SVR_SVADDR_FMT,
0826 G_server_conf.q_prefix, G_server_conf.binary_name, G_srv_id);
0827
0828 ndrx_epoll_mainq_set(rqaddress);
0829 NDRX_STRCPY_SAFE(G_server_conf.rqaddress, rqaddress);
0830 }
0831 else
0832 {
0833 snprintf(tmp, sizeof(tmp), NDRX_SVR_RQADDR_FMT,
0834 G_server_conf.q_prefix, rqaddress);
0835 ndrx_epoll_mainq_set(tmp);
0836 NDRX_STRCPY_SAFE(G_server_conf.rqaddress, tmp);
0837 }
0838 #endif
0839
0840 out:
0841
0842 ndrx_string_list_free(svcalias);
0843
0844 return ret;
0845 }
0846
0847
0848
0849
0850
0851 exprivate void childsrvuninit(void)
0852 {
0853 NDRX_LOG(log_debug, "Server un-init in forked child thread...");
0854 atmisrv_un_initialize(EXTRUE);
0855 }
0856
0857
0858
0859
0860
0861
0862 exprivate void ndrx_call_tpsvrthrdone(void)
0863 {
0864 if (NULL!=ndrx_G_tpsvrthrdone)
0865 {
0866 ndrx_G_tpsvrthrdone();
0867 }
0868
0869
0870 tpterm();
0871 }
0872
0873
0874
0875
0876
0877
0878
0879 exprivate int ndrx_call_tpsvrthrinit(int argc, char ** argv)
0880 {
0881 int ret = EXSUCCEED;
0882 int init_ok = EXFALSE;
0883
0884
0885 NDRX_LOG(log_info, "Starting new server dispatched thread");
0886 userlog("Starting new server dispatched thread");
0887
0888 if (EXSUCCEED!=tpinit(NULL))
0889 {
0890 EXFAIL_OUT(ret);
0891 }
0892
0893 init_ok = EXTRUE;
0894
0895 G_atmi_tls->pf_tpacall_noservice_hook = &ndrx_tpacall_noservice_hook_defer;
0896
0897 if (NULL!=ndrx_G_tpsvrthrinit
0898 && ndrx_G_tpsvrthrinit(argc, argv) < 0)
0899 {
0900 EXFAIL_OUT(ret);
0901 }
0902
0903
0904 G_atmi_tls->pf_tpacall_noservice_hook = NULL;
0905 out:
0906
0907 if (EXSUCCEED!=ret && init_ok)
0908 {
0909 tpterm();
0910 }
0911
0912 return ret;
0913 }
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926 exprivate int ndrx_tpacall_noservice_hook_defer(char *svc, char *data, long len, long flags)
0927 {
0928 int ret = EXSUCCEED;
0929 svc_entry_fn_t *existing=NULL, eltmp;
0930 ndrx_tpacall_defer_t *call = NULL;
0931 int err;
0932
0933 NDRX_STRCPY_SAFE(eltmp.svc_nm, svc);
0934
0935
0936 ndrx_sv_advertise_lock();
0937
0938 DL_SEARCH(G_server_conf.service_raw_list, existing, &eltmp, ndrx_svc_entry_fn_cmp);
0939
0940
0941 if (!existing)
0942 {
0943
0944 ndrx_TPset_error_fmt(TPENOENT, "%s: Service is not available %s by %s",
0945 __func__, svc, "server_init");
0946 EXFAIL_OUT(ret);
0947 }
0948
0949
0950 call = NDRX_FPMALLOC(sizeof(ndrx_tpacall_defer_t), 0);
0951
0952 if (NULL==call)
0953 {
0954 err=errno;
0955 NDRX_LOG(log_error, "Failed to malloc %d bytes: %s", tpstrerror(err));
0956 ndrx_TPset_error_fmt(TPEOS, "%s: Service is not available %s by %s",
0957 __func__, svc, "server_init");
0958 EXFAIL_OUT(ret);
0959
0960 }
0961
0962 call->flags=flags;
0963 call->len=len;
0964 NDRX_STRCPY_SAFE(call->svcnm, svc);
0965
0966 if (NULL!=data)
0967 {
0968 char type[16+1]={EXEOS};
0969 char subtype[XATMI_SUBTYPE_LEN]={EXEOS};
0970 long xatmi_len;
0971
0972
0973 xatmi_len=tptypes(data, type, subtype);
0974
0975 if (EXFAIL==xatmi_len)
0976 {
0977 NDRX_LOG(log_error, "Failed to get data type for defered tpacall buffer");
0978 EXFAIL_OUT(ret);
0979 }
0980
0981 call->data = tpalloc(type, subtype, xatmi_len);
0982
0983 if (NULL==call->data)
0984 {
0985 NDRX_LOG(log_error, "Failed to alloc defered msg data buf");
0986 EXFAIL_OUT(ret);
0987 }
0988
0989
0990
0991
0992 memcpy(call->data, data, xatmi_len);
0993
0994 }
0995 else
0996 {
0997 call->data = NULL;
0998 }
0999
1000
1001 NDRX_LOG(log_info, "Enqueue deferred tpacall svcnm=[%s] org_buf=%p "
1002 "buf=%p (copy) len=%ld flags=%ld",
1003 call->svcnm, data, call->data, call->len, call->flags);
1004
1005 DL_APPEND(M_deferred_tpacalls, call);
1006
1007 out:
1008
1009 if (EXSUCCEED!=ret)
1010 {
1011
1012 if (NULL!=call)
1013 {
1014 if (NULL!=call->data)
1015 {
1016 tpfree(call->data);
1017 }
1018
1019 NDRX_FPFREE(call);
1020 }
1021 }
1022
1023 ndrx_sv_advertise_unlock();
1024
1025 return ret;
1026 }
1027
1028
1029
1030
1031
1032
1033 exprivate int ndrx_tpacall_noservice_hook_send(void)
1034 {
1035 int ret=EXSUCCEED;
1036 ndrx_tpacall_defer_t *el, *elt;
1037
1038 DL_FOREACH_SAFE(M_deferred_tpacalls, el, elt)
1039 {
1040 NDRX_LOG(log_info, "Performing deferred tpacall svcnm=[%s] buf=%p len=%ld flags=%ld",
1041 el->svcnm, el->data, el->len, el->flags);
1042
1043 if (EXFAIL==tpacall(el->svcnm, el->data, el->len, el->flags))
1044 {
1045 NDRX_LOG(log_info, "Deferred tpacall failed (svcnm=[%s] buf=%p len=%ld flags=%ld): %s",
1046 el->svcnm, el->data, el->len, el->flags, tpstrerror(tperrno));
1047 userlog("Deferred tpacall failed (svcnm=[%s] buf=%p len=%ld flags=%ld): %s",
1048 el->svcnm, el->data, el->len, el->flags, tpstrerror(tperrno));
1049 EXFAIL_OUT(ret);
1050 }
1051
1052 if (NULL!=el->data)
1053 {
1054 tpfree(el->data);
1055 }
1056
1057 DL_DELETE(M_deferred_tpacalls, el);
1058 NDRX_FPFREE(el);
1059 }
1060
1061 out:
1062
1063
1064 if (EXSUCCEED!=ret)
1065 {
1066 DL_FOREACH_SAFE(M_deferred_tpacalls, el, elt)
1067 {
1068 if (NULL!=el->data)
1069 {
1070 tpfree(el->data);
1071 }
1072
1073 DL_DELETE(M_deferred_tpacalls, el);
1074 NDRX_FPFREE(el);
1075 }
1076 }
1077
1078 return ret;
1079 }
1080
1081
1082
1083
1084
1085
1086
1087 int ndrx_main(int argc, char** argv)
1088 {
1089 int ret=EXSUCCEED;
1090 char *env_procname;
1091 char *env_clopt = NULL;
1092
1093
1094
1095 if (argc<=1 || NULL==argv)
1096 {
1097 char *p;
1098 char *tok;
1099 int alloc_args = 0;
1100
1101
1102
1103
1104
1105
1106 env_procname = (char *)EX_PROGNAME;
1107
1108 p = getenv(CONF_NDRX_SVCLOPT);
1109
1110 if (NULL==p)
1111 {
1112 NDRX_LOG(log_error, "%s: argc/argv are empty and %s/%s env vars not "
1113 "present - missing server params", __func__,
1114 CONF_NDRX_SVPROCNAME, CONF_NDRX_SVCLOPT);
1115 userlog("%s: argc/argv are empty and %s/%s env vars not "
1116 "present - missing server params", __func__,
1117 CONF_NDRX_SVPROCNAME, CONF_NDRX_SVCLOPT);
1118 ndrx_TPset_error_fmt(TPEINVAL, "%s: argc/argv are empty and %s/%s env vars not "
1119 "present - missing server params", __func__,
1120 CONF_NDRX_SVPROCNAME, CONF_NDRX_SVCLOPT);
1121 EXFAIL_OUT(ret);
1122 }
1123
1124 if (NULL==(env_clopt=NDRX_STRDUP(p)))
1125 {
1126 int err=errno;
1127
1128 NDRX_LOG(log_error, "%s: Failed to strdup: %s", __func__,
1129 strerror(err));
1130 userlog("%s: Failed to strdup: %s", __func__,
1131 strerror(err));
1132 ndrx_TPset_error_fmt(TPEOS, "%s: Failed to strdup: %s", __func__,
1133 strerror(err));
1134 EXFAIL_OUT(ret);
1135 }
1136
1137
1138 argv = NULL;
1139 REALLOC_CLOPT;
1140
1141 argc=1;
1142 argv[0] = env_procname;
1143
1144 tok = ndrx_strtokblk(env_clopt, NDRX_CMDLINE_SEP, NDRX_CMDLINE_QUOTES);
1145 while (NULL!=tok)
1146 {
1147 argc++;
1148
1149 if (argc > alloc_args)
1150 {
1151 REALLOC_CLOPT;
1152 }
1153
1154 argv[argc-1] = tok;
1155
1156
1157 tok = ndrx_strtokblk(NULL, NDRX_CMDLINE_SEP, NDRX_CMDLINE_QUOTES);
1158 }
1159
1160 }
1161
1162
1163 if (EXSUCCEED!=ndrx_init(argc, argv))
1164 {
1165 NDRX_LOG(log_error, "ndrx_init() fail");
1166 userlog("ndrx_init() fail");
1167 EXFAIL_OUT(ret);
1168 }
1169
1170
1171
1172
1173 if (EXSUCCEED!=ndrx_epoll_sys_init())
1174 {
1175 NDRX_LOG(log_error, "ndrx_epoll_sys_init() fail");
1176 userlog("ndrx_epoll_sys_init() fail");
1177 EXFAIL_OUT(ret);
1178 }
1179
1180
1181
1182
1183
1184 if (NULL!=ndrx_G_tpsvrinit_sys && EXSUCCEED!=ndrx_G_tpsvrinit_sys(argc, argv))
1185 {
1186 NDRX_LOG(log_error, "tpsvrinit_sys() fail");
1187 userlog("tpsvrinit_sys() fail");
1188 EXFAIL_OUT(ret);
1189 }
1190
1191
1192
1193 G_atmi_tls->pf_tpacall_noservice_hook=&ndrx_tpacall_noservice_hook_defer;
1194
1195
1196
1197
1198 if (NULL!=G_tpsvrinit__ && EXSUCCEED!=G_tpsvrinit__(argc, argv))
1199 {
1200 NDRX_LOG(log_error, "tpsvrinit() fail");
1201 userlog("tpsvrinit() fail");
1202 EXFAIL_OUT(ret);
1203 }
1204
1205
1206 G_atmi_tls->pf_tpacall_noservice_hook = NULL;
1207
1208
1209
1210 if (EXSUCCEED!=atmisrv_initialise_atmi_library())
1211 {
1212 NDRX_LOG(log_error, "initialise_atmi_library() fail");
1213 userlog("initialise_atmi_library() fail");
1214 EXFAIL_OUT(ret);
1215 }
1216
1217
1218
1219
1220
1221
1222 if (G_server_conf.is_threaded)
1223 {
1224 NDRX_LOG(log_debug, "About to init dispatch thread pool");
1225 G_server_conf.dispthreads = ndrx_thpool_init(G_server_conf.mindispatchthreads,
1226 &ret, ndrx_call_tpsvrthrinit, ndrx_call_tpsvrthrdone, argc, argv);
1227
1228 if (EXSUCCEED!=ret)
1229 {
1230 NDRX_LOG(log_error, "Thread pool init failure");
1231 EXFAIL_OUT(ret);
1232 }
1233 }
1234
1235
1236
1237
1238 if (EXSUCCEED!=atmisrv_build_advertise_list())
1239 {
1240 NDRX_LOG(log_error, "tpsvrinit() fail");
1241 userlog("tpsvrinit() fail");
1242 EXFAIL_OUT(ret);
1243 }
1244
1245
1246
1247
1248 if (EXSUCCEED!=sv_open_queue())
1249 {
1250 NDRX_LOG(log_error, "sv_open_queue() fail");
1251 userlog("sv_open_queue() fail");
1252 EXFAIL_OUT(ret);
1253 }
1254
1255
1256 if (EXSUCCEED!=tp_internal_init_upd_replyq(G_server_conf.service_array[1]->q_descr,
1257 G_server_conf.service_array[1]->listen_q))
1258 {
1259 NDRX_LOG(log_error, "tp_internal_init_upd_replyq() fail");
1260 userlog("tp_internal_init_upd_replyq() fail");
1261 EXFAIL_OUT(ret);
1262 }
1263
1264
1265 if (NULL!=G_atmi_env.test_advertise_crash)
1266 {
1267 G_atmi_env.test_advertise_crash();
1268 }
1269
1270
1271
1272 report_to_ndrxd();
1273
1274 if (EXSUCCEED!=ndrx_atfork(NULL, NULL, childsrvuninit))
1275 {
1276 NDRX_LOG(log_error, "Failed to add atfork handler!");
1277 userlog("Failed to add atfork handler!");
1278 EXFAIL_OUT(ret);
1279 }
1280
1281
1282
1283
1284 if (EXSUCCEED!=(ret=ndrx_tpacall_noservice_hook_send()))
1285 {
1286 NDRX_LOG(log_error, "ndrx_tpacall_noservice_hook_send() fail %d", ret);
1287 userlog("ndrx_tpacall_noservice_hook_send() fail %d", ret);
1288 goto out;
1289 }
1290
1291
1292 if (EXSUCCEED!=(ret=sv_wait_for_request()))
1293 {
1294 NDRX_LOG(log_error, "sv_wait_for_request() fail %d", ret);
1295 userlog("sv_wait_for_request() fail %d", ret);
1296 goto out;
1297 }
1298
1299 out:
1300
1301
1302 if (NULL!=G_tpsvrdone__)
1303 {
1304 G_tpsvrdone__();
1305 }
1306
1307
1308 if (NULL!=G_server_conf.dispthreads)
1309 {
1310 ndrx_thpool_destroy(G_server_conf.dispthreads);
1311 }
1312
1313
1314
1315
1316 ndrx_epoll_sys_uninit();
1317
1318 atmisrv_un_initialize(EXFALSE);
1319
1320
1321
1322 if (EXSUCCEED!=ret)
1323 {
1324 printf("Error: %s\n", tpstrerror(tperrno));
1325 }
1326
1327 fprintf(stderr, "Server exit: %d, id: %d\n", ret, G_srv_id);
1328
1329 if (NULL!=env_clopt)
1330 {
1331 NDRX_FREE(env_clopt);
1332
1333
1334 if (NULL!=argv)
1335 {
1336 NDRX_FREE(argv);
1337 }
1338 }
1339
1340 return ret;
1341 }
1342
1343