From 45ca048f44f3c34441af225d9eae7605513db2c1 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 14 Feb 2011 19:41:42 +0100 Subject: [PATCH 1/2] IMAP in multi mode: use Curl_ssl_connect_nonblocking() when connecting. --- lib/imap.c | 11 +++++++++-- lib/imap.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/imap.c b/lib/imap.c index 5e294158b..4e71fb3ed 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -588,7 +588,14 @@ static CURLcode imap_multi_statemach(struct connectdata *conn, bool *done) { struct imap_conn *imapc = &conn->proto.imapc; - CURLcode result = Curl_pp_multi_statemach(&imapc->pp); + CURLcode result; + + if((conn->protocol & PROT_IMAPS) && !imapc->ssldone) { + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + } + else { + result = Curl_pp_multi_statemach(&imapc->pp); + } *done = (bool)(imapc->state == IMAP_STOP); @@ -700,7 +707,7 @@ static CURLcode imap_connect(struct connectdata *conn, } #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_PROXY */ - if(conn->protocol & PROT_IMAPS) { + if((conn->protocol & PROT_IMAPS) && data->state.used_interface != Curl_if_multi) { /* BLOCKING */ /* IMAPS is simply imap with SSL for the control channel */ /* now, perform the SSL initialization for this socket */ diff --git a/lib/imap.h b/lib/imap.h index 2f0b62a61..ab4cf2f09 100644 --- a/lib/imap.h +++ b/lib/imap.h @@ -47,6 +47,7 @@ struct imap_conn { imapstate state; /* always use imap.c:state() to change state! */ int cmdid; /* id number/index */ const char *idstr; /* pointer to a string for which to wait for as id */ + bool ssldone; /* is connect() over SSL done? only relevant in multi mode */ }; extern const struct Curl_handler Curl_handler_imap; From dd3760f2eb11745ea73d20bf7affe735f671fda5 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 16 Feb 2011 00:56:46 +0100 Subject: [PATCH 2/2] IMAP in multi mode: use Curl_ssl_connect_nonblocking() when upgrading the connection to TLS/SSL. --- lib/imap.c | 36 +++++++++++++++++++++++++++++++----- lib/imap.h | 1 + 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/lib/imap.c b/lib/imap.c index 4e71fb3ed..16410c7d5 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -108,6 +108,7 @@ static int imap_getsock(struct connectdata *conn, static CURLcode imap_doing(struct connectdata *conn, bool *dophase_done); static CURLcode imap_setup_connection(struct connectdata * conn); +static CURLcode imap_state_upgrade_tls(struct connectdata *conn); /* * IMAP protocol handler. @@ -342,17 +343,38 @@ static CURLcode imap_state_starttls_resp(struct connectdata *conn, result = CURLE_LOGIN_DENIED; } else { - /* Curl_ssl_connect is BLOCKING */ - result = Curl_ssl_connect(conn, FIRSTSOCKET); - if(CURLE_OK == result) { - conn->protocol |= PROT_IMAPS; - result = imap_state_login(conn); + if(data->state.used_interface == Curl_if_multi) { + state(conn, IMAP_UPGRADETLS); + return imap_state_upgrade_tls(conn); + } + else { + result = Curl_ssl_connect(conn, FIRSTSOCKET); + if(CURLE_OK == result) { + conn->protocol |= PROT_IMAPS; + result = imap_state_login(conn); + } } } state(conn, IMAP_STOP); return result; } +static CURLcode imap_state_upgrade_tls(struct connectdata *conn) +{ + struct imap_conn *imapc = &conn->proto.imapc; + CURLcode result; + + result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &imapc->ssldone); + + if(imapc->ssldone) { + conn->protocol |= PROT_IMAPS; + result = imap_state_login(conn); + state(conn, IMAP_STOP); + } + + return result; +} + /* for LOGIN responses */ static CURLcode imap_state_login_resp(struct connectdata *conn, int imapcode, @@ -524,6 +546,10 @@ static CURLcode imap_statemach_act(struct connectdata *conn) struct pingpong *pp = &imapc->pp; size_t nread = 0; + /* busy upgrading the connection; right now all I/O is SSL/TLS, not IMAP */ + if(imapc->state == IMAP_UPGRADETLS) + return imap_state_upgrade_tls(conn); + if(pp->sendleft) return Curl_pp_flushsend(pp); diff --git a/lib/imap.h b/lib/imap.h index ab4cf2f09..c1395160a 100644 --- a/lib/imap.h +++ b/lib/imap.h @@ -33,6 +33,7 @@ typedef enum { a connect */ IMAP_LOGIN, IMAP_STARTTLS, + IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS (multi mode only) */ IMAP_SELECT, IMAP_FETCH, IMAP_LOGOUT,