예제 #1
0
파일: login-proxy.c 프로젝트: bjacke/core
static unsigned int login_proxy_delay_disconnect(struct login_proxy *proxy)
{
	struct login_proxy_record *rec = proxy->state_rec;
	const unsigned int max_delay =
		proxy->client->set->login_proxy_max_disconnect_delay;
	struct timeval disconnect_time_offset;
	unsigned int max_disconnects_per_sec, delay_msecs_since_ts, max_conns;
	int delay_msecs;

	if (rec->num_disconnects_since_ts == 0) {
		rec->disconnect_timestamp = ioloop_timeval;
		/* start from a slightly random timestamp. this way all proxy
		   processes will disconnect at slightly different times to
		   spread the load. */
		timeval_add_msecs(&rec->disconnect_timestamp,
				  rand() % PROXY_DISCONNECT_INTERVAL_MSECS);
	}
	rec->num_disconnects_since_ts++;
	if (proxy->to != NULL) {
		/* we were already lazily disconnecting this */
		return 0;
	}
	if (max_delay == 0) {
		/* delaying is disabled */
		return 0;
	}
	max_conns = rec->num_proxying_connections + rec->num_disconnects_since_ts;
	max_disconnects_per_sec = (max_conns + max_delay-1) / max_delay;
	if (rec->num_disconnects_since_ts <= max_disconnects_per_sec &&
	    rec->num_delayed_client_disconnects == 0) {
		/* wait delaying until we have 1 second's worth of clients
		   disconnected */
		return 0;
	}

	/* see at which time we should be disconnecting the client.
	   do it in 100ms intervals so the timeouts are triggered together. */
	disconnect_time_offset = rec->disconnect_timestamp;
	delay_msecs_since_ts = PROXY_DISCONNECT_INTERVAL_MSECS *
		(max_delay * rec->num_disconnects_since_ts *
		 (1000/PROXY_DISCONNECT_INTERVAL_MSECS) / max_conns);
	timeval_add_msecs(&disconnect_time_offset, delay_msecs_since_ts);
	delay_msecs = timeval_diff_msecs(&disconnect_time_offset, &ioloop_timeval);
	if (delay_msecs <= 0) {
		/* we already reached the time */
		return 0;
	}

	rec->num_delayed_client_disconnects++;
	proxy->delayed_disconnect = TRUE;
	proxy->to = timeout_add(delay_msecs, login_proxy_free_final, proxy);
	DLLIST_PREPEND(&login_proxies_disconnecting, proxy);
	return delay_msecs;
}
예제 #2
0
static void http_client_request_do_submit(struct http_client_request *req)
{
	struct http_client *client = req->client;
	struct http_client_host *host;
	const char *proxy_socket_path = client->set.proxy_socket_path;
	const struct http_url *proxy_url = client->set.proxy_url;
	bool have_proxy = (proxy_socket_path != NULL) || (proxy_url != NULL) ||
		(req->host_socket != NULL) || (req->host_url != NULL);
	const char *authority, *target;

	i_assert(req->state == HTTP_REQUEST_STATE_NEW);

	authority = http_url_create_authority(&req->origin_url);
	if (req->connect_tunnel) {
		/* connect requests require authority form for request target */
		target = authority;
	} else {
		/* absolute target url */
		target = t_strconcat
			(http_url_create_host(&req->origin_url), req->target, NULL);
	}

	/* determine what host to contact to submit this request */
	if (have_proxy) {
		if (req->host_socket != NULL) {               /* specific socket proxy */
			req->host_url = NULL;
		} else if (req->host_url != NULL) {           /* specific normal proxy */
			req->host_socket = NULL;
		} else if (req->origin_url.have_ssl &&
			!client->set.no_ssl_tunnel &&	!req->connect_tunnel) {
			req->host_url = &req->origin_url;           /* tunnel to origin server */
			req->ssl_tunnel = TRUE;
		} else if (proxy_socket_path != NULL) {
			req->host_socket = proxy_socket_path;       /* proxy on unix socket */
			req->host_url = NULL;
		} else {
			req->host_url = proxy_url;                  /* normal proxy server */
			req->host_socket = NULL;
		}
	} else {
		req->host_url = &req->origin_url;             /* origin server */
	}

	/* use submission date if no date is set explicitly */
	if (req->date == (time_t)-1)
		req->date = ioloop_time;
	
	/* prepare value for Host header */
	req->authority = p_strdup(req->pool, authority);

	/* debug label */
	req->label = p_strdup_printf(req->pool, "[Req%u: %s %s]", req->id, req->method, target);

	/* update request target */
	if (req->connect_tunnel || have_proxy)
		req->target = p_strdup(req->pool, target);

	if (!have_proxy) {
		/* if we don't have a proxy, CONNECT requests are handled by creating
		   the requested connection directly */
		req->connect_direct = req->connect_tunnel;
		if (req->connect_direct)
			req->urgent = TRUE;
	}

	if (req->timeout_time.tv_sec == 0) {
		if (req->timeout_msecs > 0) {
			req->timeout_time = ioloop_timeval;
			timeval_add_msecs(&req->timeout_time, req->timeout_msecs);
		} else if (	client->set.request_absolute_timeout_msecs > 0) {
			req->timeout_time = ioloop_timeval;
			timeval_add_msecs(&req->timeout_time, client->set.request_absolute_timeout_msecs);
		}
	}

	host = http_client_host_get(req->client, req->host_url);
	req->state = HTTP_REQUEST_STATE_QUEUED;

	http_client_host_submit_request(host, req);
}
예제 #3
0
void http_client_request_delay_msecs(struct http_client_request *req,
	unsigned int msecs)
{
	req->release_time = ioloop_timeval;
	timeval_add_msecs(&req->release_time, msecs);
}