pan> (ups->ups, rspamd_upstream_restore_cb, ups); } rspamd_mutex_unlock (ups->lock); if (!forced) { type = ups->rot_alg != RSPAMD_UPSTREAM_UNDEF ? ups->rot_alg : default_type; } else { type = default_type != RSPAMD_UPSTREAM_UNDEF ? default_type : ups->rot_alg; } if (type == RSPAMD_UPSTREAM_HASHED && (keylen == 0 || key == NULL)) { /* Cannot use hashed rotation when no key is specified, switch to random */ type = RSPAMD_UPSTREAM_RANDOM; } switch (type) { default: case RSPAMD_UPSTREAM_RANDOM: return rspamd_upstream_get_random (ups); case RSPAMD_UPSTREAM_HASHED: return rspamd_upstream_get_hashed (ups, key, keylen); case RSPAMD_UPSTREAM_ROUND_ROBIN: return rspamd_upstream_get_round_robin (ups, TRUE); case RSPAMD_UPSTREAM_MASTER_SLAVE: return rspamd_upstream_get_round_robin (ups, FALSE); case RSPAMD_UPSTREAM_SEQUENTIAL: if (ups->cur_elt >= ups->alive->len) { ups->cur_elt = 0; return NULL; } return g_ptr_array_index (ups->alive, ups->cur_elt ++); } /* Silent stupid compilers */ return NULL; } struct upstream* rspamd_upstream_get (struct upstream_list *ups, enum rspamd_upstream_rotation default_type, const guchar *key, gsize keylen) { return rspamd_upstream_get_common (ups, default_type, key, keylen, FALSE); } struct upstream* rspamd_upstream_get_forced (struct upstream_list *ups, enum rspamd_upstream_rotation forced_type, const guchar *key, gsize keylen) { return rspamd_upstream_get_common (ups, forced_type, key, keylen, TRUE); } void rspamd_upstream_reresolve (struct upstream_ctx *ctx) { GList *cur; struct upstream *up; cur = ctx->upstreams->head; while (cur) { up = cur->data; REF_RETAIN (up); if (up->name[0] != '/' && ctx->res != NULL && !(up->ls->flags & RSPAMD_UPSTREAM_FLAG_NORESOLVE)) { if (rdns_make_request_full (ctx->res, rspamd_upstream_dns_cb, up, ctx->dns_timeout, ctx->dns_retransmits, 1, up->name, RDNS_REQUEST_A) != NULL) { up->dns_requests++; REF_RETAIN (up); } if (rdns_make_request_full (ctx->res, rspamd_upstream_dns_cb, up, ctx->dns_timeout, ctx->dns_retransmits, 1, up->name, RDNS_REQUEST_AAAA) != NULL) { up->dns_requests++; REF_RETAIN (up); } } REF_RELEASE (up); cur = g_list_next (cur); } } gpointer rspamd_upstream_set_data (struct upstream *up, gpointer data) { gpointer prev_data = up->data; up->data = data; return prev_data; } gpointer rspamd_upstream_get_data (struct upstream *up) { return up->data; } void rspamd_upstreams_foreach (struct upstream_list *ups, rspamd_upstream_traverse_func cb, void *ud) { struct upstream *up; guint i; for (i = 0; i < ups->ups->len; i ++) { up = g_ptr_array_index (ups->ups, i); cb (up, ud); } }