Commit 8ec4dba5 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

removed handles and states from the main structs

renamed prefixes from curl_ to Curl_
made persistant connections work with http proxies (at least partly)
parent 1efec657
Loading
Loading
Loading
Loading
+111 −159
Original line number Diff line number Diff line
@@ -122,18 +122,7 @@ static unsigned int ConnectionStore(struct UrlData *data,
                                    struct connectdata *conn);


/* does nothing, returns OK */
CURLcode curl_init(void)
{
  return CURLE_OK;
}

/* does nothing */
void curl_free(void)
{
}

CURLcode curl_close(CURL *curl)
CURLcode Curl_close(CURL *curl)
{
  struct UrlData *data=(struct UrlData *)curl;
  
@@ -178,10 +167,6 @@ CURLcode curl_close(CURL *curl)
  free(data->connects);

  free(data);

  /* global cleanup */
  curl_free();

  return CURLE_OK;
}

@@ -197,7 +182,7 @@ int my_getpass(void *clientp, char *prompt, char* buffer, int buflen )
}


CURLcode curl_open(CURL **curl, char *url)
CURLcode Curl_open(CURL **curl, char *url)
{
  /* We don't yet support specifying the URL at this point */
  struct UrlData *data;
@@ -206,8 +191,6 @@ CURLcode curl_open(CURL **curl, char *url)
  data = (struct UrlData *)malloc(sizeof(struct UrlData));
  if(data) {
    memset(data, 0, sizeof(struct UrlData));
    data->handle = STRUCT_OPEN;
    data->interf = CURLI_NORMAL; /* normal interface by default */

    /* We do some initial setup here, all those fields that can't be just 0 */

@@ -258,7 +241,7 @@ CURLcode curl_open(CURL **curl, char *url)
  return CURLE_OUT_OF_MEMORY;
}

CURLcode curl_setopt(CURL *curl, CURLoption option, ...)
CURLcode Curl_setopt(CURL *curl, CURLoption option, ...)
{
  struct UrlData *data = curl;
  va_list param;
@@ -510,10 +493,8 @@ RETSIGTYPE alarmfunc(int signal)
}
#endif

CURLcode curl_disconnect(CURLconnect *c_connect)
CURLcode Curl_disconnect(struct connectdata *conn)
{
  struct connectdata *conn = c_connect;

  if(conn->curl_disconnect)
    /* This is set if protocol-specific cleanups should be made */
    conn->curl_disconnect(conn);
@@ -570,6 +551,9 @@ CURLcode curl_disconnect(CURLconnect *c_connect)
  if(conn->allocptr.host)
    free(conn->allocptr.host);

  if(conn->proxyhost)
    free(conn->proxyhost);

  free(conn); /* free all the connection oriented data */

  return CURLE_OK;
@@ -623,9 +607,13 @@ ConnectionExists(struct UrlData *data,
    if(!check)
      /* NULL pointer means not filled-in entry */
      continue;
    if(!needle->bits.httpproxy) {
      /* The requested connection does not use a HTTP proxy */

      if(strequal(needle->protostr, check->protostr) &&
         strequal(needle->name, check->name) &&
         (needle->port == check->port) ) {
        bool dead;
        if(strequal(needle->protostr, "FTP")) {
          /* This is FTP, verify that we're using the same name and
             password as well */
@@ -635,12 +623,10 @@ ConnectionExists(struct UrlData *data,
            continue;
          }
        }
      {
        bool dead;
        dead = SocketIsDead(check->firstsocket);
        if(dead) {
          infof(data, "Connection %d seems to be dead!\n", i);
          curl_disconnect(check); /* disconnect resources */
          Curl_disconnect(check); /* disconnect resources */
          data->connects[i]=NULL; /* nothing here */
          continue; /* try another one now */
        }
@@ -648,6 +634,16 @@ ConnectionExists(struct UrlData *data,
      *usethis = check;
      return TRUE; /* yes, we found one to use! */
    }
    else { /* The requested needle connection is using a proxy,
              is the checked one using the same? */
      if(check->bits.httpproxy &&
         strequal(needle->proxyhost, check->proxyhost) &&
         needle->port == check->port) {
        /* This is the same proxy connection, use it! */
        *usethis = check;
        return TRUE;
      }
    }
  }
  return FALSE; /* no matching connecting exists */
}
@@ -690,7 +686,7 @@ ConnectionKillOne(struct UrlData *data)
  if(connindex >= 0) {

    /* the winner gets the honour of being disconnected */
    result = curl_disconnect(data->connects[connindex]);
    result = Curl_disconnect(data->connects[connindex]);

    /* clean the array entry */
    data->connects[connindex] = NULL;
@@ -811,7 +807,7 @@ static CURLcode ConnectPlease(struct UrlData *data,
	
          size = sizeof(add);
          if(getsockname(conn->firstsocket, (struct sockaddr *) &add,
                         (int *)&size)<0) {
                         (socklen_t *)&size)<0) {
            failf(data, "getsockname() failed");
            return CURLE_HTTP_PORT_FAILED;
          }
@@ -945,15 +941,14 @@ static CURLcode ConnectPlease(struct UrlData *data,
  return CURLE_OK;
}

static CURLcode _connect(CURL *curl,
                         CURLconnect **in_connect,
static CURLcode Connect(struct UrlData *data,
                        struct connectdata **in_connect,
                        bool allow_port) /* allow data->use_port ? */
{
  char *tmp;
  char *buf;
  CURLcode result;
  char resumerange[40]="";
  struct UrlData *data = curl;
  struct connectdata *conn;
  struct connectdata *conn_temp;
  char endbracket;
@@ -966,9 +961,6 @@ static CURLcode _connect(CURL *curl,
   * Check input data
   *************************************************************/

  if(!data || (data->handle != STRUCT_OPEN))
    return CURLE_BAD_FUNCTION_ARGUMENT; /* TBD: make error codes */

  if(!data->url)
    return CURLE_URL_MALFORMAT;

@@ -991,13 +983,12 @@ static CURLcode _connect(CURL *curl,
  memset(conn, 0, sizeof(struct connectdata));

  /* and we setup a few fields in case we end up actually using this struct */
  conn->handle = STRUCT_CONNECT; /* this is a connection handle */
  conn->data = data;           /* remember our daddy */
  conn->state = CONN_INIT;     /* init state */
  conn->upload_bufsize = UPLOAD_BUFSIZE; /* default upload buffer size */
  conn->firstsocket = -1;     /* no file descriptor */
  conn->secondarysocket = -1; /* no file descriptor */
  conn->connectindex = -1;    /* no index */
  conn->bits.httpproxy = data->bits.httpproxy; /* proxy-or-not status */

  /* Default protocol-indepent behaveiour doesn't support persistant
     connections, so we set this to force-close. Protocols that support
@@ -1567,6 +1558,62 @@ static CURLcode _connect(CURL *curl,
    conn->remote_port = atoi(tmp);
  }

  if(data->bits.httpproxy) {
    /* If this is supposed to use a proxy, we need to figure out the proxy
       host name name, so that we can re-use an existing connection
       that may exist registered to the same proxy host. */

#ifdef ENABLE_IPV6
    failf(data, "proxy yet to be supported");
    return CURLE_OUT_OF_MEMORY;
#else
    char *prox_portno;
    char *endofprot;

    /* We need to make a duplicate of the proxy so that we can modify the
       string safely. */
    char *proxydup=strdup(data->proxy);

    /* We use 'proxyptr' to point to the proxy name from now on... */
    char *proxyptr=proxydup;

    if(NULL == proxydup) {
      failf(data, "memory shortage");
      return CURLE_OUT_OF_MEMORY;
    }

    /* Daniel Dec 10, 1998:
       We do the proxy host string parsing here. We want the host name and the
       port name. Accept a protocol:// prefix, even though it should just be
       ignored. */

    /* 1. skip the protocol part if present */
    endofprot=strstr(proxyptr, "://");
    if(endofprot) {
      proxyptr = endofprot+3;
    }

    /* allow user to specify proxy.server.com:1080 if desired */
    prox_portno = strchr (proxyptr, ':');
    if (prox_portno) {
      *prox_portno = 0x0; /* cut off number from host name */
      prox_portno ++;
      /* now set the local port number */
      conn->port = atoi(prox_portno);
    }
    else if(data->proxyport) {
      /* None given in the proxy string, then get the default one if it is
         given */
      conn->port = data->proxyport;
    }

    /* now, clone the cleaned proxy host name */
    conn->proxyhost = strdup(proxyptr);

    free(proxydup); /* free the duplicate pointer and not the modified */
#endif /* end of IPv4-section */
  }

  /*************************************************************
   * Check the current list of connections to see if we can
   * re-use an already existing one or if we have to create a
@@ -1581,6 +1628,8 @@ static CURLcode _connect(CURL *curl,
     * existing one.
     */
    char *path = conn->path; /* setup the current path pointer properly */
    if(conn->proxyhost)
      free(conn->proxyhost);
    free(conn);              /* we don't need this new one */
    conn = conn_temp;        /* use this connection from now on */
    free(conn->path);        /* free the previous path pointer */
@@ -1591,6 +1640,8 @@ static CURLcode _connect(CURL *curl,
    conn->maxdownload = 0;   /* might have been used previously! */
    conn->bits.reuse = TRUE; /* yes, we're re-using here */

    *in_connect = conn;      /* return this instead! */

    infof(data, "Re-using existing connection! (#%d)\n", conn->connectindex);
  }
  else {
@@ -1628,59 +1679,13 @@ static CURLcode _connect(CURL *curl,
  else if(!conn->hp) {
    /* This is a proxy that hasn't been resolved yet. It may be resolved
       if we're reusing an existing connection. */
#ifdef ENABLE_IPV6
    failf(data, "proxy yet to be supported");
    return CURLE_OUT_OF_MEMORY;
#else
    char *prox_portno;
    char *endofprot;

    /* We need to make a duplicate of the proxy so that we can modify the
       string safely. */
    char *proxydup=strdup(data->proxy);

    /* We use 'proxyptr' to point to the proxy name from now on... */
    char *proxyptr=proxydup;

    if(NULL == proxydup) {
      failf(data, "memory shortage");
      return CURLE_OUT_OF_MEMORY;
    }

    /* Daniel Dec 10, 1998:
       We do the proxy host string parsing here. We want the host name and the
       port name. Accept a protocol:// prefix, even though it should just be
       ignored. */

    /* 1. skip the protocol part if present */
    endofprot=strstr(proxyptr, "://");
    if(endofprot) {
      proxyptr = endofprot+3;
    }

    /* allow user to specify proxy.server.com:1080 if desired */
    prox_portno = strchr (proxyptr, ':');
    if (prox_portno) {
      *prox_portno = 0x0; /* cut off number from host name */
      prox_portno ++;
      /* now set the local port number */
      conn->port = atoi(prox_portno);
    }
    else if(data->proxyport) {
      /* None given in the proxy string, then get the default one if it is
         given */
      conn->port = data->proxyport;
    }

    /* resolve proxy */
    conn->hp = Curl_gethost(data, proxyptr, &conn->hostent_buf);
    conn->hp = Curl_gethost(data, conn->proxyhost, &conn->hostent_buf);
    if(!conn->hp) {
      failf(data, "Couldn't resolve proxy '%s'", proxyptr);
      failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
      return CURLE_COULDNT_RESOLVE_PROXY;
    }

    free(proxydup); /* free the duplicate pointer and not the modified */
#endif
  }
  Curl_pgrsTime(data, TIMER_NAMELOOKUP);

@@ -1784,25 +1789,24 @@ static CURLcode _connect(CURL *curl,
  return CURLE_OK;
}

CURLcode curl_connect(CURL *curl, CURLconnect **in_connect,
CURLcode Curl_connect(struct UrlData *data,
                      struct connectdata **in_connect,
                      bool allow_port)
{
  CURLcode code;
  struct connectdata *conn;

  /* call the stuff that needs to be called */
  code = _connect(curl, in_connect, allow_port);
  code = Connect(data, in_connect, allow_port);

  if(CURLE_OK != code) {
    /* We're not allowed to return failure with memory left allocated
       in the connectdata struct, free those here */
    conn = (struct connectdata *)*in_connect;
    if(conn) {
      struct UrlData *data;
      int index;
      data = conn->data;
      index = conn->connectindex; /* get the index */
      curl_disconnect(conn);      /* close the connection */
      Curl_disconnect(conn);      /* close the connection */
      data->connects[index]=NULL; /* clear the pointer */
    }
  }
@@ -1810,41 +1814,12 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect,
}


/*
 * NAME curl_connect()
 *
 * DESCRIPTION
 *
 * Connects to the peer server and performs the initial setup. This function
 * writes a connect handle to its second argument that is a unique handle for
 * this connect. This allows multiple connects from the same handle returned
 * by curl_open().
 *
 * EXAMPLE
 *
 * CURLCode result;
 * CURL curl;
 * CURLconnect connect;
 * result = curl_connect(curl, &connect);
 */




CURLcode curl_done(CURLconnect *c_connect)
CURLcode Curl_done(struct connectdata *conn)
{
  struct connectdata *conn = c_connect;
  struct UrlData *data;
  CURLcode result;
  int index;

  if(!conn || (conn->handle!= STRUCT_CONNECT)) {
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }
  if(conn->state != CONN_DO) {
    /* This can only be called after a curl_do() */
    return CURLE_BAD_CALLING_ORDER;
  }
  data = conn->data;

  /* this calls the protocol-specific function pointer previously set */
@@ -1855,48 +1830,25 @@ CURLcode curl_done(CURLconnect *c_connect)

  Curl_pgrsDone(data); /* done with the operation */

  conn->state = CONN_DONE;

  /* if bits.close is TRUE, it means that the connection should be closed
     in spite of all our efforts to be nice */
  if((CURLE_OK == result) && conn->bits.close) {
    index = conn->connectindex;     /* get the index */
    result = curl_disconnect(conn); /* close the connection */
    result = Curl_disconnect(conn); /* close the connection */
    data->connects[index]=NULL;     /* clear the pointer */
  }

  return result;
}

CURLcode curl_do(CURLconnect *in_conn)
CURLcode Curl_do(struct connectdata *conn)
{
  struct connectdata *conn = in_conn;
  CURLcode result;
  CURLcode result=CURLE_OK;

  if(!conn || (conn->handle!= STRUCT_CONNECT)) {
    return CURLE_BAD_FUNCTION_ARGUMENT;
  }
  switch(conn->state) {
  case CONN_INIT:
  case CONN_DONE:
    /* these two states are OK */
    break;
  default:
    /* anything else is bad */
    return CURLE_BAD_CALLING_ORDER;
  }

  if(conn->curl_do) {
  if(conn->curl_do)
    /* generic protocol-specific function pointer set in curl_connect() */
    result = conn->curl_do(conn);
    if(result) {
      conn->state = CONN_ERROR;
      return result;
    }
  }

  conn->state = CONN_DO; /* we have entered this state */

  return CURLE_OK;
  return result;
}