* file named AUTHORS, in the root directory of this distribution.
*/
/*
- * $Id: protocol.c,v 1.45.2.2 2006/12/18 20:43:51 martinea Exp $
+ * $Id: protocol.c,v 1.45 2006/05/25 17:07:31 martinea Exp $
*
* implements amanda protocol
*/
#include "amanda.h"
+#include "conffile.h"
#include "event.h"
#include "packet.h"
#include "security.h"
#include "protocol.h"
-/*#define PROTO_DEBUG*/
+#define proto_debug(i, ...) do { \
+ if ((i) <= debug_protocol) { \
+ dbprintf(__VA_ARGS__); \
+ } \
+} while (0)
/*
* Valid actions that can be passed to the state machine
time_t origtime; /* orig start time of this request */
time_t curtime; /* time when this attempt started */
int connecttries; /* times we'll retry a connect */
- int reqtries; /* times we'll resend a REQ */
- int acktries; /* times we'll wait for an a ACK */
+ int resettries; /* times we'll resend a REQ */
+ int reqtries; /* times we'll wait for an a ACK */
pkt_t req; /* the actual wire request */
protocol_sendreq_callback continuation; /* call when req dies/finishes */
void *datap; /* opaque cookie passed to above */
char *(*conf_fn)(char *, void *); /* configuration function */
} proto_t;
-#define CONNECT_TRIES 3 /* num retries after connect errors */
#define CONNECT_WAIT 5 /* secs between connect attempts */
#define ACK_WAIT 10 /* time (secs) to wait for ACK - keep short */
-#define ACK_TRIES 3 /* num retries after ACK_WAIT timeout */
-#define REQ_TRIES 2 /* num restarts (reboot/crash) */
+#define RESET_TRIES 2 /* num restarts (reboot/crash) */
#define CURTIME (time(0) - proto_init_time) /* time relative to start */
/* if no reply in an hour, just forget it */
/* local functions */
-#ifdef PROTO_DEBUG
static const char *action2str(p_action_t);
static const char *pstate2str(pstate_t);
-#endif
static void connect_callback(void *, security_handle_t *, security_status_t);
static void connect_wait_callback(void *);
p->repwait = repwait;
p->origtime = CURTIME;
/* p->curtime set in the sendreq state */
- p->connecttries = CONNECT_TRIES;
- p->reqtries = REQ_TRIES;
- p->acktries = ACK_TRIES;
+ p->connecttries = getconf_int(CNF_CONNECT_TRIES);
+ p->resettries = RESET_TRIES;
+ p->reqtries = getconf_int(CNF_REQ_TRIES);
p->conf_fn = conf_fn;
- pkt_init(&p->req, P_REQ, req);
+ pkt_init(&p->req, P_REQ, "%s", req);
/*
* These are here for the caller
p->continuation = continuation;
p->datap = datap;
-#ifdef PROTO_DEBUG
- dbprintf(("%s: security_connect: host %s -> p %p\n",
- debug_prefix_time(": protocol"), hostname, p));
-#endif
+ proto_debug(1, _("protocol: security_connect: host %s -> p %p\n"),
+ hostname, p);
security_connect(p->security_driver, p->hostname, conf_fn, connect_callback,
p, p->datap);
assert(p != NULL);
p->security_handle = security_handle;
-#ifdef PROTO_DEBUG
- dbprintf(("%s: connect_callback: p %p\n",
- debug_prefix_time(": protocol"), p));
-#endif
+ proto_debug(1, _("protocol: connect_callback: p %p\n"), p);
switch (status) {
case S_OK:
break;
case S_TIMEOUT:
- security_seterror(p->security_handle, "timeout during connect");
+ security_seterror(p->security_handle, _("timeout during connect"));
/* FALLTHROUGH */
case S_ERROR:
if (--p->connecttries == 0) {
state_machine(p, PA_ABORT, NULL);
} else {
-#ifdef PROTO_DEBUG
- dbprintf(("%s: connect_callback: p %p: retrying %s\n",
- debug_prefix_time(": protocol"), p, p->hostname));
-#endif
+ proto_debug(1, _("protocol: connect_callback: p %p: retrying %s\n"),
+ p, p->hostname);
security_close(p->security_handle);
/* XXX overload p->security handle to hold the event handle */
p->security_handle =
pstate_t curstate;
p_action_t retaction;
-#ifdef PROTO_DEBUG
- dbprintf(("%s: state_machine: initial: p %p action %s pkt %p\n",
- debug_prefix_time(": protocol"),
- p, action2str(action), NULL));
-#endif
+ proto_debug(1, _("protocol: state_machine: initial: p %p action %s pkt %p\n"),
+ p, action2str(action), (void *)NULL);
assert(p != NULL);
assert(action == PA_RCVDATA || pkt == NULL);
assert(p->state != NULL);
for (;;) {
-#ifdef PROTO_DEBUG
- dbprintf(("%s: state_machine: p %p state %s action %s\n",
- debug_prefix_time(": protocol"),
- p, pstate2str(p->state), action2str(action)));
+ proto_debug(1, _("protocol: state_machine: p %p state %s action %s\n"),
+ p, pstate2str(p->state), action2str(action));
if (pkt != NULL) {
- dbprintf(("%s: pkt: %s (t %d) orig REQ (t %d cur %d)\n",
- debug_prefix(": protocol"),
- pkt_type2str(pkt->type), (int)CURTIME,
- (int)p->origtime, (int)p->curtime));
- dbprintf(("%s: pkt contents:\n-----\n%s-----\n",
- debug_prefix(": protocol"), pkt->body));
+ proto_debug(1, _("protocol: pkt: %s (t %d) orig REQ (t %d cur %d)\n"),
+ pkt_type2str(pkt->type), (int)CURTIME,
+ (int)p->origtime, (int)p->curtime);
+ proto_debug(1, _("protocol: pkt contents:\n-----\n%s-----\n"),
+ pkt->body);
}
-#endif
/*
* p->state is a function pointer to the current state a request
*/
retaction = (*curstate)(p, action, pkt);
-#ifdef PROTO_DEBUG
- dbprintf(("%s: state_machine: p %p state %s returned %s\n",
- debug_prefix_time(": protocol"),
- p, pstate2str(p->state), action2str(retaction)));
-#endif
+ proto_debug(1, _("protocol: state_machine: p %p state %s returned %s\n"),
+ p, pstate2str(p->state), action2str(retaction));
/*
* The state function is expected to return one of the following
/* FALLTHROUGH */
case PA_PENDING:
-#ifdef PROTO_DEBUG
- dbprintf(("%s: state_machine: p %p state %s: timeout %d\n",
- debug_prefix_time(": protocol"),
- p, pstate2str(p->state), (int)p->timeout));
-#endif
+ proto_debug(1, _("protocol: state_machine: p %p state %s: timeout %d\n"),
+ p, pstate2str(p->state), (int)p->timeout);
/*
* Get the security layer to register a receive event for this
* security handle on our behalf. Have it timeout in p->timeout
*/
case PA_CONTINUE:
assert(p->state != curstate);
-#ifdef PROTO_DEBUG
- dbprintf(("%s: state_machine: p %p: moved from %s to %s\n",
- debug_prefix_time(": protocol"),
- p, pstate2str(curstate),
- pstate2str(p->state)));
-#endif
+ proto_debug(1, _("protocol: state_machine: p %p: moved from %s to %s\n"),
+ p, pstate2str(curstate),
+ pstate2str(p->state));
continue;
/*
if (security_sendpkt(p->security_handle, &p->req) < 0) {
/* XXX should retry */
- security_seterror(p->security_handle, "error sending REQ: %s",
+ security_seterror(p->security_handle, _("error sending REQ: %s"),
security_geterror(p->security_handle));
return (PA_ABORT);
}
if (action == PA_TIMEOUT) {
assert(pkt == NULL);
- if (--p->acktries == 0) {
- security_seterror(p->security_handle, "timeout waiting for ACK");
+ if (--p->reqtries == 0) {
+ security_seterror(p->security_handle, _("timeout waiting for ACK"));
return (PA_ABORT);
}
* If we've blown our timeout limit, free up this packet and
* return.
*/
- if (p->reqtries == 0 || DROP_DEAD_TIME(p->origtime)) {
- security_seterror(p->security_handle, "timeout waiting for REP");
+ if (p->resettries == 0 || DROP_DEAD_TIME(p->origtime)) {
+ security_seterror(p->security_handle, _("timeout waiting for REP"));
return (PA_ABORT);
}
/*
* We still have some tries left. Resend the request.
*/
- p->reqtries--;
+ p->resettries--;
p->state = s_sendreq;
- p->acktries = ACK_TRIES;
+ p->reqtries = getconf_int(CNF_REQ_TRIES);
return (PA_CONTINUE);
}
assert(action == PA_RCVDATA);
+ /* Finish if we get a NAK */
+ if (pkt->type == P_NAK)
+ return (PA_FINISH);
+
/*
* We've received some data. If we didn't get a reply,
* requeue the packet and retry. Otherwise, acknowledge
if (security_sendpkt(p->security_handle, &ack) < 0) {
/* XXX should retry */
amfree(ack.body);
- security_seterror(p->security_handle, "error sending ACK: %s",
+ security_seterror(p->security_handle, _("error sending ACK: %s"),
security_geterror(p->security_handle));
return (PA_ABORT);
}
* Misc functions
*/
-#ifdef PROTO_DEBUG
/*
* Convert a pstate_t into a printable form.
*/
for (i = 0; i < ASIZE(pstates); i++)
if (pstate == pstates[i].type)
return (pstates[i].name);
- return ("BOGUS PSTATE");
+ return (_("BOGUS PSTATE"));
}
/*
for (i = 0; i < ASIZE(actions); i++)
if (action == actions[i].type)
return (actions[i].name);
- return ("BOGUS ACTION");
+ return (_("BOGUS ACTION"));
}
-#endif /* PROTO_DEBUG */