/*--------------------------------------------------------------------------*/ 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; }
/* * 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; }
/* * 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; }
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; }
/* 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; }