aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/lib/http/httpcli.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/lib/http/httpcli.c')
-rw-r--r--src/core/lib/http/httpcli.c140
1 files changed, 81 insertions, 59 deletions
diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c
index f22721ac8f..18135bcb58 100644
--- a/src/core/lib/http/httpcli.c
+++ b/src/core/lib/http/httpcli.c
@@ -39,12 +39,14 @@
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
+#include <grpc/support/useful.h>
#include "src/core/lib/http/format_request.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/endpoint.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#include "src/core/lib/iomgr/resolve_address.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/support/string.h"
@@ -59,16 +61,16 @@ typedef struct {
gpr_timespec deadline;
int have_read_byte;
const grpc_httpcli_handshaker *handshaker;
- grpc_httpcli_response_cb on_response;
- void *user_data;
+ grpc_closure *on_done;
grpc_httpcli_context *context;
- grpc_pollset *pollset;
+ grpc_polling_entity *pollent;
grpc_iomgr_object iomgr_obj;
gpr_slice_buffer incoming;
gpr_slice_buffer outgoing;
grpc_closure on_read;
grpc_closure done_write;
grpc_closure connected;
+ grpc_error *overall_error;
} internal_request;
static grpc_httpcli_get_override g_get_override = NULL;
@@ -76,6 +78,7 @@ static grpc_httpcli_post_override g_post_override = NULL;
static void plaintext_handshake(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint, const char *host,
+ gpr_timespec deadline,
void (*on_done)(grpc_exec_ctx *exec_ctx,
void *arg,
grpc_endpoint *endpoint)) {
@@ -93,14 +96,14 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
grpc_pollset_set_destroy(context->pollset_set);
}
-static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
+static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
+ grpc_error *due_to_error);
static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
- int success) {
- grpc_pollset_set_del_pollset(exec_ctx, req->context->pollset_set,
- req->pollset);
- req->on_response(exec_ctx, req->user_data,
- success ? &req->parser.http.response : NULL);
+ grpc_error *error) {
+ grpc_polling_entity_del_from_pollset_set(exec_ctx, req->pollent,
+ req->context->pollset_set);
+ grpc_exec_ctx_sched(exec_ctx, req->on_done, error, NULL);
grpc_http_parser_destroy(&req->parser);
if (req->addresses != NULL) {
grpc_resolved_addresses_destroy(req->addresses);
@@ -114,39 +117,49 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
grpc_iomgr_unregister_object(&req->iomgr_obj);
gpr_slice_buffer_destroy(&req->incoming);
gpr_slice_buffer_destroy(&req->outgoing);
+ GRPC_ERROR_UNREF(req->overall_error);
gpr_free(req);
}
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success);
+static void append_error(internal_request *req, grpc_error *error) {
+ if (req->overall_error == GRPC_ERROR_NONE) {
+ req->overall_error = GRPC_ERROR_CREATE("Failed HTTP/1 client request");
+ }
+ grpc_resolved_address *addr = &req->addresses->addrs[req->next_address - 1];
+ char *addr_text = grpc_sockaddr_to_uri((struct sockaddr *)addr->addr);
+ req->overall_error = grpc_error_add_child(
+ req->overall_error,
+ grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, addr_text));
+ gpr_free(addr_text);
+}
static void do_read(grpc_exec_ctx *exec_ctx, internal_request *req) {
grpc_endpoint_read(exec_ctx, req->ep, &req->incoming, &req->on_read);
}
-static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, bool success) {
+static void on_read(grpc_exec_ctx *exec_ctx, void *user_data,
+ grpc_error *error) {
internal_request *req = user_data;
size_t i;
for (i = 0; i < req->incoming.count; i++) {
if (GPR_SLICE_LENGTH(req->incoming.slices[i])) {
req->have_read_byte = 1;
- if (!grpc_http_parser_parse(&req->parser, req->incoming.slices[i])) {
- finish(exec_ctx, req, 0);
+ grpc_error *err =
+ grpc_http_parser_parse(&req->parser, req->incoming.slices[i]);
+ if (err != GRPC_ERROR_NONE) {
+ finish(exec_ctx, req, err);
return;
}
}
}
- if (success) {
+ if (error == GRPC_ERROR_NONE) {
do_read(exec_ctx, req);
} else if (!req->have_read_byte) {
- next_address(exec_ctx, req);
+ next_address(exec_ctx, req, GRPC_ERROR_REF(error));
} else {
- int parse_success = grpc_http_parser_eof(&req->parser);
- if (parse_success && (req->parser.type != GRPC_HTTP_RESPONSE)) {
- parse_success = 0;
- }
- finish(exec_ctx, req, parse_success);
+ finish(exec_ctx, req, grpc_http_parser_eof(&req->parser));
}
}
@@ -154,12 +167,12 @@ static void on_written(grpc_exec_ctx *exec_ctx, internal_request *req) {
do_read(exec_ctx, req);
}
-static void done_write(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void done_write(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
internal_request *req = arg;
- if (success) {
+ if (error == GRPC_ERROR_NONE) {
on_written(exec_ctx, req);
} else {
- next_address(exec_ctx, req);
+ next_address(exec_ctx, req, GRPC_ERROR_REF(error));
}
}
@@ -174,7 +187,8 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
internal_request *req = arg;
if (!ep) {
- next_address(exec_ctx, req);
+ next_address(exec_ctx, req,
+ GRPC_ERROR_CREATE("Unexplained handshake failure"));
return;
}
@@ -182,23 +196,30 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
start_write(exec_ctx, req);
}
-static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
+static void on_connected(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
internal_request *req = arg;
if (!req->ep) {
- next_address(exec_ctx, req);
+ next_address(exec_ctx, req, GRPC_ERROR_REF(error));
return;
}
req->handshaker->handshake(
exec_ctx, req, req->ep,
req->ssl_host_override ? req->ssl_host_override : req->host,
- on_handshake_done);
+ req->deadline, on_handshake_done);
}
-static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
+static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req,
+ grpc_error *error) {
grpc_resolved_address *addr;
+ if (error != GRPC_ERROR_NONE) {
+ append_error(req, error);
+ }
if (req->next_address == req->addresses->naddrs) {
- finish(exec_ctx, req, 0);
+ finish(exec_ctx, req,
+ GRPC_ERROR_CREATE_REFERENCING("Failed HTTP requests to all targets",
+ &req->overall_error, 1));
return;
}
addr = &req->addresses->addrs[req->next_address++];
@@ -208,34 +229,34 @@ static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
(struct sockaddr *)&addr->addr, addr->len, req->deadline);
}
-static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
- grpc_resolved_addresses *addresses) {
+static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
internal_request *req = arg;
- if (!addresses) {
- finish(exec_ctx, req, 0);
+ if (error != GRPC_ERROR_NONE) {
+ finish(exec_ctx, req, error);
return;
}
- req->addresses = addresses;
req->next_address = 0;
- next_address(exec_ctx, req);
+ next_address(exec_ctx, req, GRPC_ERROR_NONE);
}
-static void internal_request_begin(
- grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
- grpc_pollset *pollset, const grpc_httpcli_request *request,
- gpr_timespec deadline, grpc_httpcli_response_cb on_response,
- void *user_data, const char *name, gpr_slice request_text) {
+static void internal_request_begin(grpc_exec_ctx *exec_ctx,
+ grpc_httpcli_context *context,
+ grpc_polling_entity *pollent,
+ const grpc_httpcli_request *request,
+ gpr_timespec deadline, grpc_closure *on_done,
+ grpc_httpcli_response *response,
+ const char *name, gpr_slice request_text) {
internal_request *req = gpr_malloc(sizeof(internal_request));
memset(req, 0, sizeof(*req));
req->request_text = request_text;
- grpc_http_parser_init(&req->parser);
- req->on_response = on_response;
- req->user_data = user_data;
+ grpc_http_parser_init(&req->parser, GRPC_HTTP_RESPONSE, response);
+ req->on_done = on_done;
req->deadline = deadline;
req->handshaker =
request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
req->context = context;
- req->pollset = pollset;
+ req->pollent = pollent;
+ req->overall_error = GRPC_ERROR_NONE;
grpc_closure_init(&req->on_read, on_read, req);
grpc_closure_init(&req->done_write, done_write, req);
gpr_slice_buffer_init(&req->incoming);
@@ -244,45 +265,46 @@ static void internal_request_begin(
req->host = gpr_strdup(request->host);
req->ssl_host_override = gpr_strdup(request->ssl_host_override);
- grpc_pollset_set_add_pollset(exec_ctx, req->context->pollset_set,
- req->pollset);
+ GPR_ASSERT(pollent);
+ grpc_polling_entity_add_to_pollset_set(exec_ctx, req->pollent,
+ req->context->pollset_set);
grpc_resolve_address(exec_ctx, request->host, req->handshaker->default_port,
- on_resolved, req);
+ grpc_closure_create(on_resolved, req), &req->addresses);
}
void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
- grpc_pollset *pollset,
+ grpc_polling_entity *pollent,
const grpc_httpcli_request *request,
- gpr_timespec deadline,
- grpc_httpcli_response_cb on_response, void *user_data) {
+ gpr_timespec deadline, grpc_closure *on_done,
+ grpc_httpcli_response *response) {
char *name;
if (g_get_override &&
- g_get_override(exec_ctx, request, deadline, on_response, user_data)) {
+ g_get_override(exec_ctx, request, deadline, on_done, response)) {
return;
}
gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->http.path);
- internal_request_begin(exec_ctx, context, pollset, request, deadline,
- on_response, user_data, name,
+ internal_request_begin(exec_ctx, context, pollent, request, deadline, on_done,
+ response, name,
grpc_httpcli_format_get_request(request));
gpr_free(name);
}
void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
- grpc_pollset *pollset,
+ grpc_polling_entity *pollent,
const grpc_httpcli_request *request,
const char *body_bytes, size_t body_size,
- gpr_timespec deadline,
- grpc_httpcli_response_cb on_response, void *user_data) {
+ gpr_timespec deadline, grpc_closure *on_done,
+ grpc_httpcli_response *response) {
char *name;
if (g_post_override &&
g_post_override(exec_ctx, request, body_bytes, body_size, deadline,
- on_response, user_data)) {
+ on_done, response)) {
return;
}
gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->http.path);
internal_request_begin(
- exec_ctx, context, pollset, request, deadline, on_response, user_data,
- name, grpc_httpcli_format_post_request(request, body_bytes, body_size));
+ exec_ctx, context, pollent, request, deadline, on_done, response, name,
+ grpc_httpcli_format_post_request(request, body_bytes, body_size));
gpr_free(name);
}