Commit e9cef7c4 by Edward Thomson

http: introduce GIT_ERROR_HTTP

Disambiguate between general network problems and HTTP problems in error
codes.
parent 7fd9b3f5
......@@ -106,7 +106,8 @@ typedef enum {
GIT_ERROR_FILESYSTEM,
GIT_ERROR_PATCH,
GIT_ERROR_WORKTREE,
GIT_ERROR_SHA1
GIT_ERROR_SHA1,
GIT_ERROR_HTTP
} git_error_t;
/**
......
......@@ -158,7 +158,7 @@ static int handle_auth(
}
if (error > 0) {
git_error_set(GIT_ERROR_NET, "%s authentication required but no callback set", server_type);
git_error_set(GIT_ERROR_HTTP, "%s authentication required but no callback set", server_type);
error = -1;
}
......@@ -175,7 +175,7 @@ GIT_INLINE(int) handle_remote_auth(
http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
if (response->server_auth_credtypes == 0) {
git_error_set(GIT_ERROR_NET, "server requires authentication that we do not support");
git_error_set(GIT_ERROR_HTTP, "server requires authentication that we do not support");
return -1;
}
......@@ -197,7 +197,7 @@ GIT_INLINE(int) handle_proxy_auth(
http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
if (response->proxy_auth_credtypes == 0) {
git_error_set(GIT_ERROR_NET, "proxy requires authentication that we do not support");
git_error_set(GIT_ERROR_HTTP, "proxy requires authentication that we do not support");
return -1;
}
......@@ -226,7 +226,7 @@ static int handle_response(
if (allow_replay && git_http_response_is_redirect(response)) {
if (!response->location) {
git_error_set(GIT_ERROR_NET, "redirect without location");
git_error_set(GIT_ERROR_HTTP, "redirect without location");
return -1;
}
......@@ -236,7 +236,7 @@ static int handle_response(
return 0;
} else if (git_http_response_is_redirect(response)) {
git_error_set(GIT_ERROR_NET, "unexpected redirect");
git_error_set(GIT_ERROR_HTTP, "unexpected redirect");
return -1;
}
......@@ -255,24 +255,24 @@ static int handle_response(
return git_http_client_skip_body(transport->http_client);
} else if (response->status == GIT_HTTP_STATUS_UNAUTHORIZED ||
response->status == GIT_HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
git_error_set(GIT_ERROR_NET, "unexpected authentication failure");
git_error_set(GIT_ERROR_HTTP, "unexpected authentication failure");
return -1;
}
if (response->status != GIT_HTTP_STATUS_OK) {
git_error_set(GIT_ERROR_NET, "unexpected http status code: %d", response->status);
git_error_set(GIT_ERROR_HTTP, "unexpected http status code: %d", response->status);
return -1;
}
/* The response must contain a Content-Type header. */
if (!response->content_type) {
git_error_set(GIT_ERROR_NET, "no content-type header in response");
git_error_set(GIT_ERROR_HTTP, "no content-type header in response");
return -1;
}
/* The Content-Type header must match our expectation. */
if (strcmp(response->content_type, stream->service->response_type) != 0) {
git_error_set(GIT_ERROR_NET, "invalid content-type: '%s'", response->content_type);
git_error_set(GIT_ERROR_HTTP, "invalid content-type: '%s'", response->content_type);
return -1;
}
......@@ -411,7 +411,7 @@ static int http_stream_read(
}
if (stream->state == HTTP_STATE_SENDING_REQUEST) {
git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays");
git_error_set(GIT_ERROR_HTTP, "too many redirects or authentication replays");
error = -1;
goto done;
}
......@@ -548,7 +548,7 @@ static int http_stream_write(
}
if (stream->state == HTTP_STATE_NONE) {
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"too many redirects or authentication replays");
error = -1;
goto done;
......@@ -653,7 +653,7 @@ static int http_action(
return error;
if ((service = select_service(action)) == NULL) {
git_error_set(GIT_ERROR_NET, "invalid action");
git_error_set(GIT_ERROR_HTTP, "invalid action");
return -1;
}
......
......@@ -154,7 +154,7 @@ static int on_header_complete(http_parser *parser)
if (!strcasecmp("Content-Type", name->ptr)) {
if (response->content_type) {
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"multiple content-type headers");
return -1;
}
......@@ -166,14 +166,14 @@ static int on_header_complete(http_parser *parser)
int64_t len;
if (response->content_length) {
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"multiple content-length headers");
return -1;
}
if (git__strntol64(&len, value->ptr, value->size,
NULL, 10) < 0 || len < 0) {
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"invalid content-length");
return -1;
}
......@@ -196,7 +196,7 @@ static int on_header_complete(http_parser *parser)
return -1;
} else if (!strcasecmp("Location", name->ptr)) {
if (response->location) {
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"multiple location headers");
return -1;
}
......@@ -235,7 +235,7 @@ static int on_header_field(http_parser *parser, const char *str, size_t len)
break;
default:
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"header name seen at unexpected time");
return ctx->parse_status = PARSE_STATUS_ERROR;
}
......@@ -258,7 +258,7 @@ static int on_header_value(http_parser *parser, const char *str, size_t len)
break;
default:
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"header value seen at unexpected time");
return ctx->parse_status = PARSE_STATUS_ERROR;
}
......@@ -348,7 +348,7 @@ static int on_headers_complete(http_parser *parser)
break;
default:
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"header completion at unexpected time");
return ctx->parse_status = PARSE_STATUS_ERROR;
}
......@@ -511,14 +511,14 @@ static const char *init_auth_context(
int error;
if (!best_scheme_and_challenge(&scheme, &challenge, challenges, credentials)) {
git_error_set(GIT_ERROR_NET, "could not find appropriate mechanism for credentials");
git_error_set(GIT_ERROR_HTTP, "could not find appropriate mechanism for credentials");
return NULL;
}
error = scheme->init_context(&server->auth_context, &server->url);
if (error == GIT_PASSTHROUGH) {
git_error_set(GIT_ERROR_NET, "'%s' authentication is not supported", scheme->name);
git_error_set(GIT_ERROR_HTTP, "'%s' authentication is not supported", scheme->name);
return NULL;
}
......@@ -585,7 +585,7 @@ static int apply_credentials(
if (auth->connection_affinity)
free_auth_context(server);
} else if (!token.size) {
git_error_set(GIT_ERROR_NET, "failed to respond to authentication challange");
git_error_set(GIT_ERROR_HTTP, "failed to respond to authentication challange");
error = -1;
goto done;
}
......@@ -745,7 +745,7 @@ static int check_certificate(
else if (error == GIT_PASSTHROUGH)
error = 0;
else if (error && !git_error_last())
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"user rejected certificate for %s", url->host);
git_error_state_free(&last_error);
......@@ -864,7 +864,7 @@ GIT_INLINE(int) server_create_stream(git_http_server *server)
else if (strcasecmp(url->scheme, "http") == 0)
return git_socket_stream_new(&server->stream, url->host, url->port);
git_error_set(GIT_ERROR_NET, "unknown http scheme '%s'", url->scheme);
git_error_set(GIT_ERROR_HTTP, "unknown http scheme '%s'", url->scheme);
return -1;
}
......@@ -920,7 +920,7 @@ static int proxy_connect(
error = GIT_RETRY;
goto done;
} else if (response.status != GIT_HTTP_STATUS_OK) {
git_error_set(GIT_ERROR_NET, "proxy returned unexpected status: %d", response.status);
git_error_set(GIT_ERROR_HTTP, "proxy returned unexpected status: %d", response.status);
error = -1;
goto done;
}
......@@ -1044,7 +1044,7 @@ GIT_INLINE(int) client_read(git_http_client *client)
max_len = min(max_len, INT_MAX);
if (max_len == 0) {
git_error_set(GIT_ERROR_NET, "no room in output buffer");
git_error_set(GIT_ERROR_HTTP, "no room in output buffer");
return -1;
}
......@@ -1101,12 +1101,12 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
http_errno = client->parser.http_errno;
if (parsed_len > INT_MAX) {
git_error_set(GIT_ERROR_NET, "unexpectedly large parse");
git_error_set(GIT_ERROR_HTTP, "unexpectedly large parse");
return -1;
}
if (parser->upgrade) {
git_error_set(GIT_ERROR_NET, "server requested upgrade");
git_error_set(GIT_ERROR_HTTP, "server requested upgrade");
return -1;
}
......@@ -1140,14 +1140,14 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
/* Most failures will be reported in http_errno */
else if (parser->http_errno != HPE_OK) {
git_error_set(GIT_ERROR_NET, "http parser error: %s",
git_error_set(GIT_ERROR_HTTP, "http parser error: %s",
http_errno_description(http_errno));
return -1;
}
/* Otherwise we should have consumed the entire buffer. */
else if (parsed_len != client->read_buf.size) {
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"http parser did not consume entire buffer: %s",
http_errno_description(http_errno));
return -1;
......@@ -1155,7 +1155,7 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client)
/* recv returned 0, the server hung up on us */
else if (!parsed_len) {
git_error_set(GIT_ERROR_NET, "unexpected EOF");
git_error_set(GIT_ERROR_HTTP, "unexpected EOF");
return -1;
}
......@@ -1281,7 +1281,7 @@ int git_http_client_send_body(
return 0;
if (client->state != SENDING_BODY) {
git_error_set(GIT_ERROR_NET, "client is in invalid state");
git_error_set(GIT_ERROR_HTTP, "client is in invalid state");
return -1;
}
......@@ -1317,7 +1317,7 @@ static int complete_request(git_http_client *client)
assert(client && client->state == SENDING_BODY);
if (client->request_body_len && client->request_body_remain) {
git_error_set(GIT_ERROR_NET, "truncated write");
git_error_set(GIT_ERROR_HTTP, "truncated write");
error = -1;
} else if (client->request_chunked) {
error = stream_write(&client->server, "0\r\n\r\n", 5);
......@@ -1349,7 +1349,7 @@ int git_http_client_read_response(
}
if (client->state != SENT_REQUEST) {
git_error_set(GIT_ERROR_NET, "client is in invalid state");
git_error_set(GIT_ERROR_HTTP, "client is in invalid state");
error = -1;
goto done;
}
......@@ -1392,7 +1392,7 @@ int git_http_client_read_body(
return 0;
if (client->state != READING_BODY) {
git_error_set(GIT_ERROR_NET, "client is in invalid state");
git_error_set(GIT_ERROR_HTTP, "client is in invalid state");
return -1;
}
......@@ -1438,7 +1438,7 @@ int git_http_client_skip_body(git_http_client *client)
return 0;
if (client->state != READING_BODY) {
git_error_set(GIT_ERROR_NET, "client is in invalid state");
git_error_set(GIT_ERROR_HTTP, "client is in invalid state");
return -1;
}
......@@ -1451,7 +1451,7 @@ int git_http_client_skip_body(git_http_client *client)
if (parser_context.error != HPE_OK ||
(parser_context.parse_status != PARSE_STATUS_OK &&
parser_context.parse_status != PARSE_STATUS_NO_OUTPUT)) {
git_error_set(GIT_ERROR_NET,
git_error_set(GIT_ERROR_HTTP,
"unexpected data handled in callback");
error = -1;
}
......
......@@ -145,7 +145,7 @@ static int apply_userpass_credentials(HINTERNET request, DWORD target, int mecha
} else if (mechanisms & GIT_WINHTTP_AUTH_BASIC) {
native_scheme = WINHTTP_AUTH_SCHEME_BASIC;
} else {
git_error_set(GIT_ERROR_NET, "invalid authentication scheme");
git_error_set(GIT_ERROR_HTTP, "invalid authentication scheme");
error = -1;
goto done;
}
......@@ -184,7 +184,7 @@ static int apply_default_credentials(HINTERNET request, DWORD target, int mechan
} else if ((mechanisms & GIT_WINHTTP_AUTH_NTLM) != 0) {
native_scheme = WINHTTP_AUTH_SCHEME_NTLM;
} else {
git_error_set(GIT_ERROR_NET, "invalid authentication scheme");
git_error_set(GIT_ERROR_HTTP, "invalid authentication scheme");
return -1;
}
......@@ -287,7 +287,7 @@ static int certificate_check(winhttp_stream *s, int valid)
/* If there is no override, we should fail if WinHTTP doesn't think it's fine */
if (t->owner->certificate_check_cb == NULL && !valid) {
if (!git_error_last())
git_error_set(GIT_ERROR_NET, "unknown certificate check failure");
git_error_set(GIT_ERROR_HTTP, "unknown certificate check failure");
return GIT_ECERTIFICATE;
}
......@@ -311,7 +311,7 @@ static int certificate_check(winhttp_stream *s, int valid)
error = valid ? 0 : GIT_ECERTIFICATE;
if (error < 0 && !git_error_last())
git_error_set(GIT_ERROR_NET, "user cancelled certificate check");
git_error_set(GIT_ERROR_HTTP, "user cancelled certificate check");
return error;
}
......@@ -440,7 +440,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
goto on_error;
if (strcmp(t->proxy.url.scheme, "http") != 0 && strcmp(t->proxy.url.scheme, "https") != 0) {
git_error_set(GIT_ERROR_NET, "invalid URL: '%s'", proxy_url);
git_error_set(GIT_ERROR_HTTP, "invalid URL: '%s'", proxy_url);
error = -1;
goto on_error;
}
......@@ -713,21 +713,21 @@ static void CALLBACK winhttp_status(
status = *((DWORD *)info);
if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID))
git_error_set(GIT_ERROR_NET, "SSL certificate issued for different common name");
git_error_set(GIT_ERROR_HTTP, "SSL certificate issued for different common name");
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID))
git_error_set(GIT_ERROR_NET, "SSL certificate has expired");
git_error_set(GIT_ERROR_HTTP, "SSL certificate has expired");
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA))
git_error_set(GIT_ERROR_NET, "SSL certificate signed by unknown CA");
git_error_set(GIT_ERROR_HTTP, "SSL certificate signed by unknown CA");
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT))
git_error_set(GIT_ERROR_NET, "SSL certificate is invalid");
git_error_set(GIT_ERROR_HTTP, "SSL certificate is invalid");
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED))
git_error_set(GIT_ERROR_NET, "certificate revocation check failed");
git_error_set(GIT_ERROR_HTTP, "certificate revocation check failed");
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED))
git_error_set(GIT_ERROR_NET, "SSL certificate was revoked");
git_error_set(GIT_ERROR_HTTP, "SSL certificate was revoked");
else if ((status & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR))
git_error_set(GIT_ERROR_NET, "security libraries could not be loaded");
git_error_set(GIT_ERROR_HTTP, "security libraries could not be loaded");
else
git_error_set(GIT_ERROR_NET, "unknown security error %lu", status);
git_error_set(GIT_ERROR_HTTP, "unknown security error %lu", status);
}
static int winhttp_connect(
......@@ -971,7 +971,7 @@ static int winhttp_stream_read(
replay:
/* Enforce a reasonable cap on the number of replays */
if (replay_count++ >= GIT_HTTP_REPLAY_MAX) {
git_error_set(GIT_ERROR_NET, "too many redirects or authentication replays");
git_error_set(GIT_ERROR_HTTP, "too many redirects or authentication replays");
return -1;
}
......@@ -1177,7 +1177,7 @@ replay:
}
if (HTTP_STATUS_OK != status_code) {
git_error_set(GIT_ERROR_NET, "request failed with status code: %lu", status_code);
git_error_set(GIT_ERROR_HTTP, "request failed with status code: %lu", status_code);
return -1;
}
......@@ -1204,7 +1204,7 @@ replay:
}
if (wcscmp(expected_content_type, content_type)) {
git_error_set(GIT_ERROR_NET, "received unexpected content-type");
git_error_set(GIT_ERROR_HTTP, "received unexpected content-type");
return -1;
}
......@@ -1239,7 +1239,7 @@ static int winhttp_stream_write_single(
/* This implementation of write permits only a single call. */
if (s->sent_request) {
git_error_set(GIT_ERROR_NET, "subtransport configured for only one write");
git_error_set(GIT_ERROR_HTTP, "subtransport configured for only one write");
return -1;
}
......@@ -1270,12 +1270,12 @@ static int put_uuid_string(LPWSTR buffer, size_t buffer_len_cch)
if (RPC_S_OK != status &&
RPC_S_UUID_LOCAL_ONLY != status &&
RPC_S_UUID_NO_ADDRESS != status) {
git_error_set(GIT_ERROR_NET, "unable to generate name for temp file");
git_error_set(GIT_ERROR_HTTP, "unable to generate name for temp file");
return -1;
}
if (buffer_len_cch < UUID_LENGTH_CCH + 1) {
git_error_set(GIT_ERROR_NET, "buffer too small for name of temp file");
git_error_set(GIT_ERROR_HTTP, "buffer too small for name of temp file");
return -1;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment