#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;
typedef struct {
git_stream parent;
git_stream *io;
+ int owned;
SSLContextRef ctx;
CFDataRef der_data;
git_cert_x509 cert_info;
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;
}
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;
}
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;
}
{
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;
}
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;
}
/*
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;
}
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