IMAP in multi mode: use Curl_ssl_connect_nonblocking() when upgrading the connection...
authorBen Noordhuis <info@bnoordhuis.nl>
Tue, 15 Feb 2011 23:56:46 +0000 (00:56 +0100)
committerBen Noordhuis <info@bnoordhuis.nl>
Sun, 20 Feb 2011 20:11:12 +0000 (21:11 +0100)
lib/imap.c
lib/imap.h

index 4e71fb3..16410c7 100644 (file)
@@ -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);
 
index ab4cf2f..c139516 100644 (file)
@@ -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,