diff --git a/src/netops.c b/src/netops.c index 23e7e9d3c..ab135c46b 100644 --- a/src/netops.c +++ b/src/netops.c @@ -104,6 +104,16 @@ static int ssl_set_error(gitno_ssl *ssl, int error) int gitno_recv(gitno_buffer *buf) { + if (buf->io) { + int ret; + ret = git_stream_read(buf->io, buf->data + buf->offset, buf->len - buf->offset); + if (ret < 0) + return -1; + + buf->offset += ret; + return ret; + } + return buf->recv(buf); } @@ -168,6 +178,15 @@ void gitno_buffer_setup(gitno_socket *socket, gitno_buffer *buf, char *data, siz gitno_buffer_setup_callback(socket, buf, data, len, gitno__recv, NULL); } +void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len) +{ + memset(data, 0x0, len); + buf->data = data; + buf->len = len; + buf->offset = 0; + buf->io = st; +} + /* Consume up to ptr and move the rest of the buffer to the beginning */ void gitno_consume(gitno_buffer *buf, const char *ptr) { diff --git a/src/netops.h b/src/netops.h index 8ad915301..fee6d82da 100644 --- a/src/netops.h +++ b/src/netops.h @@ -9,6 +9,7 @@ #include "posix.h" #include "common.h" +#include "stream.h" #ifdef GIT_SSL # include @@ -32,6 +33,7 @@ typedef struct gitno_buffer { char *data; size_t len; size_t offset; + git_stream *io; gitno_socket *socket; int (*recv)(struct gitno_buffer *buffer); void *cb_data; @@ -57,6 +59,7 @@ enum { int gitno__match_host(const char *pattern, const char *host); void gitno_buffer_setup(gitno_socket *t, gitno_buffer *buf, char *data, size_t len); +void gitno_buffer_setup_fromstream(git_stream *st, gitno_buffer *buf, char *data, size_t len); void gitno_buffer_setup_callback(gitno_socket *t, gitno_buffer *buf, char *data, size_t len, int (*recv)(gitno_buffer *buf), void *cb_data); int gitno_recv(gitno_buffer *buf); diff --git a/src/transports/git.c b/src/transports/git.c index e2690fe36..6f25736b1 100644 --- a/src/transports/git.c +++ b/src/transports/git.c @@ -9,6 +9,8 @@ #include "buffer.h" #include "netops.h" #include "git2/sys/transport.h" +#include "stream.h" +#include "socket_stream.h" #define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport) @@ -18,16 +20,16 @@ static const char cmd_receivepack[] = "git-receive-pack"; typedef struct { git_smart_subtransport_stream parent; - gitno_socket socket; + git_stream *io; const char *cmd; char *url; unsigned sent_command : 1; -} git_stream; +} git_proto_stream; typedef struct { git_smart_subtransport parent; git_transport *owner; - git_stream *current_stream; + git_proto_stream *current_stream; } git_subtransport; /* @@ -67,7 +69,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) return 0; } -static int send_command(git_stream *s) +static int send_command(git_proto_stream *s) { int error; git_buf request = GIT_BUF_INIT; @@ -76,10 +78,7 @@ static int send_command(git_stream *s) if (error < 0) goto cleanup; - /* It looks like negative values are errors here, and positive values - * are the number of bytes sent. */ - error = gitno_send(&s->socket, request.ptr, request.size, 0); - + error = git_stream_write(s->io, request.ptr, request.size, 0); if (error >= 0) s->sent_command = 1; @@ -88,14 +87,14 @@ cleanup: return error; } -static int git_stream_read( +static int git_proto_stream_read( git_smart_subtransport_stream *stream, char *buffer, size_t buf_size, size_t *bytes_read) { int error; - git_stream *s = (git_stream *)stream; + git_proto_stream *s = (git_proto_stream *)stream; gitno_buffer buf; *bytes_read = 0; @@ -103,7 +102,7 @@ static int git_stream_read( if (!s->sent_command && (error = send_command(s)) < 0) return error; - gitno_buffer_setup(&s->socket, &buf, buffer, buf_size); + gitno_buffer_setup_fromstream(s->io, &buf, buffer, buf_size); if ((error = gitno_recv(&buf)) < 0) return error; @@ -113,23 +112,23 @@ static int git_stream_read( return 0; } -static int git_stream_write( +static int git_proto_stream_write( git_smart_subtransport_stream *stream, const char *buffer, size_t len) { int error; - git_stream *s = (git_stream *)stream; + git_proto_stream *s = (git_proto_stream *)stream; if (!s->sent_command && (error = send_command(s)) < 0) return error; - return gitno_send(&s->socket, buffer, len, 0); + return git_stream_write(s->io, buffer, len, 0); } -static void git_stream_free(git_smart_subtransport_stream *stream) +static void git_proto_stream_free(git_smart_subtransport_stream *stream) { - git_stream *s = (git_stream *)stream; + git_proto_stream *s = (git_proto_stream *)stream; git_subtransport *t = OWNING_SUBTRANSPORT(s); int ret; @@ -137,33 +136,31 @@ static void git_stream_free(git_smart_subtransport_stream *stream) t->current_stream = NULL; - if (s->socket.socket) { - ret = gitno_close(&s->socket); - assert(!ret); - } - + git_stream_free(s->io); git__free(s->url); git__free(s); } -static int git_stream_alloc( +static int git_proto_stream_alloc( git_subtransport *t, const char *url, const char *cmd, + const char *host, + const char *port, git_smart_subtransport_stream **stream) { - git_stream *s; + git_proto_stream *s; if (!stream) return -1; - s = git__calloc(sizeof(git_stream), 1); + s = git__calloc(sizeof(git_proto_stream), 1); GITERR_CHECK_ALLOC(s); s->parent.subtransport = &t->parent; - s->parent.read = git_stream_read; - s->parent.write = git_stream_write; - s->parent.free = git_stream_free; + s->parent.read = git_proto_stream_read; + s->parent.write = git_proto_stream_write; + s->parent.free = git_proto_stream_free; s->cmd = cmd; s->url = git__strdup(url); @@ -173,6 +170,11 @@ static int git_stream_alloc( return -1; } + if ((git_socket_stream_new(&s->io, host, port)) < 0) + return -1; + + GITERR_CHECK_VERSION(s->io, GIT_STREAM_VERSION, "git_stream"); + *stream = &s->parent; return 0; } @@ -184,7 +186,7 @@ static int _git_uploadpack_ls( { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *stream_url = url; - git_stream *s; + git_proto_stream *s; int error; *stream = NULL; @@ -192,26 +194,32 @@ static int _git_uploadpack_ls( if (!git__prefixcmp(url, prefix_git)) stream_url += strlen(prefix_git); - if ((error = git_stream_alloc(t, stream_url, cmd_uploadpack, stream)) < 0) + if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT)) < 0) return error; - s = (git_stream *)*stream; + error = git_proto_stream_alloc(t, stream_url, cmd_uploadpack, host, port, stream); - if (!(error = gitno_extract_url_parts( - &host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) { + git__free(host); + git__free(port); + git__free(path); + git__free(user); + git__free(pass); - if (!(error = gitno_connect(&s->socket, host, port, 0))) - t->current_stream = s; - git__free(host); - git__free(port); - git__free(path); - git__free(user); - git__free(pass); - } else if (*stream) - git_stream_free(*stream); + if (error < 0) { + git_proto_stream_free(*stream); + return error; + } - return error; + s = (git_proto_stream *) *stream; + if ((error = git_stream_connect(s->io)) < 0) { + git_proto_stream_free(*stream); + return error; + } + + t->current_stream = s; + + return 0; } static int _git_uploadpack( @@ -237,31 +245,37 @@ static int _git_receivepack_ls( { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *stream_url = url; - git_stream *s; + git_proto_stream *s; int error; *stream = NULL; if (!git__prefixcmp(url, prefix_git)) stream_url += strlen(prefix_git); - if (git_stream_alloc(t, stream_url, cmd_receivepack, stream) < 0) - return -1; + if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT)) < 0) + return error; - s = (git_stream *)*stream; + error = git_proto_stream_alloc(t, stream_url, cmd_receivepack, host, port, stream); - if (!(error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, GIT_DEFAULT_PORT))) { - if (!(error = gitno_connect(&s->socket, host, port, 0))) - t->current_stream = s; + git__free(host); + git__free(port); + git__free(path); + git__free(user); + git__free(pass); - git__free(host); - git__free(port); - git__free(path); - git__free(user); - git__free(pass); - } else if (*stream) - git_stream_free(*stream); + if (error < 0) { + git_proto_stream_free(*stream); + return error; + } - return error; + s = (git_proto_stream *) *stream; + + if ((error = git_stream_connect(s->io)) < 0) + return error; + + t->current_stream = s; + + return 0; } static int _git_receivepack(