Mercurial > notdcc
view dcclib/aop.c @ 2:f6716cb00029
Replace buggy stuff in deb dir, never make phone calls while working
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 14:29:12 +0100 |
parents | c7f6b056b673 |
children |
line wrap: on
line source
/* Distributed Checksum Clearinghouse * * ask for and administrative operation * * Copyright (c) 2008 by Rhyolite Software, LLC * * This agreement is not applicable to any entity which sells anti-spam * solutions to others or provides an anti-spam solution as part of a * security solution sold to other entities, or to a private network * which employs the DCC or uses data provided by operation of the DCC * but does not provide corresponding data to other users. * * Permission to use, copy, modify, and distribute this software without * changes for any purpose with or without fee is hereby granted, provided * that the above copyright notice and this permission notice appear in all * copies and any distributed versions or copies are either unchanged * or not called anything similar to "DCC" or "Distributed Checksum * Clearinghouse". * * Parties not eligible to receive a license under this agreement can * obtain a commercial license to use DCC by contacting Rhyolite Software * at sales@rhyolite.com. * * A commercial license would be for Distributed Checksum and Reputation * Clearinghouse software. That software includes additional features. This * free license for Distributed ChecksumClearinghouse Software does not in any * way grant permision to use Distributed Checksum and Reputation Clearinghouse * software * * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * * Rhyolite Software DCC 1.3.103-1.39 $Revision$ */ #include "dcc_clnt.h" /* ask for an administrative operation */ DCC_OPS /* DCC_OP_INVALID=failed, else result */ dcc_aop(DCC_EMSG emsg, /* result if DCC_OP_ERROR or _INVALID */ DCC_CLNT_CTXT *ctxt, DCC_CLNT_FGS clnt_fgs, /* DCC_CLNT_FG_* */ SRVR_INX anum, /* server index or NO_SRVR */ time_t dsecs, /* fudge timestamp by this */ DCC_AOPS aop, u_int32_t val1, u_char val2, u_char val3, u_char val4, u_char *val5, u_int val5_len, DCC_OP_RESP *resp, DCC_SOCKU *resp_su) /* IP address of server used */ { DCC_ADMN_REQ req; DCC_EMSG loc_emsg; DCC_OP_RESP resp0; char resp_buf[DCC_OPBUF]; memset(&req, 0, sizeof(req)); req.date = htonl(time(0) + dsecs); req.aop = aop; req.val1 = ntohl(val1); req.val2 = val2; req.val3 = val3; req.val4 = val4; if (val5_len != 0) { if (val5_len > MAX_DCC_ADMN_REQ_VAL5) dcc_logbad(EX_SOFTWARE, "bogus aop val5 length %d", val5_len); memcpy(req.val5, val5, val5_len); } if (!resp) { resp = &resp0; } else if (clnt_fgs & DCC_CLNT_FG_RETRANS) { req.hdr.op_nums.r = resp->hdr.op_nums.r; } memset(resp, 0, sizeof(*resp)); if (!dcc_clnt_op(loc_emsg, ctxt, clnt_fgs | DCC_CLNT_FG_NO_FAIL, &anum, 0, resp_su, &req.hdr, sizeof(req)-MAX_DCC_ADMN_REQ_VAL5+val5_len, DCC_OP_ADMN, resp, sizeof(*resp))) { dcc_pemsg(dcc_ex_code, emsg, "%s: %s", dcc_aop2str(resp_buf, sizeof(resp_buf), aop, val1), loc_emsg); return DCC_OP_INVALID; } if (resp->hdr.op == DCC_OP_OK) return DCC_OP_OK; if (resp->hdr.op == DCC_OP_ADMN) { /* clear signature after possible string */ int len = (ntohs(resp->hdr.len) - (sizeof(resp->resp) - sizeof(resp->resp.val.string))); if (len < ISZ(resp->resp.val.string)) resp->resp.val.string[len] = '\0'; return DCC_OP_ADMN; } if (resp->hdr.op == DCC_OP_ERROR) { dcc_pemsg(dcc_ex_code, emsg, "%s: %s", dcc_aop2str(resp_buf, sizeof(resp_buf), aop, val1), resp->resp.val.string); return DCC_OP_ERROR; } dcc_pemsg(EX_PROTOCOL, emsg, "%s unexpected response: %s", dcc_aop2str(0, 0, aop, val1), dcc_hdr_op2str(resp_buf, sizeof(resp_buf), &resp->hdr)); return DCC_OP_INVALID; } /* try for a long time or until the server hears */ u_char /* 1=ok, 0=failed */ dcc_aop_persist(DCC_EMSG emsg, DCC_CLNT_CTXT *ctxt, DCC_CLNT_FGS clnt_fgs, u_char debug, DCC_AOPS aop, u_int32_t val1, int secs, /* try for this long */ DCC_OP_RESP *aop_resp) /* results here */ { struct timeval begin, now, op_start; char buf1[DCC_OPBUF]; char buf2[DCC_OPBUF]; u_char complained, fast; time_t us; DCC_OPS result; gettimeofday(&begin, 0); complained = 0; fast = 0; for (;;) { /* This kludge on the transaction ID makes all of our * requests appear to be retransmissions of a single request. * This is nice for operations such as DCC_AOP_FLOD_SHUTDOWN * that are not idempotent when the server has been stalled by * the operating system. */ gettimeofday(&op_start, 0); result = dcc_aop(emsg, ctxt, clnt_fgs, NO_SRVR, 0, aop, val1, 0, 0, 0, 0, 0, aop_resp, 0); /* finished if that worked */ if (result == DCC_OP_ADMN || result == DCC_OP_OK) return 1; /* use the same transaction ID next time */ if (aop_resp) clnt_fgs |= DCC_CLNT_FG_RETRANS; if (result != DCC_OP_ERROR && result != DCC_OP_INVALID) dcc_pemsg(EX_UNAVAILABLE, emsg, "%s: %s", dcc_aop2str(buf1, sizeof(buf1), aop, val1), aop_resp ? dcc_hdr_op2str(buf2, sizeof(buf2), &aop_resp->hdr) : ""); /* deal with time change */ gettimeofday(&now, 0); us = tv_diff2us(&now, &begin); if (us < 0) begin = op_start = now; /* eventually give up */ if (us/DCC_US >= secs) return 0; us = tv_diff2us(&now, &op_start); if (us >= DCC_US) { fast = 0; } else { /* assume the server is dead if it persistently fails * immediately */ if (result == DCC_OP_INVALID && ++fast > 4) { if (debug) quiet_trace_msg("%s: assume dccd dead", dcc_aop2str(buf1, sizeof(buf1), aop, val1)); return 0; } /* explicit delay since the request didn't delay */ usleep(1000); } /* sometimes emit a message if we are going to try again */ if ((result != DCC_OP_ERROR && result != DCC_OP_INVALID) && (debug || !complained)) { complained = 1; dcc_error_msg("%s", emsg); emsg[0] = '\0'; } } }