/*--------------------------------------------------------------------------*/
static const char *cmd_advertise_m(cmd_parms *cmd, void *dummy,
                                   const char *arg, const char *opt)
{
    mod_advertise_config *mconf = ap_get_module_config(cmd->server->module_config, &advertise_module);
    if (mconf->ma_advertise_srvs)
        return "Duplicate ServerAdvertise directives are not allowed";

    if (strcasecmp(arg, "Off") == 0)
        mconf->ma_advertise_mode = ma_advertise_off;
    else if (strcasecmp(arg, "On") == 0)
        mconf->ma_advertise_mode = ma_advertise_on;
    else
        return "ServerAdvertise must be Off or On";
    if (opt) {
        const char *p = ap_strstr_c(opt, "://");
        if (p) {
            mconf->ma_advertise_srvm = apr_pstrndup(cmd->pool, opt, p - opt);
            opt = p + 3;
        }
        if (apr_parse_addr_port(&mconf->ma_advertise_srvs,
                                &mconf->ma_advertise_srvi,
                                &mconf->ma_advertise_srvp,
                                opt, cmd->pool) != APR_SUCCESS ||
                                !mconf->ma_advertise_srvs ||
                                !mconf->ma_advertise_srvp)
            return "Invalid ServerAdvertise Address";
    }
    mconf->ma_advertise_server = cmd->server;
    return NULL;
}
Beispiel #2
0
/*
 * initialize the Redis struct the specified Redis server
 */
static int oidc_cache_redis_post_config(server_rec *s) {
	oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(s->module_config,
			&auth_openidc_module);

	if (cfg->cache_cfg != NULL)
		return APR_SUCCESS;
	oidc_cache_cfg_redis_t *context = oidc_cache_redis_cfg_create(
			s->process->pool);
	cfg->cache_cfg = context;

	apr_status_t rv = APR_SUCCESS;

	/* parse the host:post tuple from the configuration */
	if (cfg->cache_redis_server == NULL) {
		oidc_serror(s,
				"cache type is set to \"redis\", but no valid OIDCRedisCacheServer setting was found");
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	char* scope_id;
	rv = apr_parse_addr_port(&context->host_str, &scope_id, &context->port,
			cfg->cache_redis_server, s->process->pool);
	if (rv != APR_SUCCESS) {
		oidc_serror(s, "failed to parse cache server: '%s'",
				cfg->cache_redis_server);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	if (context->host_str == NULL) {
		oidc_serror(s,
				"failed to parse cache server, no hostname specified: '%s'",
				cfg->cache_redis_server);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	if (context->port == 0)
		context->port = 6379;

	if (oidc_cache_mutex_post_config(s, context->mutex, "redis") == FALSE)
		return HTTP_INTERNAL_SERVER_ERROR;

	return OK;
}
/*--------------------------------------------------------------------------*/
static const char *cmd_bindaddr(cmd_parms *cmd, void *dummy,
                                   const char *arg)
{
    mod_advertise_config *mconf = ap_get_module_config(cmd->server->module_config, &advertise_module);
    if (mconf->ma_bind_set)
        return "Duplicate AdvertiseBindAddress directives are not allowed";

    if (apr_parse_addr_port(&mconf->ma_bind_adrs,
                            &mconf->ma_bind_adsi,
                            &mconf->ma_bind_port,
                            arg, cmd->pool) != APR_SUCCESS)
        return "Invalid AdvertiseBindAddress address";
    if (!mconf->ma_bind_adrs)
        return "Missing Ip part from AdvertiseBindAddress address";
    if (!mconf->ma_bind_port)
        mconf->ma_bind_port = MA_DEFAULT_ADVPORT;
    mconf->ma_bind_set = 1;
    mconf->ma_advertise_server = cmd->server;
    return NULL;
}
Beispiel #4
0
/*
 * Parses a host of the form <address>[:port]
 * paddr is used to create a list in the order of input
 * **paddr is the ->next pointer of the last entry (or s->addrs)
 * *paddr is the variable used to keep track of **paddr between calls
 * port is the default port to assume
 */
static const char *get_addresses(apr_pool_t *p, const char *w_,
                                 server_addr_rec ***paddr,
                                 apr_port_t default_port)
{
    apr_sockaddr_t *my_addr;
    server_addr_rec *sar;
    char *w, *host, *scope_id;
    int wild_port;
    apr_size_t wlen;
    apr_port_t port;
    apr_status_t rv;

    if (*w_ == '\0')
        return NULL;

    wlen = strlen(w_);                   /* wlen must be > 0 at this point */
    w = apr_pstrmemdup(p, w_, wlen);
    /* apr_parse_addr_port() doesn't understand ":*" so handle that first. */
    wild_port = 0;
    if (w[wlen - 1] == '*') {
        if (wlen < 2) {
            wild_port = 1;
        }
        else if (w[wlen - 2] == ':') {
            w[wlen - 2] = '\0';
            wild_port = 1;
        }
    }
    rv = apr_parse_addr_port(&host, &scope_id, &port, w, p);
    /* If the string is "80", apr_parse_addr_port() will be happy and set
     * host to NULL and port to 80, so watch out for that.
     */
    if (rv != APR_SUCCESS) {
        return "The address or port is invalid";
    }
    if (!host) {
        return "Missing address for VirtualHost";
    }
    if (scope_id) {
        return "Scope ids are not supported";
    }
    if (!port && !wild_port) {
        port = default_port;
    }

    if (strcmp(host, "*") == 0 || strcasecmp(host, "_default_") == 0) {
        rv = apr_sockaddr_info_get(&my_addr, NULL, APR_UNSPEC, port, 0, p);
        if (rv) {
            return "Could not determine a wildcard address ('0.0.0.0') -- "
                "check resolver configuration.";
        }
    }
    else {
        rv = apr_sockaddr_info_get(&my_addr, host, APR_UNSPEC, port, 0, p);
        if (rv != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL, APLOGNO(00547)
                "Could not resolve host name %s -- ignoring!", host);
            return NULL;
        }
    }

    /* Remember all addresses for the host */

    do {
        sar = apr_pcalloc(p, sizeof(server_addr_rec));
        **paddr = sar;
        *paddr = &sar->next;
        sar->host_addr = my_addr;
        sar->host_port = port;
        sar->virthost = host;
        my_addr = my_addr->next;
    } while (my_addr);

    return NULL;
}
/*
 * initialize the memcache struct to a number of memcache servers
 */
static int oidc_cache_memcache_post_config(server_rec *s) {
	oidc_cfg *cfg = (oidc_cfg *) ap_get_module_config(s->module_config,
			&auth_openidc_module);

	if (cfg->cache_cfg != NULL)
		return APR_SUCCESS;
	oidc_cache_cfg_memcache_t *context = oidc_cache_memcache_cfg_create(
			s->process->pool);
	cfg->cache_cfg = context;

	apr_status_t rv = APR_SUCCESS;
	int nservers = 0;
	char* split;
	char* tok;
	apr_pool_t *p = s->process->pool;

	if (cfg->cache_memcache_servers == NULL) {
		oidc_serror(s,
				"cache type is set to \"memcache\", but no valid OIDCMemCacheServers setting was found");
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	/* loop over the provided memcache servers to find out the number of servers configured */
	char *cache_config = apr_pstrdup(p, cfg->cache_memcache_servers);
	split = apr_strtok(cache_config, " ", &tok);
	while (split) {
		nservers++;
		split = apr_strtok(NULL, " ", &tok);
	}

	/* allocated space for the number of servers */
	rv = apr_memcache_create(p, nservers, 0, &context->cache_memcache);
	if (rv != APR_SUCCESS) {
		oidc_serror(s, "failed to create memcache object of '%d' size",
				nservers);
		return HTTP_INTERNAL_SERVER_ERROR;
	}

	/* loop again over the provided servers */
	cache_config = apr_pstrdup(p, cfg->cache_memcache_servers);
	split = apr_strtok(cache_config, " ", &tok);
	while (split) {
		apr_memcache_server_t* st;
		char* host_str;
		char* scope_id;
		apr_port_t port;

		/* parse out host and port */
		rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p);
		if (rv != APR_SUCCESS) {
			oidc_serror(s, "failed to parse cache server: '%s'", split);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		if (host_str == NULL) {
			oidc_serror(s,
					"failed to parse cache server, no hostname specified: '%s'",
					split);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		if (port == 0)
			port = 11211;

		/* create the memcache server struct */
		// TODO: tune this
		rv = apr_memcache_server_create(p, host_str, port, 0, 1, 1, 60, &st);
		if (rv != APR_SUCCESS) {
			oidc_serror(s, "failed to create cache server: %s:%d", host_str,
					port);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		/* add the memcache server struct to the list */
		rv = apr_memcache_add_server(context->cache_memcache, st);
		if (rv != APR_SUCCESS) {
			oidc_serror(s, "failed to add cache server: %s:%d", host_str, port);
			return HTTP_INTERNAL_SERVER_ERROR;
		}

		/* go to the next entry */
		split = apr_strtok(NULL, " ", &tok);
	}

	return OK;
}
Beispiel #6
0
int main(int argc, const char **argv)
{
    apr_status_t status;
    apr_pool_t *pool;
    serf_bucket_alloc_t *bkt_alloc;
    serf_context_t *context;
    serf_connection_t **connections;
    app_baton_t app_ctx;
    handler_baton_t handler_ctx;
    serf_bucket_t *req_hdrs = NULL;
    apr_uri_t url;
    const char *proxy = NULL;
    const char *raw_url, *method, *req_body_path = NULL;
    int count, inflight, conn_count;
    int i;
    int print_headers, debug;
    const char *username = NULL;
    const char *password = "";
    const char *pem_path = NULL, *pem_pwd = NULL;
    apr_getopt_t *opt;
    int opt_c;
    const char *opt_arg;

    apr_initialize();
    atexit(apr_terminate);

    apr_pool_create(&pool, NULL);
    /* serf_initialize(); */
    bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);

    /* Default to one round of fetching with no limit to max inflight reqs. */
    count = 1;
    inflight = 0;
    conn_count = 1;
    /* Default to GET. */
    method = "GET";
    /* Do not print headers by default. */
    print_headers = 0;
    /* Do not debug by default. */
    debug = 0;

    
    apr_getopt_init(&opt, pool, argc, argv);
    while ((status = apr_getopt_long(opt, options, &opt_c, &opt_arg)) ==
           APR_SUCCESS) {

        switch (opt_c) {
        case 'U':
            username = opt_arg;
            break;
        case 'P':
            password = opt_arg;
            break;
        case 'd':
            debug = 1;
            break;
        case 'f':
            req_body_path = opt_arg;
            break;
        case 'h':
            print_usage(pool);
            exit(0);
            break;
        case 'H':
            print_headers = 1;
            break;
        case 'm':
            method = opt_arg;
            break;
        case 'n':
            errno = 0;
            count = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of times to fetch URL (%d)\n",
                       errno);
                return errno;
            }
            break;
        case 'c':
            errno = 0;
            conn_count = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of concurrent connections to use (%d)\n",
                       errno);
                return errno;
            }

            if (conn_count <= 0) {
                printf("Invalid number of concurrent connections to use (%d)\n",
                       conn_count);
                return 1;
            }
            break;
        case 'x':
            errno = 0;
            inflight = apr_strtoi64(opt_arg, NULL, 10);
            if (errno) {
                printf("Problem converting number of requests to have outstanding (%d)\n",
                       errno);
                return errno;
            }
            break;
        case 'p':
            proxy = opt_arg;
            break;
        case 'r':
            {
                char *sep;
                char *hdr_val;

                if (req_hdrs == NULL) {
                    /* first request header, allocate bucket */
                    req_hdrs = serf_bucket_headers_create(bkt_alloc);
                }
                sep = strchr(opt_arg, ':');
                if ((sep == NULL) || (sep == opt_arg) || (strlen(sep) <= 1)) {
                    printf("Invalid request header string (%s)\n", opt_arg);
                    return EINVAL;
                }
                hdr_val = sep + 1;
                while (*hdr_val == ' ') {
                    hdr_val++;
                }
                serf_bucket_headers_setx(req_hdrs, opt_arg, (sep - opt_arg), 1,
                                         hdr_val, strlen(hdr_val), 1);
            }
            break;
        case CERTFILE:
            pem_path = opt_arg;
            break;
        case CERTPWD:
            pem_pwd = opt_arg;
            break;
        case 'v':
            puts("Serf version: " SERF_VERSION_STRING);
            exit(0);
        default:
            break;
        }
    }

    if (opt->ind != opt->argc - 1) {
        print_usage(pool);
        exit(-1);
    }

    raw_url = argv[opt->ind];

    apr_uri_parse(pool, raw_url, &url);
    if (!url.port) {
        url.port = apr_uri_port_of_scheme(url.scheme);
    }
    if (!url.path) {
        url.path = "/";
    }

    if (strcasecmp(url.scheme, "https") == 0) {
        app_ctx.using_ssl = 1;
    }
    else {
        app_ctx.using_ssl = 0;
    }

    if (strcasecmp(method, "HEAD") == 0) {
        app_ctx.head_request = 1;
    }
    else {
        app_ctx.head_request = 0;
    }

    app_ctx.hostinfo = url.hostinfo;
    app_ctx.pem_path = pem_path;
    app_ctx.pem_pwd = pem_pwd;

    context = serf_context_create(pool);
    app_ctx.serf_ctx = context;

    if (proxy)
    {
        apr_sockaddr_t *proxy_address = NULL;
        apr_port_t proxy_port;
        char *proxy_host;
        char *proxy_scope;

        status = apr_parse_addr_port(&proxy_host, &proxy_scope, &proxy_port, proxy, pool);
        if (status)
        {
            printf("Cannot parse proxy hostname/port: %d\n", status);
            apr_pool_destroy(pool);
            exit(1);
        }

        if (!proxy_host)
        {
            printf("Proxy hostname must be specified\n");
            apr_pool_destroy(pool);
            exit(1);
        }

        if (!proxy_port)
        {
            printf("Proxy port must be specified\n");
            apr_pool_destroy(pool);
            exit(1);
        }

        status = apr_sockaddr_info_get(&proxy_address, proxy_host, APR_UNSPEC,
                                       proxy_port, 0, pool);

        if (status)
        {
            printf("Cannot resolve proxy address '%s': %d\n", proxy_host, status);
            apr_pool_destroy(pool);
            exit(1);
        }

        serf_config_proxy(context, proxy_address);
    }

    if (username)
    {
        serf_config_authn_types(context, SERF_AUTHN_ALL);
    }
    else
    {
        serf_config_authn_types(context, SERF_AUTHN_NTLM | SERF_AUTHN_NEGOTIATE);
    }

    serf_config_credentials_callback(context, credentials_callback);

    /* Setup debug logging */
    if (debug)
    {
        serf_log_output_t *output;
        apr_status_t status;

        status = serf_logging_create_stream_output(&output,
                                                   context,
                                                   SERF_LOG_DEBUG,
                                                   SERF_LOGCOMP_ALL_MSG,
                                                   SERF_LOG_DEFAULT_LAYOUT,
                                                   stderr,
                                                   pool);

        if (!status)
            serf_logging_add_output(context, output);
    }

    /* ### Connection or Context should have an allocator? */
    app_ctx.bkt_alloc = bkt_alloc;

    connections = apr_pcalloc(pool, conn_count * sizeof(serf_connection_t*));
    for (i = 0; i < conn_count; i++)
    {
        conn_baton_t *conn_ctx = apr_pcalloc(pool, sizeof(*conn_ctx));
        conn_ctx->app = &app_ctx;
        conn_ctx->ssl_ctx = NULL;

        status = serf_connection_create2(&connections[i], context, url,
                                         conn_setup, conn_ctx,
                                         closed_connection, conn_ctx,
                                         pool);
        if (status) {
            printf("Error creating connection: %d\n", status);
            apr_pool_destroy(pool);
            exit(1);
        }

        serf_connection_set_max_outstanding_requests(connections[i], inflight);
    }

    handler_ctx.completed_requests = 0;
    handler_ctx.print_headers = print_headers;

#if APR_VERSION_AT_LEAST(1, 3, 0)
    apr_file_open_flags_stdout(&handler_ctx.output_file, APR_BUFFERED, pool);
#else
    apr_file_open_stdout(&handler_ctx.output_file, pool);
#endif

    handler_ctx.host = url.hostinfo;
    handler_ctx.method = method;
    handler_ctx.path = apr_pstrcat(pool,
                                   url.path,
                                   url.query ? "?" : "",
                                   url.query ? url.query : "",
                                   NULL);
    handler_ctx.username = username;
    handler_ctx.password = password;
    handler_ctx.auth_attempts = 0;

    handler_ctx.req_body_path = req_body_path;

    handler_ctx.acceptor = accept_response;
    handler_ctx.acceptor_baton = &app_ctx;
    handler_ctx.handler = handle_response;
    handler_ctx.req_hdrs = req_hdrs;

    for (i = 0; i < count; i++) {
        /* We don't need the returned request here. */
        serf_connection_request_create(connections[i % conn_count],
                                       setup_request, &handler_ctx);
    }

    while (1) {
        status = serf_context_run(context, SERF_DURATION_FOREVER, pool);
        if (APR_STATUS_IS_TIMEUP(status))
            continue;
        if (status) {
            char buf[200];
            const char *err_string;
            err_string = serf_error_string(status);
            if (!err_string) {
                err_string = apr_strerror(status, buf, sizeof(buf));
            }

            printf("Error running context: (%d) %s\n", status, err_string);
            apr_pool_destroy(pool);
            exit(1);
        }
        if (apr_atomic_read32(&handler_ctx.completed_requests) >= count) {
            break;
        }
        /* Debugging purposes only! */
        serf_debug__closed_conn(app_ctx.bkt_alloc);
    }

    apr_file_close(handler_ctx.output_file);

    for (i = 0; i < conn_count; i++)
    {
        serf_connection_close(connections[i]);
    }

    apr_pool_destroy(pool);
    return 0;
}
Beispiel #7
0
/* Implements svn_config_enumerator2_t. */
static svn_boolean_t
add_memcache_server(const char *name,
                    const char *value,
                    void *baton,
                    apr_pool_t *pool)
{
  struct ams_baton *b = baton;
  char *host, *scope;
  apr_port_t port;
  apr_status_t apr_err;
  apr_memcache_server_t *server;

  apr_err = apr_parse_addr_port(&host, &scope, &port,
                                value, pool);
  if (apr_err != APR_SUCCESS)
    {
      b->err = svn_error_wrap_apr(apr_err,
                                  _("Error parsing memcache server '%s'"),
                                  name);
      return FALSE;
    }

  if (scope)
    {
      b->err = svn_error_createf(SVN_ERR_BAD_SERVER_SPECIFICATION, NULL,
                                  _("Scope not allowed in memcache server "
                                    "'%s'"),
                                  name);
      return FALSE;
    }
  if (!host || !port)
    {
      b->err = svn_error_createf(SVN_ERR_BAD_SERVER_SPECIFICATION, NULL,
                                  _("Must specify host and port for memcache "
                                    "server '%s'"),
                                  name);
      return FALSE;
    }

  /* Note: the four numbers here are only relevant when an
     apr_memcache_t is being shared by multiple threads. */
  apr_err = apr_memcache_server_create(b->memcache_pool,
                                       host,
                                       port,
                                       0,  /* min connections */
                                       5,  /* soft max connections */
                                       10, /* hard max connections */
                                       /*  time to live (in microseconds) */
                                       apr_time_from_sec(50),
                                       &server);
  if (apr_err != APR_SUCCESS)
    {
      b->err = svn_error_wrap_apr(apr_err,
                                  _("Unknown error creating memcache server"));
      return FALSE;
    }

  apr_err = apr_memcache_add_server(b->memcache, server);
  if (apr_err != APR_SUCCESS)
    {
      b->err = svn_error_wrap_apr(apr_err,
                                  _("Unknown error adding server to memcache"));
      return FALSE;
    }

  return TRUE;
}
/*--------------------------------------------------------------------------*/
static int 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 = "advertise_init_module_tag";
    apr_pool_t *pproc = s->process->pool;
    apr_thread_t *tp;
    mod_advertise_config *mconf = ap_get_module_config(s->module_config, &advertise_module);
    int advertisefound = 0;
    server_rec *server = s;

    /* Advertise directive in more than one VirtualHost: not supported */
    while (server) {
        mod_advertise_config *conf = ap_get_module_config(server->module_config, &advertise_module);
        if (conf->ma_advertise_server == server) {
            if (advertisefound) {
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                         "mod_advertise: directive in more than one VirtualHost: not supported");
                return !OK;
            } else
                advertisefound = -1;
        }
        server = server->next;
    }

    /* Our server */
    server = s;
    while (server) {
        mconf = ap_get_module_config(server->module_config, &advertise_module);
        if (mconf->ma_advertise_server == server)
            break;
        server = server->next;
    }

    apr_pool_userdata_get((void *)&magd, pk, pproc);
    if (!magd) {
        if (!(magd = apr_pcalloc(pproc, sizeof(ma_global_data_t))))
            return apr_get_os_error();
        apr_pool_create(&magd->ppool, pproc);
        apr_pool_userdata_set(magd, pk, apr_pool_cleanup_null, pproc);
        /* First time config phase -- skip. */
        return OK;
    }
#if defined(WIN32)
    {
        const char *ppid = getenv("AP_PARENT_PID");
        if (ppid) {
            ma_parent_pid = atol(ppid);
            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                "[%" APR_PID_T_FMT " - %" APR_PID_T_FMT
                "] in child post config hook",
                getpid(), ma_parent_pid);
            return OK;
        }
    }
#endif
    ma_server_rec = server; 
    if (mconf->ma_advertise_skey) {
        apr_md5_ctx_t mc;
        apr_md5_init(&mc);
        apr_md5_update(&mc, mconf->ma_advertise_skey, strlen(mconf->ma_advertise_skey));
        apr_md5_final(magd->ssalt, &mc);
    } else {
        /* If security key is not configured, the digest is calculated from zero bytes */
        memset(magd->ssalt, '\0', APR_MD5_DIGESTSIZE);
    }
    apr_uuid_get(&magd->suuid);
    magd->srvid[0] = '/';
    apr_uuid_format(&magd->srvid[1], &magd->suuid);
    if (!mconf->ma_advertise_srvh)
        mconf->ma_advertise_srvh = magd->srvid;
    /* Check if we have advertise set */
    if (mconf->ma_advertise_mode != ma_advertise_off &&
        mconf->ma_advertise_adrs) {
        rv = ma_group_join(mconf->ma_advertise_adrs, mconf->ma_advertise_port, mconf->ma_bind_adrs, mconf->ma_bind_port, pconf, s);
        if (rv != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                         "mod_advertise: multicast join failed for %s:%d.",
                         mconf->ma_advertise_adrs, mconf->ma_advertise_port);
            ma_advertise_run = 0;
        }
        else {
            ma_advertise_run  = 1;
            ma_advertise_stat = 200;
        }
    }

    /* Fill default values */
    if (!mconf->ma_advertise_srvm)  {
        if (ma_server_rec && ma_server_rec->server_scheme) {
            /* ServerName scheme://fully-qualified-domain-name[:port] */
            mconf->ma_advertise_srvm = apr_pstrdup(pconf, ma_server_rec->server_scheme);
        } else {
            mconf->ma_advertise_srvm = apr_pstrdup(pconf, "http");
        }
    }

    if (mconf->ma_advertise_srvs == NULL && ma_server_rec) {
        /*
         * That is not easy just use ServerAdvertise with the server parameter
         * if the code below doesn't work
         */
        char *ptr = NULL;
        int port = DEFAULT_HTTP_PORT;
        if (ma_server_rec->addrs && ma_server_rec->addrs->host_addr &&
            ma_server_rec->addrs->host_addr->next == NULL) {
            ptr = apr_psprintf(pproc, "%pI", ma_server_rec->addrs->host_addr);
        }
        /* Use don't use any as local address too */
        if (ptr == NULL || strncmp(ptr,"0.0.0.0", 7) == 0 || strncmp(ptr,"::",2) == 0) {
            if  ( ma_server_rec->port == 0 || ma_server_rec->port == 1) {
                if (ma_server_rec->addrs->host_addr->port != 0)
                    port = ma_server_rec->addrs->host_addr->port;
            } else {
                port = ma_server_rec->port;
             }
            ptr = apr_psprintf(pproc, "%s:%lu", ma_server_rec->server_hostname, port);
        }
        rv = apr_parse_addr_port(&mconf->ma_advertise_srvs,
                                 &mconf->ma_advertise_srvi,
                                 &mconf->ma_advertise_srvp,
                                 ptr, pproc);
        if (rv != APR_SUCCESS || !mconf->ma_advertise_srvs ||
                                 !mconf->ma_advertise_srvp) {
            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
                         "mod_advertise: Invalid ServerAdvertise Address %s",
                         ptr);
            return rv;
        }
    }

    /* prevent X-Manager-Address: (null):0  */
    if (!mconf->ma_advertise_srvs || !mconf->ma_advertise_srvp) {
            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
                         "mod_advertise: ServerAdvertise Address or Port not defined, Advertise disabled!!!");
            return OK;
    }

    /* Create parent management thread */
    is_mp_running = 1;
    rv = apr_thread_create(&tp, NULL, parent_thread, server, pconf);
    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
                     "mod_advertise: parent apr_thread_create");
        return rv;
    }
    apr_thread_detach(tp);

    /* Create cleanup pool that will be destroyed first
     * in future use new apr_pool_pre_cleanup_register from APR 1.3
     */
    apr_pool_create(&magd->cpool, pconf);
    apr_pool_cleanup_register(magd->cpool, magd, pconfig_cleanup,
                              apr_pool_cleanup_null);

    ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s,
                 "Advertise initialized for process %" APR_PID_T_FMT,
                 getpid());

    apr_pool_cleanup_register(magd->ppool, magd, process_cleanup,
                              apr_pool_cleanup_null);



    return OK;
}
apr_status_t
rainx_http_req(struct req_params_store* rps) {
	const dav_resource* resource = rps->resource;
	char* remote_uri = rps->service_address;
	char* req_type = rps->req_type;
	char* header = rps->header;
	char* data = rps->data_to_send;
	int data_length = rps->data_to_send_size;
	char** reply = &(rps->reply);
	apr_pool_t *local_pool = rps->pool;
	dav_rainx_server_conf *server_conf = resource_get_server_config(resource);

	if (NULL == resource || NULL == remote_uri ||
			NULL == req_type || NULL == server_conf) {
		DAV_ERROR_POOL(local_pool, APR_EINVAL, "One of these params is wrong: "
				"remote_uri=%p, req_type=%p, server_conf=%p"
				" (__FILE__:__LINE__)",
				remote_uri, req_type, server_conf);
		return APR_EINVAL;
	}

	const gboolean is_get = (0 == g_strcmp0(req_type, "GET"));

	/* Isolating Rawx IP and port */
	char *temp_remote_uri = apr_pstrdup(local_pool, remote_uri);
	char* last;
	char* full_remote_url = apr_strtok(temp_remote_uri, "/", &last);
	char* content_hexid = apr_pstrdup(local_pool, remote_uri + strlen(full_remote_url));

	char* remote_ip = NULL;
	char* scope_id = NULL;
	apr_port_t remote_port;
	apr_parse_addr_port(&remote_ip, &scope_id, &remote_port, full_remote_url, local_pool);
	/* ------- */

	/* Preparing the socket */
	apr_socket_t* sock;
	apr_sockaddr_t* sockaddr;
	apr_status_t status;

	if ((status = apr_sockaddr_info_get(&sockaddr, remote_ip, APR_INET, remote_port, 0, local_pool)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to connect to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_create(&sock, sockaddr->family, SOCK_STREAM, APR_PROTO_TCP, local_pool)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to create a socket to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_timeout_set(sock, server_conf->socket_timeout)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to set timeout for the socket to the rawx %s", full_remote_url);
		return status;
	}

	if ((status = apr_socket_connect(sock, sockaddr)) != APR_SUCCESS) {
		DAV_DEBUG_REQ(resource->info->request, 0, "unable to establish the connection to the rawx %s", full_remote_url);
		return status;
	}
	/* ------- */

	/* Forging the message */
	char* forged_header = apr_psprintf(local_pool, "%s %s HTTP/1.1\nHost: %s", req_type, content_hexid, full_remote_url);
	if (header)
		forged_header = apr_psprintf(local_pool, "%s\n%s", forged_header, header);
	if (data)
		forged_header = apr_psprintf(local_pool, "%s\nContent-Length: %d\n\n", forged_header, data_length);
	else
		forged_header = apr_psprintf(local_pool, "%s\n\n", forged_header);
	/* ------- */

	/* Sending the message */
	int remaining_to_send = strlen(forged_header);
	char* ptr_start = forged_header;
	apr_size_t send_buffer_size;
	while (remaining_to_send > 0) {
		if (remaining_to_send < REQUEST_BUFFER_SIZE)
			send_buffer_size = (apr_size_t)remaining_to_send;
		else
			send_buffer_size = REQUEST_BUFFER_SIZE;

		if ((status = apr_socket_send(sock, ptr_start, &send_buffer_size)) != APR_SUCCESS) {
            DAV_DEBUG_REQ(resource->info->request, 0, "failed to send the %s request to the rawx %s", req_type, full_remote_url);
            apr_status_t status_sav = status;
            apr_socket_close(sock);
            return status_sav;
        }

		remaining_to_send -= send_buffer_size;
		ptr_start = ptr_start + send_buffer_size;
	}
	if (NULL != data) {
		remaining_to_send = data_length;
		ptr_start = data;
		while (remaining_to_send > 0) {
			if (remaining_to_send < REQUEST_BUFFER_SIZE)
				send_buffer_size = (apr_size_t)remaining_to_send;
			else
				send_buffer_size = REQUEST_BUFFER_SIZE;

			if ((status = apr_socket_send(sock, ptr_start, &send_buffer_size)) != APR_SUCCESS) {
				DAV_DEBUG_REQ(resource->info->request, 0, "failed to send the %s request to the rawx %s", req_type, full_remote_url);
				apr_status_t status_sav = status;
				apr_socket_close(sock);
				return status_sav;
			}

			remaining_to_send -= send_buffer_size;
			ptr_start = ptr_start + send_buffer_size;
		}
	}

	if (is_get) {
		/* This avoids a ~5s delay in the communication */
		apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE);
	}

	DAV_DEBUG_REQ(resource->info->request, 0, "%s request to the rawx %s sent for the content %s", req_type, full_remote_url, content_hexid);
    /* ------ */

	/* Getting the reply */
	char* reply_ptr = *reply;
	apr_size_t total_size;
	if (!is_get)
		total_size = REPLY_BUFFER_SIZE; // PUT or DELETE
	else
		total_size = MAX_REPLY_HEADER_SIZE + data_length; // GET
	apr_size_t reply_size = (apr_size_t)total_size;
	apr_size_t total_replied_size;
	do {
		status = apr_socket_recv(sock, reply_ptr, &reply_size);
		reply_ptr += reply_size;
		total_replied_size = reply_ptr - *reply;
		/* Leave when OK, or error != timeout, or buffer full */
        if (status == APR_EOF || (status == APR_SUCCESS && !is_get) ||
				(reply_size == 0) ||
				total_replied_size >= total_size) {
            break;
		}
		/* Take care of overflows! */
		reply_size = total_size - total_replied_size;
	} while (total_replied_size < total_size);
	/* ------- */

	apr_socket_close(sock);

	return status;
}