diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2014-11-01 21:35:06 +0100 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2014-12-10 01:39:09 +0100 |
commit | b6f5464e2823b0782305d79c7d94b4f2fdfe0322 (patch) | |
tree | 22c4646e9da0fc75c0df1ac3b3feeaaa439a1256 | |
parent | 02b4c1e2a426404ad7cad8e8a114f7f36bdb8b59 (diff) | |
download | libgit2-b6f5464e2823b0782305d79c7d94b4f2fdfe0322.tar.gz |
Port HTTP(S) to the new stream API
-rw-r--r-- | src/transports/http.c | 100 |
1 files changed, 39 insertions, 61 deletions
diff --git a/src/transports/http.c b/src/transports/http.c index 234ee229f..c433a5913 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -13,16 +13,14 @@ #include "smart.h" #include "auth.h" #include "auth_negotiate.h" +#include "openssl_stream.h" +#include "socket_stream.h" git_http_auth_scheme auth_schemes[] = { { GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate }, { 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_ls_service_url = "/info/refs?service=git-upload-pack"; static const char *upload_pack_service_url = "/git-upload-pack"; @@ -62,7 +60,7 @@ typedef struct { typedef struct { git_smart_subtransport parent; transport_smart *owner; - gitno_socket socket; + git_stream *io; gitno_connection_data connection_data; 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) { http_parser_init(&t->parser, HTTP_RESPONSE); - gitno_buffer_setup(&t->socket, + gitno_buffer_setup_fromstream(t->io, &t->parse_buffer, 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); } -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; @@ -508,7 +506,7 @@ static int write_chunk(gitno_socket *socket, const char *buffer, size_t len) if (git_buf_oom(&buf)) 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); return -1; } @@ -516,11 +514,11 @@ static int write_chunk(gitno_socket *socket, const char *buffer, size_t len) git_buf_free(&buf); /* 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; /* Chunk footer */ - if (gitno_send(socket, "\r\n", 2, 0) < 0) + if (git_stream_write(io, "\r\n", 2, 0) < 0) return -1; return 0; @@ -535,57 +533,36 @@ static int http_connect(http_subtransport *t) t->parse_finished) return 0; - if (t->socket.socket) - gitno_close(&t->socket); + if (t->io) { + git_stream_close(t->io); + git_stream_free(t->io); + t->io = NULL; + } if (t->connection_data.use_ssl) { - int tflags; + 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 (t->owner->parent.read_flags(&t->owner->parent, &tflags) < 0) - return -1; + if (error < 0) + return error; - flags |= GITNO_CONNECT_SSL; - } + GITERR_CHECK_VERSION(t->io, GIT_STREAM_VERSION, "git_stream"); - error = gitno_connect(&t->socket, t->connection_data.host, t->connection_data.port, flags); + error = git_stream_connect(t->io); #ifdef GIT_SSL if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL) { - X509 *cert = SSL_get_peer_certificate(t->socket.ssl.ssl); - git_cert_x509 cert_info, *cert_info_ptr; - int len, is_valid; - unsigned char *guard, *encoded_cert; - - /* Retrieve the length of the certificate first */ - len = i2d_X509(cert, NULL); - if (len < 0) { - giterr_set(GITERR_NET, "failed to retrieve certificate information"); - return -1; - } - + git_cert *cert; + int is_valid; - 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; - } + if ((error = git_stream_certificate(&cert, t->io)) < 0) + return error; giterr_clear(); is_valid = error != GIT_ECERTIFICATE; - cert_info.cert_type = GIT_CERT_X509; - 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); + error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload); if (error < 0) { if (!giterr_last()) @@ -626,7 +603,7 @@ replay: if (gen_request(&request, s, 0) < 0) 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); return -1; } @@ -642,13 +619,13 @@ replay: /* Flush, if necessary */ 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; s->chunk_buffer_len = 0; /* 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; } @@ -743,7 +720,7 @@ static int http_stream_write_chunked( if (gen_request(&request, s, 0) < 0) 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); return -1; } @@ -756,14 +733,14 @@ static int http_stream_write_chunked( if (len > CHUNK_SIZE) { /* Flush, if necessary */ 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; s->chunk_buffer_len = 0; } /* Write chunk directly */ - if (write_chunk(&t->socket, buffer, len) < 0) + if (write_chunk(t->io, buffer, len) < 0) return -1; } else { @@ -780,7 +757,7 @@ static int http_stream_write_chunked( /* Is the buffer full? If so, then flush */ 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; s->chunk_buffer_len = 0; @@ -816,10 +793,10 @@ static int http_stream_write_single( if (gen_request(&request, s, len) < 0) 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; - if (len && gitno_send(&t->socket, buffer, len, 0) < 0) + if (len && git_stream_write(t->io, buffer, len, 0) < 0) goto on_error; git_buf_free(&request); @@ -986,9 +963,10 @@ static int http_close(git_smart_subtransport *subtransport) clear_parser_state(t); - if (t->socket.socket) { - gitno_close(&t->socket); - memset(&t->socket, 0x0, sizeof(gitno_socket)); + if (t->io) { + git_stream_close(t->io); + git_stream_free(t->io); + t->io = NULL; } if (t->cred) { |