diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/global.c | 4 | ||||
| -rw-r--r-- | src/streams/registry.c | 99 | ||||
| -rw-r--r-- | src/streams/registry.h | 19 | ||||
| -rw-r--r-- | src/streams/socket.c | 34 | ||||
| -rw-r--r-- | src/streams/tls.c | 77 | ||||
| -rw-r--r-- | src/streams/tls.h | 3 |
6 files changed, 163 insertions, 73 deletions
diff --git a/src/global.c b/src/global.c index 51d34f61b..86a35a2ff 100644 --- a/src/global.c +++ b/src/global.c @@ -12,7 +12,7 @@ #include "sysdir.h" #include "filter.h" #include "merge_driver.h" -#include "streams/tls.h" +#include "streams/registry.h" #include "streams/mbedtls.h" #include "streams/openssl.h" #include "thread-utils.h" @@ -67,7 +67,7 @@ static int init_common(void) (ret = git_filter_global_init()) == 0 && (ret = git_merge_driver_global_init()) == 0 && (ret = git_transport_ssh_global_init()) == 0 && - (ret = git_tls_stream_global_init()) == 0 && + (ret = git_stream_registry_global_init()) == 0 && (ret = git_openssl_stream_global_init()) == 0 && (ret = git_mbedtls_stream_global_init()) == 0) ret = git_mwindow_global_init(); diff --git a/src/streams/registry.c b/src/streams/registry.c new file mode 100644 index 000000000..210e2d024 --- /dev/null +++ b/src/streams/registry.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "git2/errors.h" + +#include "common.h" +#include "global.h" +#include "streams/tls.h" +#include "streams/mbedtls.h" +#include "streams/openssl.h" +#include "streams/stransport.h" + +struct stream_registry { + git_rwlock lock; + git_stream_registration callbacks; + git_stream_registration tls_callbacks; +}; + +static struct stream_registry stream_registry; + +static void shutdown_stream_registry(void) +{ + git_rwlock_free(&stream_registry.lock); +} + +int git_stream_registry_global_init(void) +{ + if (git_rwlock_init(&stream_registry.lock) < 0) + return -1; + + git__on_shutdown(shutdown_stream_registry); + return 0; +} + +int git_stream_registry_lookup(git_stream_registration *out, int tls) +{ + git_stream_registration *target = tls ? + &stream_registry.callbacks : + &stream_registry.tls_callbacks; + int error = GIT_ENOTFOUND; + + assert(out); + + if (git_rwlock_rdlock(&stream_registry.lock) < 0) { + giterr_set(GITERR_OS, "failed to lock stream registry"); + return -1; + } + + if (target->init) { + memcpy(out, target, sizeof(git_stream_registration)); + error = 0; + } + + git_rwlock_rdunlock(&stream_registry.lock); + return error; +} + +int git_stream_register(int tls, git_stream_registration *registration) +{ + git_stream_registration *target = tls ? + &stream_registry.callbacks : + &stream_registry.tls_callbacks; + + assert(!registration || registration->init); + + GITERR_CHECK_VERSION(registration, GIT_STREAM_VERSION, "stream_registration"); + + if (git_rwlock_wrlock(&stream_registry.lock) < 0) { + giterr_set(GITERR_OS, "failed to lock stream registry"); + return -1; + } + + if (registration) + memcpy(target, registration, sizeof(git_stream_registration)); + else + memset(target, 0, sizeof(git_stream_registration)); + + git_rwlock_wrunlock(&stream_registry.lock); + return 0; +} + +int git_stream_register_tls(git_stream_cb ctor) +{ + git_stream_registration registration = {0}; + + if (ctor) { + registration.version = GIT_STREAM_VERSION; + registration.init = ctor; + registration.wrap = NULL; + + return git_stream_register(1, ®istration); + } else { + return git_stream_register(1, NULL); + } +} diff --git a/src/streams/registry.h b/src/streams/registry.h new file mode 100644 index 000000000..92f87a7bc --- /dev/null +++ b/src/streams/registry.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_streams_registry_h__ +#define INCLUDE_streams_registry_h__ + +#include "common.h" +#include "git2/sys/stream.h" + +/** Configure stream registry. */ +int git_stream_registry_global_init(void); + +/** Lookup a stream registration. */ +extern int git_stream_registry_lookup(git_stream_registration *out, int tls); + +#endif diff --git a/src/streams/socket.c b/src/streams/socket.c index 0c6073b66..21f7fea06 100644 --- a/src/streams/socket.c +++ b/src/streams/socket.c @@ -9,6 +9,7 @@ #include "posix.h" #include "netops.h" +#include "registry.h" #include "stream.h" #ifndef _WIN32 @@ -180,11 +181,14 @@ void socket_free(git_stream *stream) git__free(st); } -int git_socket_stream_new(git_stream **out, const char *host, const char *port) +static int default_socket_stream_new( + git_stream **out, + const char *host, + const char *port) { git_socket_stream *st; - assert(out && host); + assert(out && host && port); st = git__calloc(1, sizeof(git_socket_stream)); GITERR_CHECK_ALLOC(st); @@ -208,3 +212,29 @@ int git_socket_stream_new(git_stream **out, const char *host, const char *port) *out = (git_stream *) st; return 0; } + +int git_socket_stream_new( + git_stream **out, + const char *host, + const char *port) +{ + int (*init)(git_stream **, const char *, const char *) = NULL; + git_stream_registration custom = {0}; + int error; + + assert(out && host && port); + + if ((error = git_stream_registry_lookup(&custom, 0)) == 0) + init = custom.init; + else if (error == GIT_ENOTFOUND) + init = default_socket_stream_new; + else + return error; + + if (!init) { + giterr_set(GITERR_NET, "there is no socket stream available"); + return -1; + } + + return init(out, host, port); +} diff --git a/src/streams/tls.c b/src/streams/tls.c index fe0725272..0e10697cd 100644 --- a/src/streams/tls.c +++ b/src/streams/tls.c @@ -9,66 +9,23 @@ #include "common.h" #include "global.h" +#include "streams/registry.h" #include "streams/tls.h" #include "streams/mbedtls.h" #include "streams/openssl.h" #include "streams/stransport.h" -struct git_tls_stream_registration { - git_rwlock lock; - git_stream_registration callbacks; -}; - -static struct git_tls_stream_registration stream_registration; - -static void shutdown_ssl(void) -{ - git_rwlock_free(&stream_registration.lock); -} - -int git_tls_stream_global_init(void) -{ - if (git_rwlock_init(&stream_registration.lock) < 0) - return -1; - - git__on_shutdown(shutdown_ssl); - return 0; -} - -int git_stream_register_tls(git_stream_registration *registration) -{ - assert(!registration || registration->init); - - if (git_rwlock_wrlock(&stream_registration.lock) < 0) { - giterr_set(GITERR_OS, "failed to lock stream registration"); - return -1; - } - - if (registration) - memcpy(&stream_registration.callbacks, registration, - sizeof(git_stream_registration)); - else - memset(&stream_registration.callbacks, 0, - sizeof(git_stream_registration)); - - git_rwlock_wrunlock(&stream_registration.lock); - return 0; -} - int git_tls_stream_new(git_stream **out, const char *host, const char *port) { int (*init)(git_stream **, const char *, const char *) = NULL; + git_stream_registration custom = {0}; + int error; assert(out && host && port); - if (git_rwlock_rdlock(&stream_registration.lock) < 0) { - giterr_set(GITERR_OS, "failed to lock stream registration"); - return -1; - } - - if (stream_registration.callbacks.init) { - init = stream_registration.callbacks.init; - } else { + if ((error = git_stream_registry_lookup(&custom, 1)) == 0) { + init = custom.init; + } else if (error == GIT_ENOTFOUND) { #ifdef GIT_SECURE_TRANSPORT init = git_stransport_stream_new; #elif defined(GIT_OPENSSL) @@ -76,11 +33,8 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port) #elif defined(GIT_MBEDTLS) init = git_mbedtls_stream_new; #endif - } - - if (git_rwlock_rdunlock(&stream_registration.lock) < 0) { - giterr_set(GITERR_OS, "failed to unlock stream registration"); - return -1; + } else { + return error; } if (!init) { @@ -94,16 +48,12 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port) int git_tls_stream_wrap(git_stream **out, git_stream *in, const char *host) { int (*wrap)(git_stream **, git_stream *, const char *) = NULL; + git_stream_registration custom = {0}; assert(out && in); - if (git_rwlock_rdlock(&stream_registration.lock) < 0) { - giterr_set(GITERR_OS, "failed to lock stream registration"); - return -1; - } - - if (stream_registration.callbacks.wrap) { - wrap = stream_registration.callbacks.wrap; + if (git_stream_registry_lookup(&custom, 1) == 0) { + wrap = custom.wrap; } else { #ifdef GIT_SECURE_TRANSPORT wrap = git_stransport_stream_wrap; @@ -114,11 +64,6 @@ int git_tls_stream_wrap(git_stream **out, git_stream *in, const char *host) #endif } - if (git_rwlock_rdunlock(&stream_registration.lock) < 0) { - giterr_set(GITERR_OS, "failed to unlock stream registration"); - return -1; - } - if (!wrap) { giterr_set(GITERR_SSL, "there is no TLS stream available"); return -1; diff --git a/src/streams/tls.h b/src/streams/tls.h index 00c6e0b56..465a6ea89 100644 --- a/src/streams/tls.h +++ b/src/streams/tls.h @@ -11,9 +11,6 @@ #include "git2/sys/stream.h" -/** Configure TLS stream functions. */ -int git_tls_stream_global_init(void); - /** * Create a TLS stream with the most appropriate backend available for * the current platform, whether that's SecureTransport on macOS, |
