Progress converting to new error system

pull/6897/head
Craig Tiller 9 years ago
parent f51457b34d
commit 5b15afd75c
  1. 9
      src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c
  2. 63
      src/core/lib/http/httpcli.c
  3. 19
      src/core/lib/http/httpcli.h
  4. 230
      src/core/lib/http/parser.c
  5. 17
      src/core/lib/http/parser.h
  6. 14
      src/core/lib/iomgr/resolve_address.h
  7. 84
      src/core/lib/iomgr/resolve_address_posix.c
  8. 3
      src/core/lib/iomgr/unix_sockets_posix.h

@ -176,6 +176,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
grpc_security_status status = GRPC_SECURITY_ERROR;
grpc_server_security_connector *sc = NULL;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_error *err = GRPC_ERROR_NONE;
GRPC_API_TRACE(
"grpc_server_add_secure_http2_port("
@ -214,11 +215,12 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
gpr_mu_init(&state->mu);
gpr_ref_init(&state->refcount, 1);
grpc_error **errs = gpr_malloc(sizeof(*errs) * resolved->naddrs);
for (i = 0; i < resolved->naddrs; i++) {
port_temp = grpc_tcp_server_add_port(
errs[i] = grpc_tcp_server_add_port(
tcp, (struct sockaddr *)&resolved->addrs[i].addr,
resolved->addrs[i].len);
if (port_temp > 0) {
resolved->addrs[i].len, &port_temp);
if (errs[i] != GRPC_ERROR_NONE) {
if (port_num == -1) {
port_num = port_temp;
} else {
@ -247,6 +249,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
/* Error path: cleanup and return */
error:
GPR_ASSERT(err != GRPC_ERROR_NONE);
if (resolved) {
grpc_resolved_addresses_destroy(resolved);
}

@ -59,8 +59,7 @@ 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_iomgr_object iomgr_obj;
@ -96,11 +95,10 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
int success) {
grpc_error *error) {
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_exec_ctx_push(exec_ctx, req->on_done, error, NULL);
grpc_http_parser_destroy(&req->parser);
if (req->addresses != NULL) {
grpc_resolved_addresses_destroy(req->addresses);
@ -141,11 +139,11 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *user_data,
} else if (!req->have_read_byte) {
next_address(exec_ctx, req);
} else {
int parse_success = grpc_http_parser_eof(&req->parser);
if (parse_success && (req->parser.type != GRPC_HTTP_RESPONSE)) {
parse_success = 0;
grpc_error *err = grpc_http_parser_eof(&req->parser);
if (err == GRPC_ERROR_NONE && (req->parser.type != GRPC_HTTP_RESPONSE)) {
err = GRPC_ERROR_CREATE("Expected http response, got http request");
}
finish(exec_ctx, req, parse_success);
finish(exec_ctx, req, err);
}
}
@ -208,29 +206,28 @@ 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);
}
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_pollset *pollset,
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;
@ -247,22 +244,22 @@ static void internal_request_begin(
grpc_pollset_set_add_pollset(exec_ctx, req->context->pollset_set,
req->pollset);
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,
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, pollset, request, deadline, on_done,
response, name,
grpc_httpcli_format_get_request(request));
gpr_free(name);
}
@ -271,18 +268,18 @@ void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_pollset *pollset,
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, pollset, request, deadline, on_done, response, name,
grpc_httpcli_format_post_request(request, body_bytes, body_size));
gpr_free(name);
}

@ -81,11 +81,6 @@ typedef struct grpc_httpcli_request {
/* Expose the parser response type as a httpcli response too */
typedef struct grpc_http_response grpc_httpcli_response;
/* Callback for grpc_httpcli_get and grpc_httpcli_post. */
typedef void (*grpc_httpcli_response_cb)(grpc_exec_ctx *exec_ctx,
void *user_data,
const grpc_http_response *response);
void grpc_httpcli_context_init(grpc_httpcli_context *context);
void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
@ -102,8 +97,8 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
void grpc_httpcli_get(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);
gpr_timespec deadline, grpc_closure *on_complete,
grpc_httpcli_response *response);
/* Asynchronously perform a HTTP POST.
'context' specifies the http context under which to do the post
@ -124,19 +119,19 @@ void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_pollset *pollset,
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_complete,
grpc_httpcli_response *response);
/* override functions return 1 if they handled the request, 0 otherwise */
typedef int (*grpc_httpcli_get_override)(grpc_exec_ctx *exec_ctx,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data);
grpc_closure *on_complete,
grpc_httpcli_response *response);
typedef int (*grpc_httpcli_post_override)(
grpc_exec_ctx *exec_ctx, 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);
grpc_closure *on_complete, grpc_httpcli_response *response);
void grpc_httpcli_set_override(grpc_httpcli_get_override get,
grpc_httpcli_post_override post);

@ -48,37 +48,38 @@ static char *buf2str(void *buffer, size_t length) {
return out;
}
static int handle_response_line(grpc_http_parser *parser) {
static grpc_error *handle_response_line(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
if (cur == end || *cur++ != 'H') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'P') goto error;
if (cur == end || *cur++ != '/') goto error;
if (cur == end || *cur++ != '1') goto error;
if (cur == end || *cur++ != '.') goto error;
if (cur == end || *cur < '0' || *cur++ > '1') goto error;
if (cur == end || *cur++ != ' ') goto error;
if (cur == end || *cur < '1' || *cur++ > '9') goto error;
if (cur == end || *cur < '0' || *cur++ > '9') goto error;
if (cur == end || *cur < '0' || *cur++ > '9') goto error;
parser->http.response.status =
if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
if (cur == end || *cur++ != '1') return GRPC_ERROR_CREATE("Expected '1'");
if (cur == end || *cur++ != '.') return GRPC_ERROR_CREATE("Expected '.'");
if (cur == end || *cur < '0' || *cur++ > '1') {
return GRPC_ERROR_CREATE("Expected HTTP/1.0 or HTTP/1.1");
}
if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
if (cur == end || *cur < '1' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
if (cur == end || *cur < '0' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
if (cur == end || *cur < '0' || *cur++ > '9')
return GRPC_ERROR_CREATE("Expected status code");
parser->http.response->status =
(cur[-3] - '0') * 100 + (cur[-2] - '0') * 10 + (cur[-1] - '0');
if (cur == end || *cur++ != ' ') goto error;
if (cur == end || *cur++ != ' ') return GRPC_ERROR_CREATE("Expected ' '");
/* we don't really care about the status code message */
return 1;
error:
if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing response line");
return 0;
return GRPC_ERROR_NONE;
}
static int handle_request_line(grpc_http_parser *parser) {
static grpc_error *handle_request_line(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
@ -87,83 +88,81 @@ static int handle_request_line(grpc_http_parser *parser) {
while (cur != end && *cur++ != ' ')
;
if (cur == end) goto error;
parser->http.request.method = buf2str(beg, (size_t)(cur - beg - 1));
if (cur == end) return GRPC_ERROR_CREATE("No method on HTTP request line");
parser->http.request->method = buf2str(beg, (size_t)(cur - beg - 1));
beg = cur;
while (cur != end && *cur++ != ' ')
;
if (cur == end) goto error;
parser->http.request.path = buf2str(beg, (size_t)(cur - beg - 1));
if (cur == end || *cur++ != 'H') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'T') goto error;
if (cur == end || *cur++ != 'P') goto error;
if (cur == end || *cur++ != '/') goto error;
if (cur == end) return GRPC_ERROR_CREATE("No path on HTTP request line");
parser->http.request->path = buf2str(beg, (size_t)(cur - beg - 1));
if (cur == end || *cur++ != 'H') return GRPC_ERROR_CREATE("Expected 'H'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'T') return GRPC_ERROR_CREATE("Expected 'T'");
if (cur == end || *cur++ != 'P') return GRPC_ERROR_CREATE("Expected 'P'");
if (cur == end || *cur++ != '/') return GRPC_ERROR_CREATE("Expected '/'");
vers_major = (uint8_t)(*cur++ - '1' + 1);
++cur;
if (cur == end) goto error;
if (cur == end)
return GRPC_ERROR_CREATE("End of line in HTTP version string");
vers_minor = (uint8_t)(*cur++ - '1' + 1);
if (vers_major == 1) {
if (vers_minor == 0) {
parser->http.request.version = GRPC_HTTP_HTTP10;
parser->http.request->version = GRPC_HTTP_HTTP10;
} else if (vers_minor == 1) {
parser->http.request.version = GRPC_HTTP_HTTP11;
parser->http.request->version = GRPC_HTTP_HTTP11;
} else {
goto error;
return GRPC_ERROR_CREATE(
"Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
} else if (vers_major == 2) {
if (vers_minor == 0) {
parser->http.request.version = GRPC_HTTP_HTTP20;
parser->http.request->version = GRPC_HTTP_HTTP20;
} else {
goto error;
return GRPC_ERROR_CREATE(
"Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
} else {
goto error;
return GRPC_ERROR_CREATE("Expected one of HTTP/1.0, HTTP/1.1, or HTTP/2.0");
}
return 1;
error:
if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing request line");
return 0;
return GRPC_ERROR_NONE;
}
static int handle_first_line(grpc_http_parser *parser) {
if (parser->cur_line[0] == 'H') {
parser->type = GRPC_HTTP_RESPONSE;
return handle_response_line(parser);
} else {
parser->type = GRPC_HTTP_REQUEST;
return handle_request_line(parser);
static grpc_error *handle_first_line(grpc_http_parser *parser) {
switch (parser->type) {
case GRPC_HTTP_REQUEST:
return handle_request_line(parser);
case GRPC_HTTP_RESPONSE:
return handle_response_line(parser);
}
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
static int add_header(grpc_http_parser *parser) {
static grpc_error *add_header(grpc_http_parser *parser) {
uint8_t *beg = parser->cur_line;
uint8_t *cur = beg;
uint8_t *end = beg + parser->cur_line_length;
size_t *hdr_count = NULL;
grpc_http_header **hdrs = NULL;
grpc_http_header hdr = {NULL, NULL};
grpc_error *error = GRPC_ERROR_NONE;
GPR_ASSERT(cur != end);
if (*cur == ' ' || *cur == '\t') {
if (grpc_http1_trace)
gpr_log(GPR_ERROR, "Continued header lines not supported yet");
goto error;
error = GRPC_ERROR_CREATE("Continued header lines not supported yet");
goto done;
}
while (cur != end && *cur != ':') {
cur++;
}
if (cur == end) {
if (grpc_http1_trace)
gpr_log(GPR_ERROR, "Didn't find ':' in header string");
goto error;
error = GRPC_ERROR_CREATE("Didn't find ':' in header string");
goto done;
}
GPR_ASSERT(cur >= beg);
hdr.key = buf2str(beg, (size_t)(cur - beg));
@ -176,11 +175,11 @@ static int add_header(grpc_http_parser *parser) {
hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length);
if (parser->type == GRPC_HTTP_RESPONSE) {
hdr_count = &parser->http.response.hdr_count;
hdrs = &parser->http.response.hdrs;
hdr_count = &parser->http.response->hdr_count;
hdrs = &parser->http.response->hdrs;
} else if (parser->type == GRPC_HTTP_REQUEST) {
hdr_count = &parser->http.request.hdr_count;
hdrs = &parser->http.request.hdrs;
hdr_count = &parser->http.request->hdr_count;
hdrs = &parser->http.request->hdrs;
} else {
return 0;
}
@ -191,20 +190,21 @@ static int add_header(grpc_http_parser *parser) {
*hdrs = gpr_realloc(*hdrs, parser->hdr_capacity * sizeof(**hdrs));
}
(*hdrs)[(*hdr_count)++] = hdr;
return 1;
error:
gpr_free(hdr.key);
gpr_free(hdr.value);
return 0;
done:
if (error != GRPC_ERROR_NONE) {
gpr_free(hdr.key);
gpr_free(hdr.value);
}
return error;
}
static int finish_line(grpc_http_parser *parser) {
static grpc_error *finish_line(grpc_http_parser *parser) {
grpc_error *err;
switch (parser->state) {
case GRPC_HTTP_FIRST_LINE:
if (!handle_first_line(parser)) {
return 0;
}
err = handle_first_line(parser);
if (err != GRPC_ERROR_NONE) return err;
parser->state = GRPC_HTTP_HEADERS;
break;
case GRPC_HTTP_HEADERS:
@ -221,21 +221,21 @@ static int finish_line(grpc_http_parser *parser) {
}
parser->cur_line_length = 0;
return 1;
return GRPC_ERROR_NONE;
}
static int addbyte_body(grpc_http_parser *parser, uint8_t byte) {
static grpc_error *addbyte_body(grpc_http_parser *parser, uint8_t byte) {
size_t *body_length = NULL;
char **body = NULL;
if (parser->type == GRPC_HTTP_RESPONSE) {
body_length = &parser->http.response.body_length;
body = &parser->http.response.body;
body_length = &parser->http.response->body_length;
body = &parser->http.response->body;
} else if (parser->type == GRPC_HTTP_REQUEST) {
body_length = &parser->http.request.body_length;
body = &parser->http.request.body;
body_length = &parser->http.request->body_length;
body = &parser->http.request->body;
} else {
return 0;
GPR_UNREACHABLE_CODE(return GRPC_ERROR_CREATE("Should never reach here"));
}
if (*body_length == parser->body_capacity) {
@ -245,34 +245,35 @@ static int addbyte_body(grpc_http_parser *parser, uint8_t byte) {
(*body)[*body_length] = (char)byte;
(*body_length)++;
return 1;
return GRPC_ERROR_NONE;
}
static int check_line(grpc_http_parser *parser) {
static grpc_error *check_line(grpc_http_parser *parser) {
if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\r' &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
return 1;
return GRPC_ERROR_NONE;
}
// HTTP request with \n\r line termiantors.
else if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\n' &&
parser->cur_line[parser->cur_line_length - 1] == '\r') {
return 1;
return GRPC_ERROR_NONE;
}
// HTTP request with only \n line terminators.
else if (parser->cur_line_length >= 1 &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
parser->cur_line_end_length = 1;
return 1;
return GRPC_ERROR_NONE;
}
return 0;
return GRPC_ERROR_CREATE(
"Expected line ending (one of \\r\\n, \\n\\r, or \\n)");
}
static int addbyte(grpc_http_parser *parser, uint8_t byte) {
static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte) {
switch (parser->state) {
case GRPC_HTTP_FIRST_LINE:
case GRPC_HTTP_HEADERS:
@ -287,7 +288,7 @@ static int addbyte(grpc_http_parser *parser, uint8_t byte) {
if (check_line(parser)) {
return finish_line(parser);
} else {
return 1;
return GRPC_ERROR_NONE;
}
GPR_UNREACHABLE_CODE(return 0);
case GRPC_HTTP_BODY:
@ -296,46 +297,53 @@ static int addbyte(grpc_http_parser *parser, uint8_t byte) {
GPR_UNREACHABLE_CODE(return 0);
}
void grpc_http_parser_init(grpc_http_parser *parser) {
void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
void *request_or_response) {
memset(parser, 0, sizeof(*parser));
parser->state = GRPC_HTTP_FIRST_LINE;
parser->type = GRPC_HTTP_UNKNOWN;
parser->type = type;
parser->http.request_or_response = request_or_response;
parser->cur_line_end_length = 2;
}
void grpc_http_parser_destroy(grpc_http_parser *parser) {
void grpc_http_parser_destroy(grpc_http_parser *parser) {}
void grpc_http_request_destroy(grpc_http_request *request) {
size_t i;
if (parser->type == GRPC_HTTP_RESPONSE) {
gpr_free(parser->http.response.body);
for (i = 0; i < parser->http.response.hdr_count; i++) {
gpr_free(parser->http.response.hdrs[i].key);
gpr_free(parser->http.response.hdrs[i].value);
}
gpr_free(parser->http.response.hdrs);
} else if (parser->type == GRPC_HTTP_REQUEST) {
gpr_free(parser->http.request.body);
for (i = 0; i < parser->http.request.hdr_count; i++) {
gpr_free(parser->http.request.hdrs[i].key);
gpr_free(parser->http.request.hdrs[i].value);
}
gpr_free(parser->http.request.hdrs);
gpr_free(parser->http.request.method);
gpr_free(parser->http.request.path);
gpr_free(request->body);
for (i = 0; i < request->hdr_count; i++) {
gpr_free(request->hdrs[i].key);
gpr_free(request->hdrs[i].value);
}
gpr_free(request->hdrs);
gpr_free(request->method);
gpr_free(request->path);
}
int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
void grpc_http_response_destroy(grpc_http_response *response) {
size_t i;
gpr_free(response->body);
for (i = 0; i < response->hdr_count; i++) {
gpr_free(response->hdrs[i].key);
gpr_free(response->hdrs[i].value);
}
gpr_free(response->hdrs);
}
grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice) {
size_t i;
for (i = 0; i < GPR_SLICE_LENGTH(slice); i++) {
if (!addbyte(parser, GPR_SLICE_START_PTR(slice)[i])) {
return 0;
}
grpc_error *err = addbyte(parser, GPR_SLICE_START_PTR(slice)[i]);
if (err != GRPC_ERROR_NONE) return err;
}
return 1;
return GRPC_ERROR_NONE;
}
int grpc_http_parser_eof(grpc_http_parser *parser) {
return parser->state == GRPC_HTTP_BODY;
grpc_error *grpc_http_parser_eof(grpc_http_parser *parser) {
if (parser->state != GRPC_HTTP_BODY) {
return GRPC_ERROR_CREATE("Did not finish headers");
}
return GRPC_ERROR_NONE;
}

@ -36,6 +36,7 @@
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include "src/core/lib/iomgr/error.h"
/* Maximum length of a header string of the form 'Key: Value\r\n' */
#define GRPC_HTTP_PARSER_MAX_HEADER_LENGTH 4096
@ -61,7 +62,6 @@ typedef enum {
typedef enum {
GRPC_HTTP_RESPONSE,
GRPC_HTTP_REQUEST,
GRPC_HTTP_UNKNOWN
} grpc_http_type;
/* A request */
@ -97,8 +97,9 @@ typedef struct {
grpc_http_type type;
union {
grpc_http_response response;
grpc_http_request request;
grpc_http_response *response;
grpc_http_request *request;
void *request_or_response;
} http;
size_t body_capacity;
size_t hdr_capacity;
@ -108,11 +109,15 @@ typedef struct {
size_t cur_line_end_length;
} grpc_http_parser;
void grpc_http_parser_init(grpc_http_parser *parser);
void grpc_http_parser_init(grpc_http_parser *parser, grpc_http_type type,
void *request_or_response);
void grpc_http_parser_destroy(grpc_http_parser *parser);
int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
int grpc_http_parser_eof(grpc_http_parser *parser);
grpc_error *grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
grpc_error *grpc_http_parser_eof(grpc_http_parser *parser);
void grpc_http_request_destroy(grpc_http_request *request);
void grpc_http_response_destroy(grpc_http_response *response);
extern int grpc_http1_trace;

@ -50,24 +50,20 @@ typedef struct {
grpc_resolved_address *addrs;
} grpc_resolved_addresses;
/* Async result callback:
On success: addresses is the result, and the callee must call
grpc_resolved_addresses_destroy when it's done with them
On failure: addresses is NULL */
typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses);
/* Asynchronously resolve addr. Use default_port if a port isn't designated
in addr, otherwise use the port in addr. */
/* TODO(ctiller): add a timeout here */
extern void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr,
const char *default_port,
grpc_resolve_cb cb, void *arg);
grpc_closure *on_done,
grpc_resolved_addresses **addresses);
/* Destroy resolved addresses */
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
/* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
result must be freed with grpc_resolved_addresses_destroy. */
extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port);
extern grpc_error *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses);
#endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */

@ -54,38 +54,33 @@
#include "src/core/lib/support/block_annotate.h"
#include "src/core/lib/support/string.h"
typedef struct {
char *name;
char *default_port;
grpc_resolve_cb cb;
grpc_closure request_closure;
void *arg;
} request;
static grpc_resolved_addresses *blocking_resolve_address_impl(
const char *name, const char *default_port) {
static grpc_error *blocking_resolve_address_impl(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses) {
struct addrinfo hints;
struct addrinfo *result = NULL, *resp;
char *host;
char *port;
int s;
size_t i;
grpc_resolved_addresses *addrs = NULL;
grpc_error *err;
if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
name[4] == ':' && name[5] != 0) {
return grpc_resolve_unix_domain_address(name + 5);
return grpc_resolve_unix_domain_address(name + 5, addresses);
}
/* parse name, splitting it into host and port parts */
gpr_split_host_port(name, &host, &port);
if (host == NULL) {
gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
err = grpc_error_set_str(GRPC_ERROR_CREATE("unparseable host:port"),
GRPC_ERROR_STR_TARGET_ADDRESS, name);
goto done;
}
if (port == NULL) {
if (default_port == NULL) {
gpr_log(GPR_ERROR, "no port in name '%s'", name);
err = grpc_error_set_str(GRPC_ERROR_CREATE("no port in name"),
GRPC_ERROR_STR_TARGET_ADDRESS, name);
goto done;
}
port = gpr_strdup(default_port);
@ -115,23 +110,31 @@ static grpc_resolved_addresses *blocking_resolve_address_impl(
}
if (s != 0) {
gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
err = grpc_error_set_str(
grpc_error_set_str(
grpc_error_set_str(grpc_error_set_int(GRPC_ERROR_CREATE("OS Error"),
GRPC_ERROR_INT_ERRNO, s),
GRPC_ERROR_STR_OS_ERROR, gai_strerror(s)),
GRPC_ERROR_STR_SYSCALL, "getaddrinfo"),
GRPC_ERROR_STR_TARGET_ADDRESS, name);
goto done;
}
/* Success path: set addrs non-NULL, fill it in */
addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
addrs->naddrs = 0;
*addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
(*addresses)->naddrs = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
addrs->naddrs++;
(*addresses)->naddrs++;
}
addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
(*addresses)->addrs =
gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
i = 0;
for (resp = result; resp != NULL; resp = resp->ai_next) {
memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
addrs->addrs[i].len = resp->ai_addrlen;
memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
(*addresses)->addrs[i].len = resp->ai_addrlen;
i++;
}
err = GRPC_ERROR_NONE;
done:
gpr_free(host);
@ -139,24 +142,33 @@ done:
if (result) {
freeaddrinfo(result);
}
return addrs;
return err;
}
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port) = blocking_resolve_address_impl;
grpc_error *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port,
grpc_resolved_addresses **addresses) = blocking_resolve_address_impl;
typedef struct {
char *name;
char *default_port;
grpc_closure *on_done;
grpc_resolved_addresses **addrs_out;
grpc_closure request_closure;
void *arg;
} request;
/* Callback to be passed to grpc_executor to asynch-ify
* grpc_blocking_resolve_address */
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp,
grpc_error *error) {
request *r = rp;
grpc_resolved_addresses *resolved =
grpc_blocking_resolve_address(r->name, r->default_port);
void *arg = r->arg;
grpc_resolve_cb cb = r->cb;
grpc_exec_ctx_push(
exec_ctx, r->on_done,
grpc_blocking_resolve_address(r->name, r->default_port, r->addrs_out),
NULL);
gpr_free(r->name);
gpr_free(r->default_port);
cb(exec_ctx, arg, resolved);
gpr_free(r);
}
@ -166,19 +178,21 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
}
static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) {
const char *default_port,
grpc_closure *on_done,
grpc_resolved_addresses **addrs) {
request *r = gpr_malloc(sizeof(request));
grpc_closure_init(&r->request_closure, do_request_thread, r);
r->name = gpr_strdup(name);
r->default_port = gpr_strdup(default_port);
r->cb = cb;
r->arg = arg;
r->on_done = on_done;
r->addrs_out = addrs;
grpc_executor_push(&r->request_closure, GRPC_ERROR_NONE);
}
void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) = resolve_address_impl;
const char *default_port, grpc_closure *on_done,
grpc_resolved_addresses **addrs) =
resolve_address_impl;
#endif

@ -43,7 +43,8 @@
void grpc_create_socketpair_if_unix(int sv[2]);
grpc_resolved_addresses *grpc_resolve_unix_domain_address(const char *name);
grpc_error *grpc_resolve_unix_domain_address(
const char *name, grpc_resolved_addresses **addresses);
int grpc_is_unix_socket(const struct sockaddr *addr);

Loading…
Cancel
Save