static void qmqpd_reply(QMQPD_STATE *state, int log_message, int status_code, const char *fmt,...) { va_list ap; /* * Optionally change hard errors into retryable ones. Send the reply and * optionally log it. Always insert a delay before reporting a problem. * This slows down software run-away conditions. */ if (status_code == QMQPD_STAT_HARD && var_soft_bounce) status_code = QMQPD_STAT_RETRY; VSTRING_RESET(state->buf); VSTRING_ADDCH(state->buf, status_code); va_start(ap, fmt); vstring_vsprintf_append(state->buf, fmt, ap); va_end(ap); NETSTRING_PUT_BUF(state->client, state->buf); if (log_message) (status_code == QMQPD_STAT_OK ? msg_info : msg_warn) ("%s: %s: %s", state->queue_id, state->namaddr, STR(state->buf) + 1); if (status_code != QMQPD_STAT_OK) sleep(var_qmqpd_err_sleep); netstring_fflush(state->client); }
static void send_reply(SINK_STATE *state) { vstring_sprintf(buffer, "%c*k", QMQP_STAT_OK); NETSTRING_PUT_BUF(state->stream, buffer); netstring_fflush(state->stream); if (count_deliveries) { counter++; vstream_printf("%d\r", counter); vstream_fflush(VSTREAM_OUT); } disconnect(state); }
static const char *dict_sockmap_lookup(DICT *dict, const char *key) { const char *myname = "dict_sockmap_lookup"; DICT_SOCKMAP *dp = (DICT_SOCKMAP *) dict; AUTO_CLNT *sockmap_clnt = DICT_SOCKMAP_RH_HANDLE(dp->client_info); VSTREAM *fp; int netstring_err; char *reply_payload; int except_count; const char *error_class; if (msg_verbose) msg_info("%s: key %s", myname, key); /* * Optionally fold the key. */ if (dict->flags & DICT_FLAG_FOLD_MUL) { if (dict->fold_buf == 0) dict->fold_buf = vstring_alloc(100); vstring_strcpy(dict->fold_buf, key); key = lowercase(STR(dict->fold_buf)); } /* * We retry connection-level errors once, to make server restarts * transparent. */ for (except_count = 0; /* see below */ ; except_count++) { /* * Look up the stream. */ if ((fp = auto_clnt_access(sockmap_clnt)) == 0) { msg_warn("table %s:%s lookup error: %m", dict->type, dict->name); dict->error = DICT_ERR_RETRY; return (0); } /* * Set up an exception handler. */ netstring_setup(fp, dict_sockmap_timeout); if ((netstring_err = vstream_setjmp(fp)) == 0) { /* * Send the query. This may raise an exception. */ vstring_sprintf(dp->rdwr_buf, "%s %s", dp->sockmap_name, key); NETSTRING_PUT_BUF(fp, dp->rdwr_buf); /* * Receive the response. This may raise an exception. */ netstring_get(fp, dp->rdwr_buf, dict_sockmap_max_reply); /* * If we got here, then no exception was raised. */ break; } /* * Handle exceptions. */ else { /* * We retry a broken connection only once. */ if (except_count == 0 && netstring_err == NETSTRING_ERR_EOF && errno != ETIMEDOUT) { auto_clnt_recover(sockmap_clnt); continue; } /* * We do not retry other errors. */ else { msg_warn("table %s:%s lookup error: %s", dict->type, dict->name, netstring_strerror(netstring_err)); dict->error = DICT_ERR_RETRY; return (0); } } } /* * Parse the reply. */ VSTRING_TERMINATE(dp->rdwr_buf); reply_payload = split_at(STR(dp->rdwr_buf), ' '); if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_OK) == 0) { dict->error = 0; return (reply_payload); } else if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_NOTFOUND) == 0) { dict->error = 0; return (0); } /* We got no definitive reply. */ if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_TEMP) == 0) { error_class = "temporary"; dict->error = DICT_ERR_RETRY; } else if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_TIMEOUT) == 0) { error_class = "timeout"; dict->error = DICT_ERR_RETRY; } else if (strcmp(STR(dp->rdwr_buf), DICT_SOCKMAP_PROT_PERM) == 0) { error_class = "permanent"; dict->error = DICT_ERR_CONFIG; } else { error_class = "unknown"; dict->error = DICT_ERR_RETRY; } while (reply_payload && ISSPACE(*reply_payload)) reply_payload++; msg_warn("%s:%s socketmap server %s error%s%.200s", dict->type, dict->name, error_class, reply_payload && *reply_payload ? ": " : "", reply_payload && *reply_payload ? printable(reply_payload, '?') : ""); return (0); }