Commit c4312741 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

always-multi: always use non-blocking internals

Remove internal separated behavior of the easy vs multi intercace.
curl_easy_perform() is now using the multi interface itself.

Several minor multi interface quirks and bugs have been fixed in the
process.

Much help with debugging this has been provided by: Yang Tse
parent 9fd88abb
Loading
Loading
Loading
Loading
+2 −12
Original line number Diff line number Diff line
@@ -21,8 +21,7 @@

 2. libcurl - multi interface
 2.1 More non-blocking
 2.2 Remove easy interface internally
 2.4 Fix HTTP Pipelining for PUT
 2.2 Fix HTTP Pipelining for PUT

 3. Documentation
 3.1  More and better
@@ -191,16 +190,7 @@
 - The "DONE" operation (post transfer protocol-specific actions) for the
   protocols SFTP, SMTP, FTP. Fixing Curl_done() for this is a worthy task.

2.2 Remove easy interface internally

 Make curl_easy_perform() a wrapper-function that simply creates a multi
 handle, adds the easy handle to it, runs curl_multi_perform() until the
 transfer is done, then detach the easy handle, destroy the multi handle and
 return the easy handle's return code. This will thus make everything
 internally use and assume the multi interface. The select()-loop should use
 curl_multi_socket().

2.4 Fix HTTP Pipelining for PUT
2.2 Fix HTTP Pipelining for PUT

 HTTP Pipelining can be a way to greatly enhance performance for multiple
 serial requests and currently libcurl only supports that for HEAD and GET
+1 −1
Original line number Diff line number Diff line
@@ -43,4 +43,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
  gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h curl_ntlm.h	\
  curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h curl_ntlm_msgs.h	\
  curl_sasl.h curl_schannel.h curl_multibyte.h curl_darwinssl.h	\
  hostcheck.h bundles.h conncache.h curl_setup_once.h
  hostcheck.h bundles.h conncache.h curl_setup_once.h multihandle.h
+2 −5
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
 * Copyright (C) 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 2012 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -47,7 +47,7 @@ static void free_bundle_hash_entry(void *freethis)
  Curl_bundle_destroy(b);
}

struct conncache *Curl_conncache_init(conncachetype type)
struct conncache *Curl_conncache_init(void)
{
  struct conncache *connc;

@@ -63,9 +63,6 @@ struct conncache *Curl_conncache_init(conncachetype type)
    return NULL;
  }

  connc->type = type;
  connc->num_connections = 0;

  return connc;
}

+2 −8
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 2012, Linus Nielsen Feltzing, <linus@haxx.se>
 * Copyright (C) 2012, 2013, Linus Nielsen Feltzing, <linus@haxx.se>
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -22,18 +22,12 @@
 *
 ***************************************************************************/

typedef enum {
  CONNCACHE_PRIVATE, /* used for an easy handle alone */
  CONNCACHE_MULTI    /* shared within a multi handle */
} conncachetype;

struct conncache {
  struct curl_hash *hash;
  conncachetype type;
  size_t num_connections;
};

struct conncache *Curl_conncache_init(conncachetype type);
struct conncache *Curl_conncache_init(void);

void Curl_conncache_destroy(struct conncache *connc);

+35 −7
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
 * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
@@ -74,6 +74,8 @@
#include "sslgen.h" /* for Curl_ssl_check_cxn() */
#include "progress.h"
#include "warnless.h"
#include "conncache.h"
#include "multihandle.h"

/* The last #include file should be: */
#include "memdebug.h"
@@ -980,8 +982,7 @@ singleipconnect(struct connectdata *conn,

  /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
     connect(). We can be sure of this since connect() cannot return 1. */
  if((WAITCONN_TIMEOUT == rc) &&
     (data->state.used_interface == Curl_if_multi)) {
  if(WAITCONN_TIMEOUT == rc) {
    /* Timeout when running the multi interface */
    *sockp = sockfd;
    return CURLE_OK;
@@ -1072,9 +1073,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */

    /* start connecting to the IP curr_addr points to */
    res = singleipconnect(conn, curr_addr,
                          /* don't hang when doing multi */
                          (data->state.used_interface == Curl_if_multi)?0:
                          conn->timeoutms_per_addr, &sockfd, connected);
                          0, /* don't hang when doing multi */
                          &sockfd, connected);
    if(res)
      return res;

@@ -1112,6 +1112,21 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
  return CURLE_OK;
}

struct connfind {
  struct connectdata *tofind;
  bool found;
};

static int conn_is_conn(struct connectdata *conn, void *param)
{
  struct connfind *f = (struct connfind *)param;
  if(conn == f->tofind) {
    f->found = TRUE;
    return 1;
  }
  return 0;
}

/*
 * Used to extract socket and connectdata struct for the most recent
 * transfer on the given SessionHandle.
@@ -1125,8 +1140,21 @@ curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,

  DEBUGASSERT(data);

  if(data->state.lastconnect) {
  /* this only works for an easy handle that has been used for
     curl_easy_perform()! */
  if(data->state.lastconnect && data->multi_easy) {
    struct connectdata *c = data->state.lastconnect;
    struct connfind find;
    find.tofind = data->state.lastconnect;
    find.found = FALSE;

    Curl_conncache_foreach(data->multi_easy->conn_cache, &find, conn_is_conn);

    if(!find.found) {
      data->state.lastconnect = NULL;
      return CURL_SOCKET_BAD;
    }

    if(connp)
      /* only store this if the caller cares for it */
      *connp = c;
Loading