Starting from libcurl 7.21.5, libcurl can be tricked into using an already open socket. This allows to use tunneling with libcurl instead of the legacy imap code. Signed-off-by: Nicolas Morey-Chaisemartin <nicolas@xxxxxxxxxxxxxxxxxxxxxx> --- Documentation/git-imap-send.txt | 4 ++-- imap-send.c | 45 +++++++++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt index 5d1e4c80c..e765c08d7 100644 --- a/Documentation/git-imap-send.txt +++ b/Documentation/git-imap-send.txt @@ -38,8 +38,8 @@ OPTIONS Be quiet. --curl:: - Use libcurl to communicate with the IMAP server, unless tunneling - into it. Ignored if Git was built without the USE_CURL_FOR_IMAP_SEND + Use libcurl to communicate with the IMAP server. + Ignored if Git was built without the USE_CURL_FOR_IMAP_SEND option set. --no-curl:: diff --git a/imap-send.c b/imap-send.c index e5ff70096..31b93d873 100644 --- a/imap-send.c +++ b/imap-send.c @@ -1408,6 +1408,26 @@ static int append_msgs_to_imap(struct imap_server_conf *server, } #ifdef USE_CURL_FOR_IMAP_SEND +static curl_socket_t curl_tunnel_socket(void *clientp, + curlsocktype purpose, + struct curl_sockaddr *address) +{ + return (unsigned long)clientp; +} + +static int sockopt_callback(void *clientp, curl_socket_t curlfd, + curlsocktype purpose) +{ + /* CURL_SOCKOPT_ALREADY_CONNECTED was intreocued in 7.21.5 + * and is needed to get curl working on an existing fd */ +#if LIBCURL_VERSION_NUM >= 0x071505 + return CURL_SOCKOPT_ALREADY_CONNECTED; +#else + return CURL_SOCKOPT_ERROR; +#endif +} + + static CURL *setup_curl(struct imap_server_conf *srvc) { CURL *curl; @@ -1424,8 +1444,21 @@ static CURL *setup_curl(struct imap_server_conf *srvc) curl_easy_setopt(curl, CURLOPT_USERNAME, server.user); curl_easy_setopt(curl, CURLOPT_PASSWORD, server.pass); - strbuf_addstr(&path, server.use_ssl ? "imaps://" : "imap://"); - strbuf_addstr(&path, server.host); + if (srvc->tunnel) { + int fds[2]; + + setup_tunnel(srvc, fds); + curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, curl_tunnel_socket); + curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, (unsigned long)fds[0]); + curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); + /* Create a fake hostname to avoid resolution issue and in case + * imap.host was not set */ + strbuf_addstr(&path, "imap://localhost"); + } else { + strbuf_addstr(&path, server.use_ssl ? "imaps://" : "imap://"); + strbuf_addstr(&path, server.host); + } + if (!path.len || path.buf[path.len - 1] != '/') strbuf_addch(&path, '/'); strbuf_addstr(&path, server.folder); @@ -1570,12 +1603,12 @@ int cmd_main(int argc, const char **argv) /* write it to the imap server */ - if (server.tunnel) - return append_msgs_to_imap(&server, &all_msgs, total); - #ifdef USE_CURL_FOR_IMAP_SEND if (use_curl) - return curl_append_msgs_to_imap(&server, &all_msgs, total); +#if LIBCURL_VERSION_NUM < 0x071505 + if (!server.tunnel) +#endif + return curl_append_msgs_to_imap(&server, &all_msgs, total); #endif return append_msgs_to_imap(&server, &all_msgs, total); -- 2.14.0.3.gb4ff627ec.dirty