예제 #1
0
파일: client.c 프로젝트: alepharchives/mrps
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;
	}
}
예제 #2
0
파일: subreq.c 프로젝트: dimarik/ugh
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);
	}
}
예제 #3
0
파일: thread-honest.c 프로젝트: bachan/echo
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
}
예제 #4
0
파일: client.c 프로젝트: anhdocphys/ugh
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
}