mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-11 13:12:22 +00:00
Port HTTP(S) to the new stream API
This commit is contained in:
parent
02b4c1e2a4
commit
b6f5464e28
@ -13,16 +13,14 @@
|
|||||||
#include "smart.h"
|
#include "smart.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "auth_negotiate.h"
|
#include "auth_negotiate.h"
|
||||||
|
#include "openssl_stream.h"
|
||||||
|
#include "socket_stream.h"
|
||||||
|
|
||||||
git_http_auth_scheme auth_schemes[] = {
|
git_http_auth_scheme auth_schemes[] = {
|
||||||
{ GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
|
{ GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
|
||||||
{ GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
|
{ GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef GIT_SSL
|
|
||||||
# include <openssl/x509v3.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char *upload_pack_service = "upload-pack";
|
static const char *upload_pack_service = "upload-pack";
|
||||||
static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
|
static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
|
||||||
static const char *upload_pack_service_url = "/git-upload-pack";
|
static const char *upload_pack_service_url = "/git-upload-pack";
|
||||||
@ -62,7 +60,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
git_smart_subtransport parent;
|
git_smart_subtransport parent;
|
||||||
transport_smart *owner;
|
transport_smart *owner;
|
||||||
gitno_socket socket;
|
git_stream *io;
|
||||||
gitno_connection_data connection_data;
|
gitno_connection_data connection_data;
|
||||||
bool connected;
|
bool connected;
|
||||||
|
|
||||||
@ -474,7 +472,7 @@ static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
|
|||||||
static void clear_parser_state(http_subtransport *t)
|
static void clear_parser_state(http_subtransport *t)
|
||||||
{
|
{
|
||||||
http_parser_init(&t->parser, HTTP_RESPONSE);
|
http_parser_init(&t->parser, HTTP_RESPONSE);
|
||||||
gitno_buffer_setup(&t->socket,
|
gitno_buffer_setup_fromstream(t->io,
|
||||||
&t->parse_buffer,
|
&t->parse_buffer,
|
||||||
t->parse_buffer_data,
|
t->parse_buffer_data,
|
||||||
sizeof(t->parse_buffer_data));
|
sizeof(t->parse_buffer_data));
|
||||||
@ -498,7 +496,7 @@ static void clear_parser_state(http_subtransport *t)
|
|||||||
git_vector_free_deep(&t->www_authenticate);
|
git_vector_free_deep(&t->www_authenticate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
|
static int write_chunk(git_stream *io, const char *buffer, size_t len)
|
||||||
{
|
{
|
||||||
git_buf buf = GIT_BUF_INIT;
|
git_buf buf = GIT_BUF_INIT;
|
||||||
|
|
||||||
@ -508,7 +506,7 @@ static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
|
|||||||
if (git_buf_oom(&buf))
|
if (git_buf_oom(&buf))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (gitno_send(socket, buf.ptr, buf.size, 0) < 0) {
|
if (git_stream_write(io, buf.ptr, buf.size, 0) < 0) {
|
||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -516,11 +514,11 @@ static int write_chunk(gitno_socket *socket, const char *buffer, size_t len)
|
|||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
|
|
||||||
/* Chunk body */
|
/* Chunk body */
|
||||||
if (len > 0 && gitno_send(socket, buffer, len, 0) < 0)
|
if (len > 0 && git_stream_write(io, buffer, len, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Chunk footer */
|
/* Chunk footer */
|
||||||
if (gitno_send(socket, "\r\n", 2, 0) < 0)
|
if (git_stream_write(io, "\r\n", 2, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -535,57 +533,36 @@ static int http_connect(http_subtransport *t)
|
|||||||
t->parse_finished)
|
t->parse_finished)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (t->socket.socket)
|
if (t->io) {
|
||||||
gitno_close(&t->socket);
|
git_stream_close(t->io);
|
||||||
|
git_stream_free(t->io);
|
||||||
if (t->connection_data.use_ssl) {
|
t->io = NULL;
|
||||||
int tflags;
|
|
||||||
|
|
||||||
if (t->owner->parent.read_flags(&t->owner->parent, &tflags) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
flags |= GITNO_CONNECT_SSL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error = gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags);
|
if (t->connection_data.use_ssl) {
|
||||||
|
error = git_openssl_stream_new(&t->io, t->connection_data.host, t->connection_data.port);
|
||||||
|
} else {
|
||||||
|
error = git_socket_stream_new(&t->io, t->connection_data.host, t->connection_data.port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
GITERR_CHECK_VERSION(t->io, GIT_STREAM_VERSION, "git_stream");
|
||||||
|
|
||||||
|
error = git_stream_connect(t->io);
|
||||||
|
|
||||||
#ifdef GIT_SSL
|
#ifdef GIT_SSL
|
||||||
if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL) {
|
if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL) {
|
||||||
X509 *cert = SSL_get_peer_certificate(t->socket.ssl.ssl);
|
git_cert *cert;
|
||||||
git_cert_x509 cert_info, *cert_info_ptr;
|
int is_valid;
|
||||||
int len, is_valid;
|
|
||||||
unsigned char *guard, *encoded_cert;
|
|
||||||
|
|
||||||
/* Retrieve the length of the certificate first */
|
if ((error = git_stream_certificate(&cert, t->io)) < 0)
|
||||||
len = i2d_X509(cert, NULL);
|
return error;
|
||||||
if (len < 0) {
|
|
||||||
giterr_set(GITERR_NET, "failed to retrieve certificate information");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
encoded_cert = git__malloc(len);
|
|
||||||
GITERR_CHECK_ALLOC(encoded_cert);
|
|
||||||
/* i2d_X509 makes 'copy' point to just after the data */
|
|
||||||
guard = encoded_cert;
|
|
||||||
|
|
||||||
len = i2d_X509(cert, &guard);
|
|
||||||
if (len < 0) {
|
|
||||||
git__free(encoded_cert);
|
|
||||||
giterr_set(GITERR_NET, "failed to retrieve certificate information");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
giterr_clear();
|
giterr_clear();
|
||||||
is_valid = error != GIT_ECERTIFICATE;
|
is_valid = error != GIT_ECERTIFICATE;
|
||||||
cert_info.cert_type = GIT_CERT_X509;
|
error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload);
|
||||||
cert_info.data = encoded_cert;
|
|
||||||
cert_info.len = len;
|
|
||||||
|
|
||||||
cert_info_ptr = &cert_info;
|
|
||||||
|
|
||||||
error = t->owner->certificate_check_cb((git_cert *) cert_info_ptr, is_valid, t->connection_data.host, t->owner->message_cb_payload);
|
|
||||||
git__free(encoded_cert);
|
|
||||||
|
|
||||||
if (error < 0) {
|
if (error < 0) {
|
||||||
if (!giterr_last())
|
if (!giterr_last())
|
||||||
@ -626,7 +603,7 @@ replay:
|
|||||||
if (gen_request(&request, s, 0) < 0)
|
if (gen_request(&request, s, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
|
if (git_stream_write(t->io, request.ptr, request.size, 0) < 0) {
|
||||||
git_buf_free(&request);
|
git_buf_free(&request);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -642,13 +619,13 @@ replay:
|
|||||||
|
|
||||||
/* Flush, if necessary */
|
/* Flush, if necessary */
|
||||||
if (s->chunk_buffer_len > 0 &&
|
if (s->chunk_buffer_len > 0 &&
|
||||||
write_chunk(&t->socket, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
write_chunk(t->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
s->chunk_buffer_len = 0;
|
s->chunk_buffer_len = 0;
|
||||||
|
|
||||||
/* Write the final chunk. */
|
/* Write the final chunk. */
|
||||||
if (gitno_send(&t->socket, "0\r\n\r\n", 5, 0) < 0)
|
if (git_stream_write(t->io, "0\r\n\r\n", 5, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,7 +720,7 @@ static int http_stream_write_chunked(
|
|||||||
if (gen_request(&request, s, 0) < 0)
|
if (gen_request(&request, s, 0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0) {
|
if (git_stream_write(t->io, request.ptr, request.size, 0) < 0) {
|
||||||
git_buf_free(&request);
|
git_buf_free(&request);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -756,14 +733,14 @@ static int http_stream_write_chunked(
|
|||||||
if (len > CHUNK_SIZE) {
|
if (len > CHUNK_SIZE) {
|
||||||
/* Flush, if necessary */
|
/* Flush, if necessary */
|
||||||
if (s->chunk_buffer_len > 0) {
|
if (s->chunk_buffer_len > 0) {
|
||||||
if (write_chunk(&t->socket, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
if (write_chunk(t->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
s->chunk_buffer_len = 0;
|
s->chunk_buffer_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write chunk directly */
|
/* Write chunk directly */
|
||||||
if (write_chunk(&t->socket, buffer, len) < 0)
|
if (write_chunk(t->io, buffer, len) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -780,7 +757,7 @@ static int http_stream_write_chunked(
|
|||||||
|
|
||||||
/* Is the buffer full? If so, then flush */
|
/* Is the buffer full? If so, then flush */
|
||||||
if (CHUNK_SIZE == s->chunk_buffer_len) {
|
if (CHUNK_SIZE == s->chunk_buffer_len) {
|
||||||
if (write_chunk(&t->socket, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
if (write_chunk(t->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
s->chunk_buffer_len = 0;
|
s->chunk_buffer_len = 0;
|
||||||
@ -816,10 +793,10 @@ static int http_stream_write_single(
|
|||||||
if (gen_request(&request, s, len) < 0)
|
if (gen_request(&request, s, len) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (gitno_send(&t->socket, request.ptr, request.size, 0) < 0)
|
if (git_stream_write(t->io, request.ptr, request.size, 0) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
if (len && gitno_send(&t->socket, buffer, len, 0) < 0)
|
if (len && git_stream_write(t->io, buffer, len, 0) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
git_buf_free(&request);
|
git_buf_free(&request);
|
||||||
@ -986,9 +963,10 @@ static int http_close(git_smart_subtransport *subtransport)
|
|||||||
|
|
||||||
clear_parser_state(t);
|
clear_parser_state(t);
|
||||||
|
|
||||||
if (t->socket.socket) {
|
if (t->io) {
|
||||||
gitno_close(&t->socket);
|
git_stream_close(t->io);
|
||||||
memset(&t->socket, 0x0, sizeof(gitno_socket));
|
git_stream_free(t->io);
|
||||||
|
t->io = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->cred) {
|
if (t->cred) {
|
||||||
|
Loading…
Reference in New Issue
Block a user