Skip to content

Commit df2cc10

Browse files
committed
stream: provide generic registration API
Update the new stream registration API to be `git_stream_register` which takes a registration structure and a TLS boolean. This allows callers to register non-TLS streams as well as TLS streams. Provide `git_stream_register_tls` that takes just the init callback for backward compatibliity.
1 parent 0467606 commit df2cc10

File tree

8 files changed

+262
-84
lines changed

8 files changed

+262
-84
lines changed

include/git2/sys/stream.h

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ typedef struct {
4545
int version;
4646

4747
/**
48-
* Called to create a new TLS connection to a given host.
48+
* Called to create a new connection to a given host.
4949
*
50-
* @param out The created TLS stream
50+
* @param out The created stream
5151
* @param host The hostname to connect to; may be a hostname or
5252
* IP address
5353
* @param port The port to connect to; may be a port number or
@@ -57,11 +57,12 @@ typedef struct {
5757
int (*init)(git_stream **out, const char *host, const char *port);
5858

5959
/**
60-
* Called to create a new TLS connection on top of the given
61-
* stream. May be used to proxy a TLS stream over a CONNECT
62-
* session.
60+
* Called to create a new connection on top of the given stream. If
61+
* this is a TLS stream, then this function may be used to proxy a
62+
* TLS stream over an HTTP CONNECT session. If this is unset, then
63+
* HTTP CONNECT proxies will not be supported.
6364
*
64-
* @param out The created TLS stream
65+
* @param out The created stream
6566
* @param in An existing stream to add TLS to
6667
* @param host The hostname that the stream is connected to,
6768
* for certificate validation
@@ -71,17 +72,45 @@ typedef struct {
7172
} git_stream_registration;
7273

7374
/**
74-
* Register TLS stream constructors for the library to use
75+
* Register stream constructors for the library to use
7576
*
7677
* If a registration structure is already set, it will be overwritten.
7778
* Pass `NULL` in order to deregister the current constructor and return
7879
* to the system defaults.
7980
*
8081
* @param registration the registration data
82+
* @param tls 1 if the registration is for TLS streams, 0 for regular
83+
* (insecure) sockets
8184
* @return 0 or an error code
8285
*/
83-
GIT_EXTERN(int) git_stream_register_tls(
84-
git_stream_registration *registration);
86+
GIT_EXTERN(int) git_stream_register(
87+
int tls, git_stream_registration *registration);
88+
89+
/** @name Deprecated TLS Stream Registration Functions
90+
*
91+
* These typedefs and functions are retained for backward compatibility.
92+
* The newer versions of these functions and structures should be preferred
93+
* in all new code.
94+
*/
95+
96+
/**@{*/
97+
98+
/**
99+
* @deprecated Provide a git_stream_registration to git_stream_register
100+
* @see git_stream_registration
101+
*/
102+
typedef int (*git_stream_cb)(git_stream **out, const char *host, const char *port);
103+
104+
/**
105+
* Register a TLS stream constructor for the library to use. This stream
106+
* will not support HTTP CONNECT proxies.
107+
*
108+
* @deprecated Provide a git_stream_registration to git_stream_register
109+
* @see git_stream_register
110+
*/
111+
GIT_EXTERN(int) git_stream_register_tls(git_stream_cb ctor);
112+
113+
/**@}*/
85114

86115
GIT_END_DECL
87116

src/global.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "sysdir.h"
1313
#include "filter.h"
1414
#include "merge_driver.h"
15-
#include "streams/tls.h"
15+
#include "streams/registry.h"
1616
#include "streams/mbedtls.h"
1717
#include "streams/openssl.h"
1818
#include "thread-utils.h"
@@ -67,7 +67,7 @@ static int init_common(void)
6767
(ret = git_filter_global_init()) == 0 &&
6868
(ret = git_merge_driver_global_init()) == 0 &&
6969
(ret = git_transport_ssh_global_init()) == 0 &&
70-
(ret = git_tls_stream_global_init()) == 0 &&
70+
(ret = git_stream_registry_global_init()) == 0 &&
7171
(ret = git_openssl_stream_global_init()) == 0 &&
7272
(ret = git_mbedtls_stream_global_init()) == 0)
7373
ret = git_mwindow_global_init();

src/streams/registry.c

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
#include "git2/errors.h"
9+
10+
#include "common.h"
11+
#include "global.h"
12+
#include "streams/tls.h"
13+
#include "streams/mbedtls.h"
14+
#include "streams/openssl.h"
15+
#include "streams/stransport.h"
16+
17+
struct stream_registry {
18+
git_rwlock lock;
19+
git_stream_registration callbacks;
20+
git_stream_registration tls_callbacks;
21+
};
22+
23+
static struct stream_registry stream_registry;
24+
25+
static void shutdown_stream_registry(void)
26+
{
27+
git_rwlock_free(&stream_registry.lock);
28+
}
29+
30+
int git_stream_registry_global_init(void)
31+
{
32+
if (git_rwlock_init(&stream_registry.lock) < 0)
33+
return -1;
34+
35+
git__on_shutdown(shutdown_stream_registry);
36+
return 0;
37+
}
38+
39+
int git_stream_registry_lookup(git_stream_registration *out, int tls)
40+
{
41+
git_stream_registration *target = tls ?
42+
&stream_registry.callbacks :
43+
&stream_registry.tls_callbacks;
44+
int error = GIT_ENOTFOUND;
45+
46+
assert(out);
47+
48+
if (git_rwlock_rdlock(&stream_registry.lock) < 0) {
49+
giterr_set(GITERR_OS, "failed to lock stream registry");
50+
return -1;
51+
}
52+
53+
if (target->init) {
54+
memcpy(out, target, sizeof(git_stream_registration));
55+
error = 0;
56+
}
57+
58+
git_rwlock_rdunlock(&stream_registry.lock);
59+
return error;
60+
}
61+
62+
int git_stream_register(int tls, git_stream_registration *registration)
63+
{
64+
git_stream_registration *target = tls ?
65+
&stream_registry.callbacks :
66+
&stream_registry.tls_callbacks;
67+
68+
assert(!registration || registration->init);
69+
70+
GITERR_CHECK_VERSION(registration, GIT_STREAM_VERSION, "stream_registration");
71+
72+
if (git_rwlock_wrlock(&stream_registry.lock) < 0) {
73+
giterr_set(GITERR_OS, "failed to lock stream registry");
74+
return -1;
75+
}
76+
77+
if (registration)
78+
memcpy(target, registration, sizeof(git_stream_registration));
79+
else
80+
memset(target, 0, sizeof(git_stream_registration));
81+
82+
git_rwlock_wrunlock(&stream_registry.lock);
83+
return 0;
84+
}
85+
86+
int git_stream_register_tls(git_stream_cb ctor)
87+
{
88+
git_stream_registration registration = {0};
89+
90+
if (ctor) {
91+
registration.version = GIT_STREAM_VERSION;
92+
registration.init = ctor;
93+
registration.wrap = NULL;
94+
95+
return git_stream_register(1, &registration);
96+
} else {
97+
return git_stream_register(1, NULL);
98+
}
99+
}

src/streams/registry.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
#ifndef INCLUDE_streams_registry_h__
8+
#define INCLUDE_streams_registry_h__
9+
10+
#include "common.h"
11+
#include "git2/sys/stream.h"
12+
13+
/** Configure stream registry. */
14+
int git_stream_registry_global_init(void);
15+
16+
/** Lookup a stream registration. */
17+
extern int git_stream_registry_lookup(git_stream_registration *out, int tls);
18+
19+
#endif

src/streams/socket.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "posix.h"
1111
#include "netops.h"
12+
#include "registry.h"
1213
#include "stream.h"
1314

1415
#ifndef _WIN32
@@ -180,11 +181,14 @@ void socket_free(git_stream *stream)
180181
git__free(st);
181182
}
182183

183-
int git_socket_stream_new(git_stream **out, const char *host, const char *port)
184+
static int default_socket_stream_new(
185+
git_stream **out,
186+
const char *host,
187+
const char *port)
184188
{
185189
git_socket_stream *st;
186190

187-
assert(out && host);
191+
assert(out && host && port);
188192

189193
st = git__calloc(1, sizeof(git_socket_stream));
190194
GITERR_CHECK_ALLOC(st);
@@ -208,3 +212,29 @@ int git_socket_stream_new(git_stream **out, const char *host, const char *port)
208212
*out = (git_stream *) st;
209213
return 0;
210214
}
215+
216+
int git_socket_stream_new(
217+
git_stream **out,
218+
const char *host,
219+
const char *port)
220+
{
221+
int (*init)(git_stream **, const char *, const char *) = NULL;
222+
git_stream_registration custom = {0};
223+
int error;
224+
225+
assert(out && host && port);
226+
227+
if ((error = git_stream_registry_lookup(&custom, 0)) == 0)
228+
init = custom.init;
229+
else if (error == GIT_ENOTFOUND)
230+
init = default_socket_stream_new;
231+
else
232+
return error;
233+
234+
if (!init) {
235+
giterr_set(GITERR_NET, "there is no socket stream available");
236+
return -1;
237+
}
238+
239+
return init(out, host, port);
240+
}

src/streams/tls.c

Lines changed: 11 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,78 +9,32 @@
99

1010
#include "common.h"
1111
#include "global.h"
12+
#include "streams/registry.h"
1213
#include "streams/tls.h"
1314
#include "streams/mbedtls.h"
1415
#include "streams/openssl.h"
1516
#include "streams/stransport.h"
1617

17-
struct git_tls_stream_registration {
18-
git_rwlock lock;
19-
git_stream_registration callbacks;
20-
};
21-
22-
static struct git_tls_stream_registration stream_registration;
23-
24-
static void shutdown_ssl(void)
25-
{
26-
git_rwlock_free(&stream_registration.lock);
27-
}
28-
29-
int git_tls_stream_global_init(void)
30-
{
31-
if (git_rwlock_init(&stream_registration.lock) < 0)
32-
return -1;
33-
34-
git__on_shutdown(shutdown_ssl);
35-
return 0;
36-
}
37-
38-
int git_stream_register_tls(git_stream_registration *registration)
39-
{
40-
assert(!registration || registration->init);
41-
42-
if (git_rwlock_wrlock(&stream_registration.lock) < 0) {
43-
giterr_set(GITERR_OS, "failed to lock stream registration");
44-
return -1;
45-
}
46-
47-
if (registration)
48-
memcpy(&stream_registration.callbacks, registration,
49-
sizeof(git_stream_registration));
50-
else
51-
memset(&stream_registration.callbacks, 0,
52-
sizeof(git_stream_registration));
53-
54-
git_rwlock_wrunlock(&stream_registration.lock);
55-
return 0;
56-
}
57-
5818
int git_tls_stream_new(git_stream **out, const char *host, const char *port)
5919
{
6020
int (*init)(git_stream **, const char *, const char *) = NULL;
21+
git_stream_registration custom = {0};
22+
int error;
6123

6224
assert(out && host && port);
6325

64-
if (git_rwlock_rdlock(&stream_registration.lock) < 0) {
65-
giterr_set(GITERR_OS, "failed to lock stream registration");
66-
return -1;
67-
}
68-
69-
if (stream_registration.callbacks.init) {
70-
init = stream_registration.callbacks.init;
71-
} else {
26+
if ((error = git_stream_registry_lookup(&custom, 1)) == 0) {
27+
init = custom.init;
28+
} else if (error == GIT_ENOTFOUND) {
7229
#ifdef GIT_SECURE_TRANSPORT
7330
init = git_stransport_stream_new;
7431
#elif defined(GIT_OPENSSL)
7532
init = git_openssl_stream_new;
7633
#elif defined(GIT_MBEDTLS)
7734
init = git_mbedtls_stream_new;
7835
#endif
79-
}
80-
81-
if (git_rwlock_rdunlock(&stream_registration.lock) < 0) {
82-
giterr_set(GITERR_OS, "failed to unlock stream registration");
83-
return -1;
36+
} else {
37+
return error;
8438
}
8539

8640
if (!init) {
@@ -94,16 +48,12 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port)
9448
int git_tls_stream_wrap(git_stream **out, git_stream *in, const char *host)
9549
{
9650
int (*wrap)(git_stream **, git_stream *, const char *) = NULL;
51+
git_stream_registration custom = {0};
9752

9853
assert(out && in);
9954

100-
if (git_rwlock_rdlock(&stream_registration.lock) < 0) {
101-
giterr_set(GITERR_OS, "failed to lock stream registration");
102-
return -1;
103-
}
104-
105-
if (stream_registration.callbacks.wrap) {
106-
wrap = stream_registration.callbacks.wrap;
55+
if (git_stream_registry_lookup(&custom, 1) == 0) {
56+
wrap = custom.wrap;
10757
} else {
10858
#ifdef GIT_SECURE_TRANSPORT
10959
wrap = git_stransport_stream_wrap;
@@ -114,11 +64,6 @@ int git_tls_stream_wrap(git_stream **out, git_stream *in, const char *host)
11464
#endif
11565
}
11666

117-
if (git_rwlock_rdunlock(&stream_registration.lock) < 0) {
118-
giterr_set(GITERR_OS, "failed to unlock stream registration");
119-
return -1;
120-
}
121-
12267
if (!wrap) {
12368
giterr_set(GITERR_SSL, "there is no TLS stream available");
12469
return -1;

src/streams/tls.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@
1111

1212
#include "git2/sys/stream.h"
1313

14-
/** Configure TLS stream functions. */
15-
int git_tls_stream_global_init(void);
16-
1714
/**
1815
* Create a TLS stream with the most appropriate backend available for
1916
* the current platform, whether that's SecureTransport on macOS,

0 commit comments

Comments
 (0)