summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-06-07 14:42:13 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2015-06-24 17:26:36 +0200
commit1376e784c63bc63492a9ba04d5e1f07654deba60 (patch)
treed0ceb3e6a60f4c47fe6bab32a373e9b5b813fc87
parentede517bc5322022850854f22906be934736b4f57 (diff)
downloadlibgit2-1376e784c63bc63492a9ba04d5e1f07654deba60.tar.gz
stream: add support for setting a proxy
If the stream claims to support this feature, we can let the transport set the proxy. We also set HTTPPROXYTUNNEL option so curl can create a tunnel through the proxy which lets us create our own TLS session (if needed).
-rw-r--r--include/git2/sys/stream.h2
-rw-r--r--src/curl_stream.c15
-rw-r--r--src/stream.h15
3 files changed, 32 insertions, 0 deletions
diff --git a/include/git2/sys/stream.h b/include/git2/sys/stream.h
index c22179fab..55a714bbb 100644
--- a/include/git2/sys/stream.h
+++ b/include/git2/sys/stream.h
@@ -29,8 +29,10 @@ typedef struct git_stream {
int version;
int encrypted;
+ int proxy_support;
int (*connect)(struct git_stream *);
int (*certificate)(git_cert **, struct git_stream *);
+ int (*set_proxy)(struct git_stream *, const char *proxy_url);
ssize_t (*read)(struct git_stream *, void *, size_t);
ssize_t (*write)(struct git_stream *, const char *, size_t, int);
int (*close)(struct git_stream *);
diff --git a/src/curl_stream.c b/src/curl_stream.c
index fb7a61341..51b7fa7a4 100644
--- a/src/curl_stream.c
+++ b/src/curl_stream.c
@@ -64,6 +64,17 @@ static int curls_certificate(git_cert **out, git_stream *stream)
return 0;
}
+static int curls_set_proxy(git_stream *stream, const char *proxy_url)
+{
+ CURLcode res;
+ curl_stream *s = (curl_stream *) stream;
+
+ if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXY, proxy_url)) != CURLE_OK)
+ return seterr_curl(s);
+
+ return 0;
+}
+
static int wait_for(curl_socket_t fd, bool reading)
{
int ret;
@@ -185,12 +196,16 @@ int git_curl_stream_new(git_stream **out, const char *host, const char *port, in
curl_easy_setopt(handle, CURLOPT_CONNECT_ONLY, 1);
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 1);
curl_easy_setopt(handle, CURLOPT_CERTINFO, 1);
+ curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1);
+
/* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); */
st->parent.version = GIT_STREAM_VERSION;
st->parent.encrypted = encrypted;
+ st->parent.proxy_support = 1;
st->parent.connect = curls_connect;
st->parent.certificate = curls_certificate;
+ st->parent.set_proxy = curls_set_proxy;
st->parent.read = curls_read;
st->parent.write = curls_write;
st->parent.close = curls_close;
diff --git a/src/stream.h b/src/stream.h
index d810e704d..43fcc3045 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -30,6 +30,21 @@ GIT_INLINE(int) git_stream_certificate(git_cert **out, git_stream *st)
return st->certificate(out, st);
}
+GIT_INLINE(int) git_stream_supports_proxy(git_stream *st)
+{
+ return st->proxy_support;
+}
+
+GIT_INLINE(int) git_stream_set_proxy(git_stream *st, const char *proxy_url)
+{
+ if (!st->proxy_support) {
+ giterr_set(GITERR_INVALID, "proxy not supported on this stream");
+ return -1;
+ }
+
+ return st->set_proxy(st, proxy_url);
+}
+
GIT_INLINE(ssize_t) git_stream_read(git_stream *st, void *data, size_t len)
{
return st->read(st, data, len);