]> git.proxmox.com Git - libgit2.git/blobdiff - src/streams/stransport.c
New upstream version 0.28.1+dfsg.1
[libgit2.git] / src / streams / stransport.c
index cca17bb94b3d4dce3ef131c4c4c6fc576b600c83..a79d3cbf0d77057f409de75a16f33cb733df2ece 100644 (file)
 #include "git2/transport.h"
 
 #include "streams/socket.h"
-#include "streams/curl.h"
 
 static int stransport_error(OSStatus ret)
 {
        CFStringRef message;
 
        if (ret == noErr || ret == errSSLClosedGraceful) {
-               giterr_clear();
+               git_error_clear();
                return 0;
        }
 
 #if !TARGET_OS_IPHONE
        message = SecCopyErrorMessageString(ret, NULL);
-       GITERR_CHECK_ALLOC(message);
+       GIT_ERROR_CHECK_ALLOC(message);
 
-       giterr_set(GITERR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
+       git_error_set(GIT_ERROR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
        CFRelease(message);
 #else
-    giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
-    GIT_UNUSED(message);
+       git_error_set(GIT_ERROR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
+       GIT_UNUSED(message);
 #endif
 
        return -1;
@@ -44,6 +43,7 @@ static int stransport_error(OSStatus ret)
 typedef struct {
        git_stream parent;
        git_stream *io;
+       int owned;
        SSLContextRef ctx;
        CFDataRef der_data;
        git_cert_x509 cert_info;
@@ -57,12 +57,12 @@ static int stransport_connect(git_stream *stream)
        SecTrustResultType sec_res;
        OSStatus ret;
 
-       if ((error = git_stream_connect(st->io)) < 0)
+       if (st->owned && (error = git_stream_connect(st->io)) < 0)
                return error;
 
        ret = SSLHandshake(st->ctx);
        if (ret != errSSLServerAuthCompleted) {
-               giterr_set(GITERR_SSL, "unexpected return value from ssl handshake %d", ret);
+               git_error_set(GIT_ERROR_SSL, "unexpected return value from ssl handshake %d", (int)ret);
                return -1;
        }
 
@@ -78,13 +78,13 @@ static int stransport_connect(git_stream *stream)
        CFRelease(trust);
 
        if (sec_res == kSecTrustResultInvalid || sec_res == kSecTrustResultOtherError) {
-               giterr_set(GITERR_SSL, "internal security trust error");
+               git_error_set(GIT_ERROR_SSL, "internal security trust error");
                return -1;
        }
 
        if (sec_res == kSecTrustResultDeny || sec_res == kSecTrustResultRecoverableTrustFailure ||
            sec_res == kSecTrustResultFatalTrustFailure) {
-               giterr_set(GITERR_SSL, "untrusted connection error");
+               git_error_set(GIT_ERROR_SSL, "untrusted connection error");
                return GIT_ECERTIFICATE;
        }
 
@@ -112,7 +112,7 @@ static int stransport_certificate(git_cert **out, git_stream *stream)
        CFRelease(trust);
 
        if (st->der_data == NULL) {
-               giterr_set(GITERR_SSL, "retrieved invalid certificate data");
+               git_error_set(GIT_ERROR_SSL, "retrieved invalid certificate data");
                return -1;
        }
 
@@ -149,9 +149,8 @@ static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len)
 {
        git_stream *io = (git_stream *) conn;
 
-       if (git_stream_write(io, data, *len, 0) < 0) {
+       if (git_stream__write_full(io, data, *len, 0) < 0)
                return -36; /* "ioErr" from MacErrors.h which is not available on iOS */
-       }
 
        return noErr;
 }
@@ -164,11 +163,12 @@ static ssize_t stransport_write(git_stream *stream, const char *data, size_t len
 
        GIT_UNUSED(flags);
 
-       data_len = len;
+       data_len = min(len, SSIZE_MAX);
        if ((ret = SSLWrite(st->ctx, data, data_len, &processed)) != noErr)
                return stransport_error(ret);
 
-       return processed;
+       assert(processed < SSIZE_MAX);
+       return (ssize_t)processed;
 }
 
 /*
@@ -226,45 +226,42 @@ static int stransport_close(git_stream *stream)
        if (ret != noErr && ret != errSSLClosedGraceful)
                return stransport_error(ret);
 
-       return git_stream_close(st->io);
+       return st->owned ? git_stream_close(st->io) : 0;
 }
 
 static void stransport_free(git_stream *stream)
 {
        stransport_stream *st = (stransport_stream *) stream;
 
-       git_stream_free(st->io);
+       if (st->owned)
+               git_stream_free(st->io);
+
        CFRelease(st->ctx);
        if (st->der_data)
                CFRelease(st->der_data);
        git__free(st);
 }
 
-int git_stransport_stream_new(git_stream **out, const char *host, const char *port)
+static int stransport_wrap(
+       git_stream **out,
+       git_stream *in,
+       const char *host,
+       int owned)
 {
        stransport_stream *st;
-       int error;
        OSStatus ret;
 
-       assert(out && host);
+       assert(out && in && host);
 
        st = git__calloc(1, sizeof(stransport_stream));
-       GITERR_CHECK_ALLOC(st);
-
-#ifdef GIT_CURL
-       error = git_curl_stream_new(&st->io, host, port);
-#else
-       error = git_socket_stream_new(&st->io, host, port);
-#endif
+       GIT_ERROR_CHECK_ALLOC(st);
 
-       if (error < 0){
-               git__free(st);
-               return error;
-       }
+       st->io = in;
+       st->owned = owned;
 
        st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
        if (!st->ctx) {
-               giterr_set(GITERR_NET, "failed to create SSL context");
+               git_error_set(GIT_ERROR_NET, "failed to create SSL context");
                git__free(st);
                return -1;
        }
@@ -295,4 +292,32 @@ int git_stransport_stream_new(git_stream **out, const char *host, const char *po
        return 0;
 }
 
+int git_stransport_stream_wrap(
+       git_stream **out,
+       git_stream *in,
+       const char *host)
+{
+       return stransport_wrap(out, in, host, 0);
+}
+
+int git_stransport_stream_new(git_stream **out, const char *host, const char *port)
+{
+       git_stream *stream = NULL;
+       int error;
+
+       assert(out && host);
+
+       error = git_socket_stream_new(&stream, host, port);
+
+       if (!error)
+               error = stransport_wrap(out, stream, host, 1);
+
+       if (error < 0 && stream) {
+               git_stream_close(stream);
+               git_stream_free(stream);
+       }
+
+       return error;
+}
+
 #endif