Exemple #1
0
void echo_client_wcb_send(EV_P_ ev_io *w, int tev)
{
	int sent_nb;
	echo_client_t *c = aux_memberof(echo_client_t, wev_send, w);

	sent_nb = aux_unix_send(w->fd, c->to_send_beg, c->to_send_size);
	/* sent_nb = aux_unix_send(w->fd, OUTPUT, sizeof(OUTPUT) - 1); */
	/* fprintf(stderr, "sent %d bytes (%d: %s)\n", sent_nb, errno, strerror(errno)); */

	if (0 > sent_nb)
	{
		if (EAGAIN == errno)
		{
			return;
		}

		fprintf(stderr, "send error fd=%d (%d: %s)\n", w->fd, errno, strerror(errno));
		echo_client_del(c);
		return;
	}

	c->to_send_beg += sent_nb;
	c->to_send_size -= sent_nb;

	if (c->to_send_size > 0)
	{
		return;
	}

	ev_io_stop(loop, &c->wev_send);
}
Exemple #2
0
static
void ugh_subreq_wcb_connect(EV_P_ ev_io *w, int tev)
{
	ugh_subreq_t *r = aux_memberof(ugh_subreq_t, wev_connect, w);

	if (EV_READ & tev)
	{
		int optval = 0;
		socklen_t optlen = sizeof(optval);

		if (0 > getsockopt(w->fd, SOL_SOCKET, SO_ERROR, &optval, &optlen))
		{
			optval = errno;
		}

		ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR, optval);
		return;
	}

	ev_io_stop(loop, &r->wev_connect);
	ev_timer_stop(loop, &r->wev_timeout_connect);

	r->connection_time = ev_now(loop) - r->response_time;

	ev_io_start(loop, &r->wev_send);
}
Exemple #3
0
void echo_server_wcb_accept(EV_P_ ev_io *w, int tev)
{
	int sd, rc;
	struct sockaddr_in addr;
	socklen_t addrlen;

	echo_server_t *s = aux_memberof(echo_server_t, wev_accept, w);

	addrlen = sizeof(addr);

	pthread_mutex_lock(&accept_mtx);
	sd = accept(w->fd, (struct sockaddr *) &addr, &addrlen);
	pthread_mutex_unlock(&accept_mtx);

/* fprintf(stderr, "accept in thread=%d fd=%d (%d: %s)\n", (int) pthread_self(), sd, errno, strerror(errno)); */

	if (0 > sd)
	{
		return;
	}

	if (0 > (rc = aux_set_nonblk(sd, 1)))
	{
		return;
	}

#if 0
	if (0 > (rc = aux_set_sckopt(sd, IPPROTO_TCP, TCP_NODELAY, 1)))
	{
		fprintf(stderr, "sockopt TCP_NODELAY error\n");
	}
#endif

	echo_client_add(s, sd, &addr);
}
Exemple #4
0
void wcb_recv(EV_P_ ev_io *w, int tev)
{
	client_t *c = aux_memberof(client_t, wev_recv, w);

	char buf [4096];

	int nb = aux_unix_recv(w->fd, buf, 4096);

	double time = ev_now(loop) - c->ts;
	times_sum += time;
	times_count++;
	if (times_max < time) times_max = time;
	if (times_min > time) times_min = time;

	/* fprintf(stderr, "recv fd=%d %f (%d bytes) %.*s\n", w->fd, ev_now(loop) - c->ts, nb, nb, buf); */
	/* if (nb != 57) fprintf(stderr, "recv error %d bytes\n", nb); */

	if (0 > nb)
	{
		if (errno == EAGAIN)
		{
			return;
		}

		fprintf(stderr, "recv error fd=%d (%d: %s)\n", w->fd, errno, strerror(errno));
		client_del(c);
		return;
	}
}
Exemple #5
0
void wcb_send(EV_P_ ev_io *w, int tev)
{
	client_t *c = aux_memberof(client_t, wev_send, w);

	for (; c->to_send; c->to_send--)
	{
		int rc = client_send(c);
		if (0 > rc) return;
	}

	ev_io_stop(loop, &c->wev_send);
}
Exemple #6
0
void wcb_timeout(EV_P_ ev_timer *w, int tev)
{
	client_t *c = aux_memberof(client_t, wev_timeout, w);

	c->to_send++;

	ev_io_start(loop, &c->wev_send);

#if 0
	int rc = client_send(c);
	if (0 > rc) return;
#endif
}
Exemple #7
0
static
void ugh_subreq_wcb_send(EV_P_ ev_io *w, int tev)
{
	int rc;

	ugh_subreq_t *r = aux_memberof(ugh_subreq_t, wev_send, w);

	/* errno = 0; */

	rc = aux_unix_send(w->fd, r->b_send.data + r->b_send.rpos, r->b_send.wpos - r->b_send.rpos);
	log_debug("subreq send: %d: %.*s", rc, (int) (r->b_send.wpos - r->b_send.rpos), r->b_send.data + r->b_send.rpos);

	if (0 > rc)
	{
		log_warn("send error %.*s%s%.*s (%d: %s)", (int) r->u.uri.size, r->u.uri.data, r->u.args.size ? "?" : "", (int) r->u.args.size, r->u.args.data, errno, aux_strerror(errno));
		ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR);
		return;
	}

	/* log_debug("send %d bytes", rc); */

	if (0 == rc)
	{
		return;
	}

	if (UGH_TIMEOUT_ONCE == r->timeout_type)
	{
		ev_timer_again(loop, &r->wev_timeout);
	}

	r->b_send.rpos += rc;

	if (r->b_send.rpos == r->b_send.wpos)
	{
		ev_io_stop(loop, &r->wev_send);
		ev_io_start(loop, &r->wev_recv);
		return;
	}
}
Exemple #8
0
void wcb_connect(EV_P_ ev_io *w, int tev)
{
	client_t *c = aux_memberof(client_t, wev_connect, w);

	if (EV_READ & tev)
	{
		fprintf(stderr, "conn error fd=%d\n", w->fd);
		client_del(c);
		return;
	}

#if 0
	int rc = client_send(c);
	if (0 > rc) return;
#endif

	c->to_send = 1;

	ev_io_stop(loop, &c->wev_connect);
	ev_io_start(loop, &c->wev_send);
	ev_io_start(loop, &c->wev_recv);
}
Exemple #9
0
static
void ugh_subreq_wcb_connect(EV_P_ ev_io *w, int tev)
{
	ugh_subreq_t *r = aux_memberof(ugh_subreq_t, wev_connect, w);

	if (EV_READ & tev)
	{
		int optval = 0;
		socklen_t optlen = sizeof(optval);

		if (0 > getsockopt(w->fd, SOL_SOCKET, SO_ERROR, &optval, &optlen))
		{
			optval = errno;
		}

		log_warn("conn error %.*s%s%.*s (%d: %s)", (int) r->u.uri.size, r->u.uri.data, r->u.args.size ? "?" : "", (int) r->u.args.size, r->u.args.data, optval, aux_strerror(optval));
		ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR);
		return;
	}

	ev_io_stop(loop, &r->wev_connect);
	ev_io_start(loop, &r->wev_send);
}
Exemple #10
0
void ugh_wcb_silent(EV_P_ ev_timer *w, int tev)
{
	if (0 != aux_terminate)
	{
		ev_timer_stop(EV_A_ w);
		ev_break(EV_A_ EVBREAK_ALL);
		return;
	}

	if (0 != aux_rotatelog)
	{
		ugh_daemon_t *d;

		aux_rotatelog = 0;
		d = aux_memberof(ugh_daemon_t, wev_silent, w);

		if (-1 == log_rotate(d->cfg.log_error))
		{
			log_warn("log_rotate(%s) (%d: %s)", d->cfg.log_error,
				errno, aux_strerror(errno));
		}
	}
}
Exemple #11
0
static
void ugh_subreq_wcb_recv(EV_P_ ev_io *w, int tev)
{
	ugh_subreq_t *r = aux_memberof(ugh_subreq_t, wev_recv, w);

	/* errno = 0; */

	int nb = aux_unix_recv(w->fd, r->buf_recv.data, r->buf_recv.size);
	log_debug("subreq recv: %d: %.*s", nb, nb, r->buf_recv.data);

	if (0 == nb)
	{
		if (r->content_length != UGH_RESPONSE_CLOSE_AFTER_BODY)
		{
			/*
			 * NOTE: recv(2) will never fail with EPIPE, so I'm using it here
			 * to get meaningful error message in ugh_subreq_del'
			 */
			log_warn("upstream prematurely closed connection");
			ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR, EPIPE);
		}
		else
		{
			ugh_subreq_del(r, UGH_UPSTREAM_FT_OFF, 0);
		}

		return;
	}

	if (0 > nb)
	{
		if (EAGAIN == errno)
		{
			if (UGH_TIMEOUT_ONCE == r->timeout_type)
			{
				ev_timer_again(loop, &r->wev_timeout);
			}

			return;
		}

		ugh_subreq_del(r, UGH_UPSTREAM_FT_ERROR, errno);
		return;
	}

	r->buf_recv.data += nb;
	r->buf_recv.size -= nb;

	if (UGH_TIMEOUT_ONCE == r->timeout_type)
	{
		ev_timer_again(loop, &r->wev_timeout);
	}

	if (NULL == r->body.data)
	{
		int status = ugh_parser_subreq(r, r->buf_recv.data - nb, nb);

		if (UGH_AGAIN == status)
		{
			return;
		}

		if (UGH_ERROR == status)
		{
			ugh_subreq_del(r, UGH_UPSTREAM_FT_INVALID_HEADER, 0);
			return;
		}

		ugh_header_t *hdr_content_length = ugh_subreq_header_get_nt(r, "Content-Length");

		if (0 != hdr_content_length->value.size)
		{
			r->content_length = atoi(hdr_content_length->value.data);

			if (r->content_length > r->buf_recv.size + (r->buf_recv.data - r->request_end))
			{
				r->body.data = aux_pool_nalloc(r->c->pool, r->content_length);
				r->body.size = r->buf_recv.data - r->request_end;

				memcpy(r->body.data, r->request_end, r->body.size);

				r->buf_recv.data = r->body.data + r->body.size;
				r->buf_recv.size = r->content_length - r->body.size;
			}
			else
			{
				r->body.data = r->request_end;
				r->body.size = r->buf_recv.data - r->request_end;
			}
		}
		else
		{
			ugh_header_t *hdr_transfer_encoding = ugh_subreq_header_get_nt(r, "Transfer-Encoding");

			if (7 == hdr_transfer_encoding->value.size && 0 == strncmp(hdr_transfer_encoding->value.data, "chunked", 7))
			{
				r->content_length = UGH_RESPONSE_CHUNKED;

				r->chunk_body_size = UGH_CHUNKS_BUF;
				r->body.data = aux_pool_nalloc(r->c->pool, r->chunk_body_size);
				r->body.size = 0;

				char *next_chunk = r->request_end;

				for (;;)
				{
					status = ugh_parser_chunks(r, next_chunk, r->buf_recv.data - next_chunk);

					if (UGH_AGAIN == status)
					{
						r->buf_recv.size += r->buf_recv.data - r->request_end;
						r->buf_recv.data = r->request_end;
						r->chunk_start = 0;
						return;
					}

					if (UGH_ERROR == status)
					{
						ugh_subreq_del(r, UGH_UPSTREAM_FT_INVALID_HEADER, 0);
						return;
					}

					if (0 == r->chunk_size)
					{
						ugh_subreq_del(r, UGH_UPSTREAM_FT_OFF, 0);
						return;
					}

					size_t recv_len = r->buf_recv.data - r->chunk_start;

					if (r->chunk_size > recv_len)
					{
						ugh_subreq_copy_chunk(r, r->chunk_start, recv_len);

						r->chunk_size -= recv_len;

						r->buf_recv.size += r->buf_recv.data - r->request_end;
						r->buf_recv.data = r->request_end;

						r->chunk_start = r->buf_recv.data;

						break;
					}
					else
					{
						ugh_subreq_copy_chunk(r, r->chunk_start, r->chunk_size);

						next_chunk = r->chunk_start + r->chunk_size;

						r->chunk_size = 0;
						r->chunk_start = 0;
					}
				}
			}
			else /* http/1.0 close after body response */
			{
				r->content_length = UGH_RESPONSE_CLOSE_AFTER_BODY;

				r->body.data = r->request_end;
				r->body.size = r->buf_recv.data - r->request_end;

				if (r->buf_recv.size == 0)
				{
					char *old_body = r->body.data;

					r->body.data = aux_pool_nalloc(r->c->pool, r->body.size * 2);

					memcpy(r->body.data, old_body, r->body.size);

					r->buf_recv.data = r->body.data + r->body.size;
					r->buf_recv.size = r->body.size;
				}
			}
		}
	}
	else if (r->content_length == UGH_RESPONSE_CHUNKED)
	{
		for (;;)
		{
			char *next_chunk = r->buf_recv.data - nb;

			if (r->chunk_start)
			{
				size_t recv_len = r->buf_recv.data - r->chunk_start;

				if (r->chunk_size > recv_len)
				{
					ugh_subreq_copy_chunk(r, r->chunk_start, recv_len);

					r->chunk_size -= recv_len;

					r->buf_recv.data -= nb;
					r->buf_recv.size += nb;

					r->chunk_start = r->buf_recv.data;

					break;
				}
				else
				{
					ugh_subreq_copy_chunk(r, r->chunk_start, r->chunk_size);

					next_chunk = r->chunk_start + r->chunk_size;

					r->chunk_size = 0;
				}
			}

			int status = ugh_parser_chunks(r, next_chunk, r->buf_recv.data - next_chunk);

			if (UGH_AGAIN == status)
			{
				r->buf_recv.data -= nb;
				r->buf_recv.size += nb;
				r->chunk_start = 0;
				return;
			}

			if (UGH_ERROR == status)
			{
				ugh_subreq_del(r, UGH_UPSTREAM_FT_INVALID_HEADER, 0);
				return;
			}

			if (0 == r->chunk_size)
			{
				ugh_subreq_del(r, UGH_UPSTREAM_FT_OFF, 0);
			}
		}
	}
	else if (r->content_length == UGH_RESPONSE_CLOSE_AFTER_BODY)
	{
		r->body.size += nb;

		if (r->buf_recv.size == 0)
		{
			char *old_body = r->body.data;

			r->body.data = aux_pool_nalloc(r->c->pool, r->body.size * 2);

			memcpy(r->body.data, old_body, r->body.size);

			r->buf_recv.data = r->body.data + r->body.size;
			r->buf_recv.size = r->body.size;
		}
	}
	else
	{
		r->body.size += nb;
	}

	if (r->body.size == r->content_length)
	{
		uint32_t ft_type = UGH_UPSTREAM_FT_OFF;

		switch (r->status)
		{
		case 400: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 401: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 402: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 403: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 404: ft_type = UGH_UPSTREAM_FT_HTTP_404; break;
		case 405: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 406: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 407: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 408: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 409: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 410: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 411: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 412: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 413: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 414: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 415: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 416: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 417: ft_type = UGH_UPSTREAM_FT_HTTP_4XX; break;
		case 500: ft_type = UGH_UPSTREAM_FT_HTTP_500; break;
		case 501: ft_type = UGH_UPSTREAM_FT_HTTP_5XX; break;
		case 502: ft_type = UGH_UPSTREAM_FT_HTTP_502; break;
		case 503: ft_type = UGH_UPSTREAM_FT_HTTP_503; break;
		case 504: ft_type = UGH_UPSTREAM_FT_HTTP_504; break;
		case 505: ft_type = UGH_UPSTREAM_FT_HTTP_5XX; break;
		case 506: ft_type = UGH_UPSTREAM_FT_HTTP_5XX; break;
		case 507: ft_type = UGH_UPSTREAM_FT_HTTP_5XX; break;
		}

		ugh_subreq_del(r, ft_type, 0);
	}
}
Exemple #12
0
void echo_client_wcb_recv(EV_P_ ev_io *w, int tev)
{
	int nb;
	echo_client_t *c = aux_memberof(echo_client_t, wev_recv, w);

	int rem_size = c->to_send + TO_SEND_SIZE - (c->to_send_beg + c->to_send_size);

	if (rem_size < 32)
	{
		/* fprintf(stderr, "rem_size=%d, c->to_send_size=%u, fd=%d\n", rem_size, (unsigned) c->to_send_size, w->fd); */
		memcpy(c->to_send, c->to_send_beg, c->to_send_size);

		c->to_send_beg = c->to_send;
		rem_size = TO_SEND_SIZE - c->to_send_size;

		/* fprintf(stderr, "rem_size=%d\n", rem_size); */
	}

	nb = aux_unix_recv(w->fd, c->to_send_beg + c->to_send_size, rem_size);
	/* fprintf(stderr, "recv %d bytes (%d: %s) %.*s\n", nb, errno, strerror(errno), nb, buf); */

	if (0 > nb)
	{
		if (EAGAIN == errno)
		{
			ev_timer_again(loop, &c->wev_timeout);
			return;
		}

		fprintf(stderr, "recv error fd=%d (%d: %s)\n", w->fd, errno, strerror(errno));
		echo_client_del(c);
		return;
	}

	if (0 == nb)
	{
		/* fprintf(stderr, "recv done fd=%d\n", w->fd); */
		/* echo_client_del(c); */
		return;
	}

	c->to_send_size += nb;

	int sent_nb;

	sent_nb = aux_unix_send(w->fd, c->to_send_beg, c->to_send_size);
	/* nb = aux_unix_send(w->fd, OUTPUT, sizeof(OUTPUT) - 1); */
	/* fprintf(stderr, "sent %d bytes (%d: %s)\n", nb, errno, strerror(errno)); */

	if (0 > sent_nb)
	{
		if (EAGAIN == errno)
		{
			ev_io_start(loop, &c->wev_send);
			return;
		}

		fprintf(stderr, "send error fd=%d (%d: %s)\n", w->fd, errno, strerror(errno));
		echo_client_del(c);
		return;
	}

	c->to_send_beg += sent_nb;
	c->to_send_size -= sent_nb;

	if (c->to_send_size > 0)
	{
		ev_io_start(loop, &c->wev_send);
		return;
	}

#if 0
	nb = aux_unix_send(w->fd, buf, nb);
	/* fprintf(stderr, "sent %d bytes (%d: %s)\n", nb, errno, strerror(errno)); */

	if (0 > nb)
	{
		fprintf(stderr, "send error fd=%d (%d: %s)\n", w->fd, errno, strerror(errno));
		echo_client_del(c);
		return;
	}

	ev_timer_again(loop, &c->wev_timeout);
#endif
}
Exemple #13
0
static
void ugh_client_wcb_timeout(EV_P_ ev_timer *w, int tev)
{
	ugh_client_t *c = aux_memberof(ugh_client_t, wev_timeout, w);
	ugh_client_del(c);
}
Exemple #14
0
static
void ugh_client_wcb_send(EV_P_ ev_io *w, int tev)
{
	int rc;
	ugh_client_t *c = aux_memberof(ugh_client_t, wev_send, w);

	if (0 == c->buf_send.size)
	{
		ugh_client_del(c);
		return;
	}

	if (NULL == c->iov)
	{
		c->iov_num = ugh_module_handles_size + 1;

		c->iov = aux_pool_malloc(c->pool, c->iov_num * sizeof(c->iov[0]));

		if (NULL == c->iov)
		{
			ugh_client_del(c);
			return;
		}

		c->iov[0].iov_base = c->buf_send.data;
		c->iov[0].iov_len  = c->buf_send.size;

		size_t i;

		for (i = 0; i < c->iov_num - 1; ++i)
		{
			c->iov[i+1].iov_base = c->bufs[i].data;
			c->iov[i+1].iov_len  = c->bufs[i].size;
		}
	}

	rc = writev(w->fd, c->iov, c->iov_num);
	log_debug("client send: %d: %.*s", rc, (int) c->iov[0].iov_len, (char *) c->iov[0].iov_base);

	if (0 > rc)
	{
		log_warn("err writev(%d,%d) (%d: %s)", w->fd, rc, errno, aux_strerror(errno));
		ugh_client_del(c);
		return;
	}

	/* log_debug("end writev(%d,%d)", w->fd, rc); */

	if (0 == rc)
	{
		return;
	}

	size_t i;

	for (i = 0; i < c->iov_num; ++i)
	{
		if (rc < c->iov[i].iov_len)
		{
			c->iov[i].iov_base += rc;
			c->iov[i].iov_len  -= rc;

			c->iov += i;
			c->iov_num -= i;

			/* TODO send timeout */

			return;
		}

		rc -= c->iov[i].iov_len;
	}

	ugh_client_del(c);
}
Exemple #15
0
static
void ugh_subreq_wcb_timeout_connect(EV_P_ ev_timer *w, int tev)
{
	ugh_subreq_t *r = aux_memberof(ugh_subreq_t, wev_timeout_connect, w);
	ugh_subreq_del(r, UGH_UPSTREAM_FT_TIMEOUT_CONNECT, 0);
}
Exemple #16
0
void echo_client_wcb_timeout(EV_P_ ev_timer *w, int tev)
{
	echo_client_t *c = aux_memberof(echo_client_t, wev_timeout, w);
	echo_client_del(c);
}
Exemple #17
0
static
void ugh_client_wcb_recv(EV_P_ ev_io *w, int tev)
{
	int nb;
	ugh_client_t *c = aux_memberof(ugh_client_t, wev_recv, w);

	nb = aux_unix_recv(w->fd, c->buf_recv.data, c->buf_recv.size);
	log_debug("client recv: %d: %.*s", nb, nb, c->buf_recv.data);

	if (0 == nb)
	{
		ugh_client_del(c);
		return;
	}

	if (0 > nb)
	{
		if (EAGAIN == errno)
		{
			ev_timer_again(loop, &c->wev_timeout);
			return;
		}

		ugh_client_del(c);
		return;
	}

	c->buf_recv.data += nb;
	c->buf_recv.size -= nb;

	ev_timer_again(loop, &c->wev_timeout);

	if (NULL == c->request_end)
	{
		int status = ugh_parser_client(c, c->buf_recv.data - nb, nb);

		if (UGH_AGAIN == status)
		{
			return;
		}

		if (UGH_HTTP_BAD_REQUEST <= status)
		{
			ugh_client_send(c, status);
			return;
		}

		if (UGH_HTTP_POST == c->method)
		{
			ugh_header_t *hdr_content_length = ugh_client_header_get_nt(c, "Content-Length");

			if (0 != hdr_content_length->value.size)
			{
				c->content_length = atoi(hdr_content_length->value.data);

				if (c->content_length > (c->buf_recv.size + (c->buf_recv.data - c->request_end)))
				{
					c->body.data = aux_pool_nalloc(c->pool, c->content_length);
					c->body.size = c->buf_recv.data - c->request_end;

					memcpy(c->body.data, c->request_end, c->body.size);

					c->buf_recv.data = c->body.data + c->body.size;
					c->buf_recv.size = c->content_length - c->body.size;
				}
				else
				{
					c->body.data = c->request_end;
					c->body.size = c->buf_recv.data - c->request_end;
				}

				if (c->body.size < c->content_length)
				{
					return;
				}
			}
		}
	}
	else if (UGH_HTTP_POST == c->method)
	{
		c->body.size += nb;

		if (c->body.size < c->content_length)
		{
			return;
		}
	}

	ev_io_stop(loop, &c->wev_recv);
	ev_timer_stop(loop, &c->wev_timeout);

#if 1 /* prepare post args */
	ugh_header_t *hdr_content_type = ugh_client_header_get_nt(c, "Content-Type");

	if (sizeof("application/x-www-form-urlencoded") - 1 == hdr_content_type->value.size &&
		0 == strncmp(hdr_content_type->value.data, "application/x-www-form-urlencoded", hdr_content_type->value.size))
	{
		ugh_parser_client_body(c, c->body.data, c->body.size);
	}
#endif

#if 1 /* UGH_CORO ENABLE */
	c->stack = aux_pool_malloc(c->pool, UGH_CORO_STACK);

	if (NULL == c->stack)
	{
		ugh_client_send(c, UGH_HTTP_INTERNAL_SERVER_ERROR);
		return;
	}

	coro_create(&c->ctx, ugh_client_ccb_handle, c, c->stack, UGH_CORO_STACK, &ctx_main);
	is_main_coro = 0;
	coro_transfer(&ctx_main, &c->ctx);
	is_main_coro = 1;
#endif

#if 0 /* UGH_CORO DISABLE */
	ugh_client_ccb_handle(c);
#endif
}