summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/global.c4
-rw-r--r--src/streams/registry.c99
-rw-r--r--src/streams/registry.h19
-rw-r--r--src/streams/socket.c34
-rw-r--r--src/streams/tls.c77
-rw-r--r--src/streams/tls.h3
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, &registration);
+ } 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,