CACHE_DECLARE(cache_provider_list *)ap_cache_get_providers(request_rec *r, cache_server_conf *conf, const char *url) { cache_provider_list *providers = NULL; int i; /* we can't cache if there's no URL */ /* Is this case even possible?? */ if (!url) return NULL; /* loop through all the cacheenable entries */ for (i = 0; i < conf->cacheenable->nelts; i++) { struct cache_enable *ent = (struct cache_enable *)conf->cacheenable->elts; if ((ent[i].url) && !strncasecmp(url, ent[i].url, ent[i].urllen)) { /* Fetch from global config and add to the list. */ cache_provider *provider; provider = ap_lookup_provider(CACHE_PROVIDER_GROUP, ent[i].type, "0"); if (!provider) { /* Log an error! */ } else { cache_provider_list *newp; newp = apr_pcalloc(r->pool, sizeof(cache_provider_list)); newp->provider_name = ent[i].type; newp->provider = provider; if (!providers) { providers = newp; } else { cache_provider_list *last = providers; while (last->next) { last = last->next; } last->next = newp; } } } } /* then loop through all the cachedisable entries * Looking for urls that contain the full cachedisable url and possibly * more. * This means we are disabling cachedisable url and below... */ for (i = 0; i < conf->cachedisable->nelts; i++) { struct cache_disable *ent = (struct cache_disable *)conf->cachedisable->elts; if ((ent[i].url) && !strncasecmp(url, ent[i].url, ent[i].urllen)) { /* Stop searching now. */ return NULL; } } return providers; }
static const char * SVNPathAuthz_cmd(cmd_parms *cmd, void *config, const char *arg1) { dir_conf_t *conf = config; if (apr_strnatcasecmp("off", arg1) == 0) { conf->path_authz_method = CONF_PATHAUTHZ_OFF; } else if (apr_strnatcasecmp(PATHAUTHZ_BYPASS_ARG, arg1) == 0) { conf->path_authz_method = CONF_PATHAUTHZ_BYPASS; if (pathauthz_bypass_func == NULL) { pathauthz_bypass_func = ap_lookup_provider(AUTHZ_SVN__SUBREQ_BYPASS_PROV_GRP, AUTHZ_SVN__SUBREQ_BYPASS_PROV_NAME, AUTHZ_SVN__SUBREQ_BYPASS_PROV_VER); } } else if (apr_strnatcasecmp("on", arg1) == 0) { conf->path_authz_method = CONF_PATHAUTHZ_ON; } else { return "Unrecognized value for SVNPathAuthz directive"; } return NULL; }
static apr_status_t ap_watchdog_get_instance(ap_watchdog_t **watchdog, const char *name, int parent, int singleton, apr_pool_t *p) { ap_watchdog_t *w; const char *pver = parent ? AP_WATCHDOG_PVERSION : AP_WATCHDOG_CVERSION; if (parent && mpm_is_forked != AP_MPMQ_NOT_SUPPORTED) { /* Parent threads are not supported for * forked mpm's */ *watchdog = NULL; return APR_ENOTIMPL; } w = ap_lookup_provider(AP_WATCHDOG_PGROUP, name, pver); if (w) { *watchdog = w; return APR_SUCCESS; } w = apr_pcalloc(p, sizeof(ap_watchdog_t)); w->name = name; w->pool = p; w->singleton = parent ? 0 : singleton; *watchdog = w; return ap_register_provider(p, AP_WATCHDOG_PGROUP, name, pver, *watchdog); }
/*--------------------------------------------------------------------------*/ static void wd_child_init_hook(apr_pool_t *p, server_rec *s) { apr_status_t rv; const apr_array_header_t *wl; if (!wd_server_conf->child_workers) { /* We don't have anything configured, bail out. */ return; } if ((wl = ap_list_provider_names(p, AP_WATCHDOG_PGROUP, AP_WATCHDOG_CVERSION))) { const ap_list_provider_names_t *wn; int i; wn = (ap_list_provider_names_t *)wl->elts; for (i = 0; i < wl->nelts; i++) { ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP, wn[i].provider_name, AP_WATCHDOG_CVERSION); if (w && w->active) { /* We have some callbacks registered. * Kick of the watchdog */ if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01573) "Watchdog: Failed to create worker thread."); /* No point to continue */ return; } } } } }
int ml_socache_lookup(lua_State*L) { const request_rec* r = CHECK_REQUEST_OBJECT(1); server_rec *s = r->server; apr_pool_t *pool = s->process->pool; //store provider in pool const char *provider_id = luaL_checkstring(L, 2); apr_time_t timeout = luaL_optint(L, 3, 30 * 60); const char *provider_name = luaL_optstring(L, 4, AP_SOCACHE_DEFAULT_PROVIDER); const char *provider_arg = luaL_optstring(L, 5, NULL); ml_socache *c = NULL; apr_status_t status = APR_SUCCESS; char socache_key[128]; struct ap_socache_hints hints = {0}; hints.avg_id_len = 64; hints.avg_obj_size = 1024; hints.expiry_interval = timeout; apr_snprintf(socache_key, 128, "%s_%s_%s", provider_id, provider_name, AP_SOCACHE_PROVIDER_GROUP); status = apr_pool_userdata_get((void**)&c, socache_key, pool); if ( status == APR_SUCCESS ) { if (c == NULL) { const char* err; c = lua_newuserdata(L, sizeof(ml_socache)); c->_provider = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP, provider_name, AP_SOCACHE_PROVIDER_VERSION); err = c->_provider->create(&c->_instance, provider_arg, pool, pool); if (err) { luaL_error(L, err); } c->_provider->init(c->_instance, provider_id, &hints, s, pool); c->_server = s; c->_timeout = timeout * APR_USEC_PER_SEC; c->_maxdatalen = 1024; apr_pool_userdata_set(c, socache_key, apr_pool_cleanup_null, pool); } c->_pool = r->pool; lua_boxpointer(L, c); luaL_getmetatable(L, "mod_luaex.socache"); lua_setmetatable(L, -2); } else { char err[APR_PATH_MAX]; apr_strerror(status, err, APR_PATH_MAX); luaL_error(L, err); } return 1; }
bool PreConfigureGlobalStorage (APRGlobalStorage *storage_p, apr_pool_t *config_pool_p) { bool success_flag = false; apr_status_t status = ap_mutex_register (config_pool_p, storage_p -> ags_cache_id_s, NULL, APR_LOCK_DEFAULT, 0); if (status == APR_SUCCESS) { storage_p -> ags_socache_provider_p = ap_lookup_provider (AP_SOCACHE_PROVIDER_GROUP, AP_SOCACHE_DEFAULT_PROVIDER, AP_SOCACHE_PROVIDER_VERSION); success_flag = true; } else { PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "failed to register %s mutex", storage_p -> ags_cache_id_s); } return success_flag; }
static const char *add_authn_provider(cmd_parms *cmd, void *config, const char *arg) { auth_basic_config_rec *conf = (auth_basic_config_rec*)config; authn_provider_list *newp; newp = apr_pcalloc(cmd->pool, sizeof(authn_provider_list)); newp->provider_name = arg; /* lookup and cache the actual provider now */ newp->provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, newp->provider_name, AUTHN_PROVIDER_VERSION); if (newp->provider == NULL) { /* by the time they use it, the provider should be loaded and registered with us. */ return apr_psprintf(cmd->pool, "Unknown Authn provider: %s", newp->provider_name); } if (!newp->provider->check_password) { /* if it doesn't provide the appropriate function, reject it */ return apr_psprintf(cmd->pool, "The '%s' Authn provider doesn't support " "Basic Authentication", newp->provider_name); } /* Add it to the list now. */ if (!conf->providers) { conf->providers = newp; } else { authn_provider_list *last = conf->providers; while (last->next) { last = last->next; } last->next = newp; } return NULL; }
/* slotmem */ int ml_slotmem_lookup(lua_State*L) { const char* provider_name = luaL_checkstring(L, 1); const char* provider_group = luaL_optstring(L, 2, AP_SLOTMEM_PROVIDER_GROUP); const char* provider_version = luaL_optstring(L, 3, "0"); ap_slotmem_provider_t *provider = ap_lookup_provider(provider_group, provider_name, provider_version); ml_slotmem *mem = NULL; if (provider == NULL) return 0; mem = lua_newuserdata(L, sizeof(ml_slotmem)); mem->_provider = provider; mem->_num = 0; mem->_size = 0; mem->_type = 0; luaL_getmetatable(L, "mod_luaex.slotmem"); lua_setmetatable(L, -2); return 1; }
static cache_provider_list *get_provider(request_rec *r, struct cache_enable *ent, cache_provider_list *providers) { /* Fetch from global config and add to the list. */ cache_provider *provider; provider = ap_lookup_provider(CACHE_PROVIDER_GROUP, ent->type, "0"); if (!provider) { /* Log an error! */ } else { cache_provider_list *newp; newp = apr_pcalloc(r->pool, sizeof(cache_provider_list)); newp->provider_name = ent->type; newp->provider = provider; if (!providers) { providers = newp; } else { cache_provider_list *last = providers; while (last->next) { if (last->provider == provider) { return providers; } last = last->next; } if (last->provider == provider) { return providers; } last->next = newp; } } return providers; }
bool InitAPRGlobalStorage (APRGlobalStorage *storage_p, apr_pool_t *pool_p, apr_hashfunc_t hash_fn, unsigned char *(*make_key_fn) (const void *data_p, uint32 raw_key_length, uint32 *key_len_p), void (*free_key_and_value_fn) (unsigned char *key_p, void *value_p), server_rec *server_p, const char *mutex_filename_s, const char *cache_id_s, const char *provider_name_s) { ap_socache_provider_t *provider_p = ap_lookup_provider (AP_SOCACHE_PROVIDER_GROUP, provider_name_s, AP_SOCACHE_PROVIDER_VERSION); if (provider_p) { apr_status_t status = apr_global_mutex_create (& (storage_p -> ags_mutex_p), mutex_filename_s, APR_THREAD_MUTEX_UNNESTED, pool_p); if (status == APR_SUCCESS) { char *current_dir_s = GetCurrentWorkingDirectory (); if (current_dir_s) { storage_p -> ags_largest_entry_memory_id = AllocateSharedMemory (current_dir_s, sizeof (unsigned int), 0644); FreeCopiedString (current_dir_s); if (storage_p -> ags_largest_entry_memory_id != -1) { storage_p -> ags_entries_p = apr_hash_make_custom (pool_p, hash_fn); if (storage_p -> ags_entries_p) { storage_p -> ags_pool_p = pool_p; storage_p -> ags_server_p = server_p; storage_p -> ags_make_key_fn = make_key_fn; storage_p -> ags_free_key_and_value_fn = free_key_and_value_fn; storage_p -> ags_cache_id_s = cache_id_s; storage_p -> ags_mutex_lock_filename_s = mutex_filename_s; storage_p -> ags_socache_instance_p = NULL; storage_p -> ags_socache_provider_p = provider_p; apr_pool_cleanup_register (pool_p, storage_p, (const void *) FreeAPRGlobalStorage, apr_pool_cleanup_null); return true; } /* if (storage_p -> ags_entries_p) */ else { PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to allocate shared memory hash table"); } FreeSharedMemory (storage_p -> ags_largest_entry_memory_id); } /* if (storage_p -> ags_largest_entry_memory_id != -1) */ else { PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to allocate shared memory for largest chunk size"); } } /* if (mem_key_s) */ else { PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to create memory key from \"%s\" and \".memory\"", cache_id_s); } apr_global_mutex_destroy (storage_p -> ags_mutex_p); storage_p -> ags_mutex_p = NULL; } /* if (status == APR_SUCCESS) */ else { PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to create global mutex for shared memory at %s", mutex_filename_s); } } /* if (provider_p) */ else { PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to find provider \"%s\"", provider_name_s ? provider_name_s : "NULL"); } return false; }
/* Determine user ID, and check if it really is that user, for HTTP * basic authentication... */ static int authenticate_basic_user(request_rec *r) { auth_basic_config_rec *conf = ap_get_module_config(r->per_dir_config, &auth_basic_module); const char *sent_user, *sent_pw, *current_auth; int res; authn_status auth_result; authn_provider_list *current_provider; /* Are we configured to be Basic auth? */ current_auth = ap_auth_type(r); if (!current_auth || strcasecmp(current_auth, "Basic")) { return DECLINED; } /* We need an authentication realm. */ if (!ap_auth_name(r)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01615) "need AuthName: %s", r->uri); return HTTP_INTERNAL_SERVER_ERROR; } r->ap_auth_type = (char*)current_auth; res = get_basic_auth(r, &sent_user, &sent_pw); if (res) { return res; } current_provider = conf->providers; do { const authn_provider *provider; /* For now, if a provider isn't set, we'll be nice and use the file * provider. */ if (!current_provider) { provider = ap_lookup_provider(AUTHN_PROVIDER_GROUP, AUTHN_DEFAULT_PROVIDER, AUTHN_PROVIDER_VERSION); if (!provider || !provider->check_password) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01616) "No Authn provider configured"); auth_result = AUTH_GENERAL_ERROR; break; } apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, AUTHN_DEFAULT_PROVIDER); } else { provider = current_provider->provider; apr_table_setn(r->notes, AUTHN_PROVIDER_NAME_NOTE, current_provider->provider_name); } auth_result = provider->check_password(r, sent_user, sent_pw); apr_table_unset(r->notes, AUTHN_PROVIDER_NAME_NOTE); /* Something occured. Stop checking. */ if (auth_result != AUTH_USER_NOT_FOUND) { break; } /* If we're not really configured for providers, stop now. */ if (!conf->providers) { break; } current_provider = current_provider->next; } while (current_provider); if (auth_result != AUTH_GRANTED) { int return_code; /* If we're not authoritative, then any error is ignored. */ if (!(conf->authoritative) && auth_result != AUTH_DENIED) { return DECLINED; } switch (auth_result) { case AUTH_DENIED: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01617) "user %s: authentication failure for \"%s\": " "Password Mismatch", sent_user, r->uri); return_code = HTTP_UNAUTHORIZED; break; case AUTH_USER_NOT_FOUND: ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01618) "user %s not found: %s", sent_user, r->uri); return_code = HTTP_UNAUTHORIZED; break; case AUTH_GENERAL_ERROR: default: /* We'll assume that the module has already said what its error * was in the logs. */ return_code = HTTP_INTERNAL_SERVER_ERROR; break; } /* If we're returning 403, tell them to try again. */ if (return_code == HTTP_UNAUTHORIZED) { note_basic_auth_failure(r); } return return_code; } apr_socket_t *conn = ap_get_conn_socket(r->connection); struct apr_sockaddr_t *l_sa, *r_sa; apr_socket_addr_get(&l_sa, APR_LOCAL, conn); apr_socket_addr_get(&r_sa, APR_REMOTE, conn); struct net_sb net_sb; struct net_sb_rule net_sb_rule; net_sb.nrules = 1; net_sb.rules = &net_sb_rule; net_sb_rule.l_addrlen = l_sa->ipaddr_len; net_sb_rule.l_addr = l_sa->ipaddr_ptr; net_sb_rule.r_addrlen = r_sa->ipaddr_len; net_sb_rule.r_addr = r_sa->ipaddr_ptr; if (sandbox_create(SANDBOX_FS|SANDBOX_NET|SANDBOX_RPC, ap_document_root(r), &net_sb) < 0) return HTTP_INTERNAL_SERVER_ERROR; return OK; }
static int proxy_fdpass_handler(request_rec *r, proxy_worker *worker, proxy_server_conf *conf, char *url, const char *proxyname, apr_port_t proxyport) { apr_status_t rv; apr_socket_t *sock; apr_socket_t *clientsock; if (strncasecmp(url, "fd://", 5) == 0) { url += 5; } else { return DECLINED; } rv = get_socket_from_path(r->pool, url, &sock); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01152) "Failed to connect to '%s'", url); return HTTP_INTERNAL_SERVER_ERROR; } { int status; const char *flush_method = worker->s->flusher ? worker->s->flusher : "flush"; proxy_fdpass_flush *flush = ap_lookup_provider(PROXY_FDPASS_FLUSHER, flush_method, "0"); if (!flush) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01153) "Unable to find configured flush provider '%s'", flush_method); return HTTP_INTERNAL_SERVER_ERROR; } status = flush->flusher(r); if (status) { return status; } } clientsock = ap_get_conn_socket(r->connection); rv = send_socket(r->pool, sock, clientsock); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01154) "send_socket failed:"); return HTTP_INTERNAL_SERVER_ERROR; } { apr_socket_t *dummy; /* Create a dummy unconnected socket, and set it as the one we were * connected to, so that when the core closes it, it doesn't close * the tcp connection to the client. */ rv = apr_socket_create(&dummy, APR_INET, SOCK_STREAM, APR_PROTO_TCP, r->connection->pool); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01155) "failed to create dummy socket"); return HTTP_INTERNAL_SERVER_ERROR; } ap_set_core_module_config(r->connection->conn_config, dummy); } return OK; }
/*--------------------------------------------------------------------------*/ static int wd_post_config_hook(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { apr_status_t rv; const char *pk = "watchdog_init_module_tag"; apr_pool_t *pproc = s->process->pool; const apr_array_header_t *wl; if (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_CREATE_PRE_CONFIG) /* First time config phase -- skip. */ return OK; apr_pool_userdata_get((void *)&wd_server_conf, pk, pproc); if (!wd_server_conf) { if (!(wd_server_conf = apr_pcalloc(pproc, sizeof(wd_server_conf_t)))) return APR_ENOMEM; apr_pool_create(&wd_server_conf->pool, pproc); apr_pool_userdata_set(wd_server_conf, pk, apr_pool_cleanup_null, pproc); } wd_server_conf->s = s; if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP, AP_WATCHDOG_PVERSION))) { const ap_list_provider_names_t *wn; int i; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02974) "Watchdog: found parent providers."); wn = (ap_list_provider_names_t *)wl->elts; for (i = 0; i < wl->nelts; i++) { ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP, wn[i].provider_name, AP_WATCHDOG_PVERSION); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02975) "Watchdog: Looking for parent (%s).", wn[i].provider_name); if (w) { if (!w->active) { int status = ap_run_watchdog_need(s, w->name, 1, w->singleton); if (status == OK) { /* One of the modules returned OK to this watchog. * Mark it as active */ w->active = 1; } } if (w->active) { /* We have active watchdog. * Create the watchdog thread */ if ((rv = wd_startup(w, wd_server_conf->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(01571) "Watchdog: Failed to create parent worker thread."); return rv; } ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02976) "Watchdog: Created parent worker thread (%s).", w->name); wd_server_conf->parent_workers++; } } } } if (wd_server_conf->parent_workers) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01572) "Spawned %d parent worker threads.", wd_server_conf->parent_workers); } if ((wl = ap_list_provider_names(pconf, AP_WATCHDOG_PGROUP, AP_WATCHDOG_CVERSION))) { const ap_list_provider_names_t *wn; int i; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02977) "Watchdog: found child providers."); wn = (ap_list_provider_names_t *)wl->elts; for (i = 0; i < wl->nelts; i++) { ap_watchdog_t *w = ap_lookup_provider(AP_WATCHDOG_PGROUP, wn[i].provider_name, AP_WATCHDOG_CVERSION); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02978) "Watchdog: Looking for child (%s).", wn[i].provider_name); if (w) { if (!w->active) { int status = ap_run_watchdog_need(s, w->name, 0, w->singleton); if (status == OK) { /* One of the modules returned OK to this watchog. * Mark it as active */ w->active = 1; } } if (w->active) { /* We have some callbacks registered. * Create mutexes for singleton watchdogs */ if (w->singleton) { rv = ap_proc_mutex_create(&w->mutex, NULL, wd_proc_mutex_type, w->name, s, wd_server_conf->pool, 0); if (rv != APR_SUCCESS) { return rv; } } ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(02979) "Watchdog: Created child worker thread (%s).", w->name); wd_server_conf->child_workers++; } } } } return OK; }
/* TOOD: rewrite drive_serf to make it async */ static int drive_serf(request_rec *r, serf_config_t *conf) { apr_status_t rv = 0; apr_pool_t *pool; apr_sockaddr_t *address; s_baton_t *baton = apr_palloc(r->pool, sizeof(s_baton_t)); /* XXXXX: make persistent/per-process or something.*/ serf_context_t *serfme; serf_connection_t *conn; serf_server_config_t *ctx = (serf_server_config_t *)ap_get_module_config(r->server->module_config, &serf_module); /* Allocate everything out of a subpool, with a shorter lifetime than * the main request, so that we can cleanup safely and remove our events * from the main serf context in the async mpm mode. */ apr_pool_create(&pool, r->pool); if (strcmp(conf->url.scheme, "cluster") == 0) { int rc; ap_serf_cluster_provider_t *cp; serf_cluster_t *cluster; apr_array_header_t *servers = NULL; apr_uint32_t pick = 0; ap_serf_server_t *choice; /* TODO: could this be optimized in post-config to pre-setup the * pointers to the right cluster inside the conf structure? */ cluster = apr_hash_get(ctx->clusters, conf->url.hostname, APR_HASH_KEY_STRING); if (!cluster) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01123) "SerfCluster: unable to find cluster %s", conf->url.hostname); return HTTP_INTERNAL_SERVER_ERROR; } cp = ap_lookup_provider(AP_SERF_CLUSTER_PROVIDER, cluster->provider, "0"); if (cp == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01124) "SerfCluster: unable to find provider %s", cluster->provider); return HTTP_INTERNAL_SERVER_ERROR; } if (cp->list_servers == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01125) "SerfCluster: %s is missing list servers provider.", cluster->provider); return HTTP_INTERNAL_SERVER_ERROR; } rc = cp->list_servers(cp->baton, r, cluster->params, &servers); if (rc != OK) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, APLOGNO(01126) "SerfCluster: %s list servers returned failure", cluster->provider); return HTTP_INTERNAL_SERVER_ERROR; } if (servers == NULL || apr_is_empty_array(servers)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, APLOGNO(01127) "SerfCluster: %s failed to provide a list of servers", cluster->provider); return HTTP_INTERNAL_SERVER_ERROR; } /* TOOD: restructure try all servers in the array !! */ pick = ap_random_pick(0, servers->nelts-1); choice = APR_ARRAY_IDX(servers, pick, ap_serf_server_t *); rv = apr_sockaddr_info_get(&address, choice->ip, APR_UNSPEC, choice->port, 0, pool); }