Git-Raw
view release on metacpan or search on metacpan
deps/libgit2/src/libgit2/transports/http.c view on Meta::CPAN
int error;
/* NTLM requires a full challenge/response */
if (transport->server.auth_schemetypes == GIT_HTTP_AUTH_NTLM)
steps = GIT_AUTH_STEPS_NTLM;
/*
* Send at most two requests: one without any authentication to see
* if we get prompted to authenticate. If we do, send a second one
* with the first authentication message. The final authentication
* message with the response will occur with the *actual* POST data.
*/
for (step = 0; step < steps && !complete; step++) {
git_net_url_dispose(&url);
git_http_response_dispose(&response);
if ((error = generate_request(&url, &request, stream, len)) < 0 ||
(error = git_http_client_send_request(client, &request)) < 0 ||
(error = git_http_client_send_body(client, probe, len)) < 0 ||
(error = git_http_client_read_response(&response, client)) < 0 ||
(error = git_http_client_skip_body(client)) < 0 ||
(error = handle_response(&complete, stream, &response, true)) < 0)
goto done;
}
done:
git_http_response_dispose(&response);
git_net_url_dispose(&url);
return error;
}
/*
* Write to an HTTP transport - for the first invocation of this function
* (ie, when stream->state == HTTP_STATE_NONE), we'll send a POST request
* to the remote host. If we're sending chunked data, then subsequent calls
* will write the additional data given in the buffer. If we're not chunking,
* then the caller should have given us all the data in the original call.
* The caller should call http_stream_read_response to get the result.
*/
static int http_stream_write(
git_smart_subtransport_stream *s,
const char *buffer,
size_t len)
{
http_stream *stream = GIT_CONTAINER_OF(s, http_stream, parent);
http_subtransport *transport = OWNING_SUBTRANSPORT(stream);
git_net_url url = GIT_NET_URL_INIT;
git_http_request request = {0};
git_http_response response = {0};
int error;
while (stream->state == HTTP_STATE_NONE &&
stream->replay_count < GIT_HTTP_REPLAY_MAX) {
git_net_url_dispose(&url);
git_http_response_dispose(&response);
/*
* If we're authenticating with a connection-based mechanism
* (NTLM, Kerberos), send a "probe" packet. Servers SHOULD
* authenticate an entire keep-alive connection, so ideally
* we should not need to authenticate but some servers do
* not support this. By sending a probe packet, we'll be
* able to follow up with a second POST using the actual
* data (and, in the degenerate case, the authentication
* header as well).
*/
if (needs_probe(stream) && (error = send_probe(stream)) < 0)
goto done;
/* Send the regular POST request. */
if ((error = generate_request(&url, &request, stream, len)) < 0 ||
(error = git_http_client_send_request(
transport->http_client, &request)) < 0)
goto done;
if (request.expect_continue &&
git_http_client_has_response(transport->http_client)) {
bool complete;
/*
* If we got a response to an expect/continue, then
* it's something other than a 100 and we should
* deal with the response somehow.
*/
if ((error = git_http_client_read_response(&response, transport->http_client)) < 0 ||
(error = handle_response(&complete, stream, &response, true)) < 0)
goto done;
} else {
stream->state = HTTP_STATE_SENDING_REQUEST;
}
stream->replay_count++;
}
if (stream->state == HTTP_STATE_NONE) {
git_error_set(GIT_ERROR_HTTP,
"too many redirects or authentication replays");
error = GIT_ERROR; /* not GIT_EAUTH because the exact cause is unclear */
goto done;
}
GIT_ASSERT(stream->state == HTTP_STATE_SENDING_REQUEST);
error = git_http_client_send_body(transport->http_client, buffer, len);
done:
git_http_response_dispose(&response);
git_net_url_dispose(&url);
return error;
}
/*
* Read from an HTTP transport after it has been written to. This is the
* response from a POST request made by http_stream_write.
*/
static int http_stream_read_response(
git_smart_subtransport_stream *s,
char *buffer,
size_t buffer_size,
size_t *out_len)
( run in 0.840 second using v1.01-cache-2.11-cpan-39bf76dae61 )