static ErrorObj* ldm_clnt_nullproc(CLIENT* const clnt) { struct timeval timeout; ErrorObj* error; log_assert(NULL != clnt); timeout.tv_sec = 25; /* RPC default */ timeout.tv_usec = 0; if (clnt_call(clnt, NULLPROC, xdr_void, NULL, xdr_void, NULL, timeout) == 0) { error = NULL; } else { struct rpc_err rpcErr; clnt_geterr(clnt, &rpcErr); error = ERR_NEW(rpcErr.re_status, NULL, clnt_errmsg(clnt)); } return error; }
/* * Returns the LDM proxy status for a given client failure. Logs the failure. * * Arguments: * proxy The LDM proxy data-structure. * name The name of the failed message or NULL. * info Metadata on the data-product that couldn't be sent or * NULL. * Returns: * 0 Success. * LP_TIMEDOUT The failure was due to an RPC timeout. "log_start()" * called iff "name" isn't NULL. * LP_RPC_ERROR RPC error. "log_start()" called iff "name" isn't NULL. */ static LdmProxyStatus getStatus( LdmProxy* const proxy, const char* const name, prod_info* const info) { LdmProxyStatus status; struct rpc_err rpcErr; clnt_geterr(proxy->clnt, &rpcErr); if (0 == rpcErr.re_status) { status = 0; } else { if (NULL != name) { LOG_START3("%s failure to host \"%s\": %s", name, proxy->host, clnt_errmsg(proxy->clnt)); if (NULL != info) { LOG_ADD1("Couldn't send product: %s", s_prod_info(NULL, 0, info, ulogIsDebug())); } } status = RPC_TIMEDOUT == rpcErr.re_status ? LP_TIMEDOUT : LP_RPC_ERROR; } return status; }
/* * Send a product from file-descriptor to clnt using LDM-6 protocol. */ static void send_product_6(CLIENT *clnt, int fd, prod_info *infop) { unsigned size = infop->sz; if (size <= max_hereis) { /* * The file is small enough to be sent in a single HEREIS message. */ void* buf = (char*)malloc(size); udebug("Sending file via HEREIS"); if (NULL == buf) { serror("Couldn't allocate %u bytes for product data", size); } else { ssize_t nread = read(fd, buf, size); if(nread != size) { serror("Couldn't read %u bytes of data", size); } else { product product; product.info = *infop; product.data = buf; if (NULL == hereis_6(&product, clnt)) { uerror("%s: HEREIS_6 failure: %s", remote, clnt_errmsg(clnt)); } } free(buf); } } else { /* * The file is so large that it must be sent via COMINGSOON/BLKDATA * messages. */ comingsoon_reply_t* reply; comingsoon_args soonArg; udebug("Sending file via COMINGSOON/BLKDATA"); soonArg.infop = infop; soonArg.pktsz = size; reply = comingsoon_6(&soonArg, clnt); if (NULL == reply) { uerror("%s: COMINGSOON_6 failure: %s", remote, clnt_errmsg(clnt)); } else { if (DONT_SEND == *reply) { if (ulogIsVerbose() || ulogIsDebug()) uinfo("Downstream LDM says don't send: %s", s_prod_info(NULL, 0, infop, ulogIsDebug())); } else if (0 != *reply) { uwarn("Unexpected reply (%s) from downstream LDM: %s", s_prod_info(NULL, 0, infop, ulogIsDebug())); } else { void* buf = (char*)malloc(size); if (NULL == buf) { serror("Couldn't allocate %u bytes for product data", size); } else { ssize_t nread = read(fd, buf, size); if(nread != size) { serror("Couldn't read %u bytes of data", size); } else { datapkt packet; packet.signaturep = (signaturet*)&infop->signature; packet.pktnum = 0; packet.data.dbuf_len = size; packet.data.dbuf_val = buf; if (NULL == blkdata_6(&packet, clnt)) { uerror("%s: BLKDATA_6 failure: %s", remote, clnt_errmsg(clnt)); } } free(buf); } } } } }
static int ldmsend(CLIENT *clnt, prod_class_t* clssp, char* origin, int seq_start, int nfiles, char* filenames[]) { int status = 0; char *filename; int fd; struct stat statb; prod_info info; MD5_CTX *md5ctxp = NULL; /* * Allocate an MD5 context */ md5ctxp = new_MD5_CTX(); if(md5ctxp == NULL) { status = errno; serror("new_md5_CTX failed"); return status; } status = (*hiya)(clnt, &clssp); if(status != 0) return status; /* These members are constant over the loop. */ info.origin = origin; info.feedtype = clssp->psa.psa_val->feedtype; for( info.seqno = seq_start; exitIfDone(1) && nfiles > 0; filenames++, nfiles--, info.seqno++) { filename = *filenames; info.ident = filename; /* * ?? This could be the creation time of the file. */ (void) set_timestamp(&info.arrival); /* * Checks 'arrival', 'feedtype', and 'ident' * against what the other guy has said he wants. */ if(!prodInClass(clssp, &info)) { uinfo("%s doesn't want %s", remote, filename); continue; } fd = open(filename, O_RDONLY, 0); if(fd == -1) { serror("open: %s", filename); continue; } if( fstat(fd, &statb) == -1) { serror("fstat: %s", filename); (void) close(fd); continue; } uinfo("Sending %s, %d bytes", filename, statb.st_size); /* These members, and seqno, vary over the loop. */ if(fd_md5(md5ctxp, fd, statb.st_size, info.signature) != 0) { (void) close(fd); continue; } if(lseek(fd, 0, SEEK_SET) == (off_t)-1) { serror("rewind: %s", filename); (void) close(fd); continue; } (void)exitIfDone(1); info.sz = (u_int)statb.st_size; (*send_product)(clnt, fd, &info); (void) close(fd); } if (exitIfDone(1) && NULL != nullproc && NULL == (*nullproc)(NULL, clnt)) { uerror("%s: NULLPROC failure: %s", remote, clnt_errmsg(clnt)); status = 1; } free_MD5_CTX(md5ctxp); return status; }
static int my_hiya_6(CLIENT *clnt, prod_class_t **clsspp) { static hiya_reply_t* reply; int error; reply = hiya_6(*clsspp, clnt); if (NULL == reply) { uerror("%s: HIYA_6 failure: %s", remote, clnt_errmsg(clnt)); error = ECONNABORTED; } else { switch (reply->code) { case OK: max_hereis = reply->hiya_reply_t_u.max_hereis; error = 0; break; case SHUTTING_DOWN: uerror("%s: LDM shutting down", remote); error = ECONNABORTED; break; case BADPATTERN: uerror("%s: Bad product-class pattern", remote); error = ECONNABORTED; break; case DONT_SEND: uerror("%s: LDM says don't send", remote); error = ECONNABORTED; break; case RESEND: uerror("%s: LDM says resend (ain't gonna happen)", remote); error = ECONNABORTED; break; case RESTART: uerror("%s: LDM says restart (ain't gonna happen)", remote); error = ECONNABORTED; break; case REDIRECT: uerror("%s: LDM says redirect (ain't gonna happen)", remote); error = ECONNABORTED; break; case RECLASS: *clsspp = reply->hiya_reply_t_u.feedPar.prod_class; max_hereis = reply->hiya_reply_t_u.feedPar.max_hereis; clss_regcomp(*clsspp); /* N.B. we use the downstream patterns */ unotice("%s: reclass: %s", remote, s_prod_class(NULL, 0, *clsspp)); error = 0; break; } if (!error) udebug("max_hereis = %u", max_hereis); } return error; }