/** * Ensures the existence of a client-side transport on the TCP connection. * * @param[in] xprt Server-side RPC transport. * @retval true Success. * @retval false System error. `log_start()` called. */ static bool up7_ensureClientTransport( struct SVCXPRT* const xprt) { bool status; if (NULL == clnt) { /* * Create a client-side RPC transport on the TCP connection. */ do { clnt = clnttcp_create(&xprt->xp_raddr, LDMPROG, SEVEN, &xprt->xp_sock, MAX_RPC_BUF_NEEDED, 0); /* TODO: adjust sending buffer size in above */ } while (clnt == NULL && rpc_createerr.cf_stat == RPC_TIMEDOUT); if (clnt == NULL ) { LOG_START2("Couldn't create client-side transport to downstream LDM-7 on " "%s%s", hostbyaddr(&xprt->xp_raddr), clnt_spcreateerror("")); status = false; } else { status = true; } } return status; }
/* * Sends a data-product to an LDM using the LDM-5 messages COMINGSOON and * BLOCKDATA. * * Arguments: * proxy Pointer to the LDM proxy data-structure. * info Pointer to the data-product's metadata. * datap Pointer to the data-product's data. * Returns: * 0 Success. * LP_UNWANTED Data-product was unwanted. * LP_TIMEDOUT The RPC call timed-out. "log_start()" called. * LP_RPC_ERROR RPC error. "log_start()" called. * LP_LDM_ERROR LDM error. "log_start()" called. */ static LdmProxyStatus my_csbd_5( LdmProxy* const proxy, product* const product) { CLIENT* const clnt = proxy->clnt; LdmProxyStatus status = 0; /* success */ ldm_replyt reply; prod_info* const info = &product->info; memset(&reply, 0, sizeof(ldm_replyt)); status = my_comingsoon_5(proxy, info, DBUFMAX, &reply); if (0 == status) { if (reply.code != OK) { if (reply.code == DONT_SEND) { status = LP_UNWANTED; } else { LOG_START2("send_5: %s: %s", info->ident, s_ldm_errt(reply.code)); status = LP_LDM_ERROR; } } else { size_t unsent = info->sz; char* data = product->data; datapkt pkt; pkt.signaturep = &info->signature; pkt.pktnum = 0; while (unsent > 0) { size_t nsend = DBUFMAX < unsent ? DBUFMAX : unsent; pkt.data.dbuf_len = (u_int)nsend; pkt.data.dbuf_val = data; status = my_blkdata_5(proxy, &pkt, &reply); if (0 != status) { getStatus(proxy, "BLOCKDATA_5", info); break; } else if (reply.code != OK) { LOG_START1("Unexpected reply from LDM: %s", s_ldm_errt(reply.code)); status = LP_LDM_ERROR; break; } pkt.pktnum++; data += nsend; unsent -= nsend; } } /* reply.code == OK */ } /* OK COMINGSOON */ return status; }
/** * Notifies the LDM of the class of data-products that will be sent via LDM-5 * protocols. * * Arguments: * proxy Pointer to the LDM proxy data-structure. * offer Pointer to the data-product class structure which will * be offered to the LDM. * want Pointer to a pointer to a data-product class structure. * "*want" will be set the data-product class structure * that the LDM wants. The client should call * "free_prod_class(*want)" when the product-class is no * longer needed. * Returns: * 0 Success. "*clsspp" might be modified. * LP_TIMEDOUT The RPC call timed-out. "log_start()" called. * LP_RPC_ERROR RPC error. "log_start()" called. * LP_LDM_ERROR LDM error. "log_start()" called. */ static LdmProxyStatus my_hiya_5( LdmProxy* const proxy, prod_class_t* const offer, prod_class_t** const want) { static ldm_replyt reply; enum clnt_stat rpc_stat; CLIENT* const clnt = proxy->clnt; memset(&reply, 0, sizeof(ldm_replyt)); rpc_stat = clnt_call(clnt, HIYA, xdr_prod_class, (caddr_t)offer, xdr_ldm_replyt, (caddr_t)&reply, proxy->rpcTimeout); if (rpc_stat != RPC_SUCCESS) { return getStatus(proxy, "HIYA_5", NULL); } switch (reply.code) { case OK: *want = (prod_class_t*)PQ_CLASS_ALL; break; case SHUTTING_DOWN: LOG_START1("%s is shutting down", proxy->host); return LP_LDM_ERROR; case DONT_SEND: case RESTART: case REDIRECT: /* TODO */ default: LOG_START2("%s: Unexpected reply from LDM: %s", proxy->host, s_ldm_errt(reply.code)); return LP_LDM_ERROR; case RECLASS: *want = reply.ldm_replyt_u.newclssp; clss_regcomp(*want); /* N.B. we use the downstream patterns */ /* Use of "buf" added to prevent SIGSEGV on 64-bit RHEL 6 */ (void)s_prod_class(buf, sizeof(buf)-1, *want); unotice("%s: reclass: %s", proxy->host, buf); break; } return 0; }
/** * Returns the pathname of the static, system-specific directory * * Returns: * Pointer to the pathname. Might be absolute or relative to the current * working directory. */ const char* getSysConfDirPath(void) { static char sysConfDirPath[PATH_MAX]; if (strlen(sysConfDirPath) == 0) { const char* ldmHome = getLdmHomePath(); static const char subdir[] = "/etc"; if (strlen(ldmHome) + strlen(subdir) >= sizeof(sysConfDirPath)) { LOG_START2("System configuration directory pathname too long: " "\"%s%s\"", ldmHome, subdir); log_log(LOG_ERR); abort(); } (void)strcat(strcpy(sysConfDirPath, ldmHome), subdir); } return sysConfDirPath; }