mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
First curl_multi_socket() commit. Should primarily be considered as an internal
code rearrange to fit the future better.
This commit is contained in:
parent
5dc02d53c3
commit
686d90745b
@ -8,7 +8,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
||||
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
||||
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
||||
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
|
||||
select.c gtls.c sslgen.c tftp.c
|
||||
select.c gtls.c sslgen.c tftp.c splay.c
|
||||
|
||||
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
||||
@ -18,6 +18,6 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
|
||||
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
|
||||
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
|
||||
gtls.h tftp.h sockaddr.h
|
||||
gtls.h tftp.h sockaddr.h splay.h
|
||||
|
||||
|
||||
|
@ -98,6 +98,7 @@
|
||||
#include "memory.h"
|
||||
#include "select.h"
|
||||
#include "url.h" /* for Curl_safefree() */
|
||||
#include "multiif.h"
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
|
||||
/* The last #include file should be: */
|
||||
@ -534,6 +535,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
CURLcode code = CURLE_OK;
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
long allow = DEFAULT_CONNECT_TIMEOUT;
|
||||
long allow_total = 0;
|
||||
long has_passed;
|
||||
|
||||
curlassert(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
|
||||
@ -546,12 +548,12 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
/* subtract the most strict timeout of the ones */
|
||||
if(data->set.timeout && data->set.connecttimeout) {
|
||||
if (data->set.timeout < data->set.connecttimeout)
|
||||
allow = data->set.timeout*1000;
|
||||
allow_total = allow = data->set.timeout*1000;
|
||||
else
|
||||
allow = data->set.connecttimeout*1000;
|
||||
}
|
||||
else if(data->set.timeout) {
|
||||
allow = data->set.timeout*1000;
|
||||
allow_total = allow = data->set.timeout*1000;
|
||||
}
|
||||
else if(data->set.connecttimeout) {
|
||||
allow = data->set.connecttimeout*1000;
|
||||
@ -564,10 +566,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
||||
}
|
||||
if(conn->bits.tcpconnect) {
|
||||
/* we are connected already! */
|
||||
Curl_expire(data, allow_total);
|
||||
*connected = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
Curl_expire(data, allow);
|
||||
|
||||
/* check for connect without timeout as we want to return immediately */
|
||||
rc = waitconnect(sockfd, 0);
|
||||
|
||||
@ -818,6 +823,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||
return CURLE_OPERATION_TIMEOUTED;
|
||||
}
|
||||
}
|
||||
Curl_expire(data, timeout_ms);
|
||||
|
||||
/* Max time for each address */
|
||||
num_addr = Curl_num_addresses(remotehost->addr);
|
||||
|
26
lib/ftp.c
26
lib/ftp.c
@ -96,6 +96,7 @@
|
||||
#include "select.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "multiif.h"
|
||||
|
||||
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
|
||||
#include "inet_ntoa_r.h"
|
||||
@ -718,27 +719,24 @@ static CURLcode ftp_state_pwd(struct connectdata *conn)
|
||||
}
|
||||
|
||||
/* For the FTP "protocol connect" and "doing" phases only */
|
||||
CURLcode Curl_ftp_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_ftp_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
struct FTP *ftp = conn->proto.ftp;
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(ftp->sendleft) {
|
||||
/* write mode */
|
||||
FD_SET(sockfd, write_fd_set);
|
||||
}
|
||||
else {
|
||||
/* read mode */
|
||||
FD_SET(sockfd, read_fd_set);
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
|
||||
if((int)sockfd > *max_fdp)
|
||||
*max_fdp = (int)sockfd;
|
||||
|
||||
return CURLE_OK;
|
||||
/* read mode */
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
|
||||
/* This is called after the FTP_QUOTE state is passed.
|
||||
|
@ -34,10 +34,9 @@ CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn,
|
||||
int *ftpcode);
|
||||
CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
|
||||
CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_ftp_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
int Curl_ftp_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
CURLcode Curl_ftp_doing(struct connectdata *conn,
|
||||
bool *dophase_done);
|
||||
#endif /* CURL_DISABLE_FTP */
|
||||
|
26
lib/hash.c
26
lib/hash.c
@ -124,8 +124,11 @@ mk_hash_element(char *key, size_t key_len, const void *p)
|
||||
(struct curl_hash_element *) malloc(sizeof(struct curl_hash_element));
|
||||
|
||||
if(he) {
|
||||
char *dup = strdup(key);
|
||||
char *dup = malloc(key_len);
|
||||
if(dup) {
|
||||
/* copy the key */
|
||||
memcpy(dup, key, key_len);
|
||||
|
||||
he->key = dup;
|
||||
he->key_len = key_len;
|
||||
he->ptr = (void *) p;
|
||||
@ -179,6 +182,23 @@ Curl_hash_add(struct curl_hash *h, char *key, size_t key_len, void *p)
|
||||
return NULL; /* failure */
|
||||
}
|
||||
|
||||
/* remove the identified hash entry, returns non-zero on failure */
|
||||
int Curl_hash_delete(struct curl_hash *h, char *key, size_t key_len)
|
||||
{
|
||||
struct curl_llist_element *le;
|
||||
struct curl_hash_element *he;
|
||||
struct curl_llist *l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for (le = l->head; le; le = le->next) {
|
||||
he = le->ptr;
|
||||
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
|
||||
Curl_llist_remove(l, le, (void *) h);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void *
|
||||
Curl_hash_pick(struct curl_hash *h, char *key, size_t key_len)
|
||||
{
|
||||
@ -186,9 +206,7 @@ Curl_hash_pick(struct curl_hash *h, char *key, size_t key_len)
|
||||
struct curl_hash_element *he;
|
||||
struct curl_llist *l = FETCH_LIST(h, key, key_len);
|
||||
|
||||
for (le = l->head;
|
||||
le;
|
||||
le = le->next) {
|
||||
for (le = l->head; le; le = le->next) {
|
||||
he = le->ptr;
|
||||
if (hash_key_compare(he->key, he->key_len, key, key_len)) {
|
||||
return he->ptr;
|
||||
|
@ -105,17 +105,15 @@
|
||||
* Returns: CURLE_OK always!
|
||||
*/
|
||||
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
|
||||
{
|
||||
int max = ares_fds(conn->data->state.areschannel,
|
||||
read_fd_set, write_fd_set);
|
||||
*max_fdp = max;
|
||||
int max = ares_getsock(conn->data->state.areschannel,
|
||||
(int *)socks, numsocks);
|
||||
|
||||
return CURLE_OK;
|
||||
return max;
|
||||
}
|
||||
|
||||
/*
|
||||
|
13
lib/hostip.h
13
lib/hostip.h
@ -160,6 +160,14 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||
struct Curl_dns_entry **dnsentry);
|
||||
|
||||
|
||||
/* Curl_resolv_getsock() is a generic function that exists in multiple versions
|
||||
depending on what name resolve technology we've built to use. The function
|
||||
is called from the multi_getsock() function */
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock,
|
||||
int numsocks);
|
||||
#if 0
|
||||
/* Curl_resolv_fdset() is a generic function that exists in multiple versions
|
||||
depending on what name resolve technology we've built to use. The function
|
||||
is called from the curl_multi_fdset() function */
|
||||
@ -167,8 +175,11 @@ CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
#endif
|
||||
|
||||
/* unlock a previously resolved dns entry */
|
||||
void Curl_resolv_unlock(struct SessionHandle *data, struct Curl_dns_entry *dns);
|
||||
void Curl_resolv_unlock(struct SessionHandle *data,
|
||||
struct Curl_dns_entry *dns);
|
||||
|
||||
/* for debugging purposes only: */
|
||||
void Curl_scan_cache_used(void *user, void *ptr);
|
||||
|
@ -126,17 +126,15 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||
* It is present here to keep #ifdefs out from multi.c
|
||||
*/
|
||||
|
||||
CURLcode Curl_resolv_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_resolv_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock,
|
||||
int numsocks)
|
||||
{
|
||||
(void)conn;
|
||||
(void)read_fd_set;
|
||||
(void)write_fd_set;
|
||||
(void)max_fdp;
|
||||
(void)sock;
|
||||
(void)numsocks;
|
||||
|
||||
return CURLE_OK;
|
||||
return 0; /* no bits since we don't use any socks */
|
||||
}
|
||||
|
||||
#endif /* truly sync */
|
||||
|
22
lib/http.c
22
lib/http.c
@ -97,6 +97,7 @@
|
||||
#include "select.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
#include "strtoofft.h"
|
||||
#include "multiif.h"
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
#include <curl/mprintf.h>
|
||||
@ -1416,26 +1417,25 @@ CURLcode Curl_https_connecting(struct connectdata *conn, bool *done)
|
||||
}
|
||||
|
||||
#ifdef USE_SSLEAY
|
||||
CURLcode Curl_https_proto_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
if (conn->protocol & PROT_HTTPS) {
|
||||
struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
|
||||
curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(!numsocks)
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
if (connssl->connecting_state == ssl_connect_2_writing) {
|
||||
/* write mode */
|
||||
FD_SET(sockfd, write_fd_set);
|
||||
if((int)sockfd > *max_fdp)
|
||||
*max_fdp = (int)sockfd;
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
else if (connssl->connecting_state == ssl_connect_2_reading) {
|
||||
/* read mode */
|
||||
FD_SET(sockfd, read_fd_set);
|
||||
if((int)sockfd > *max_fdp)
|
||||
*max_fdp = (int)sockfd;
|
||||
socks[0] = conn->sock[FIRSTSOCKET];
|
||||
return GETSOCK_READSOCK(0);
|
||||
}
|
||||
}
|
||||
return CURLE_OK;
|
||||
|
@ -8,7 +8,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2006, 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
|
||||
@ -38,10 +38,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_http_done(struct connectdata *, CURLcode);
|
||||
CURLcode Curl_http_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_https_connecting(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_https_proto_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
int Curl_https_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
|
||||
/* The following functions are defined in http_chunks.c */
|
||||
void Curl_httpchunk_init(struct connectdata *conn);
|
||||
|
1397
lib/multi.c
1397
lib/multi.c
File diff suppressed because it is too large
Load Diff
@ -26,5 +26,19 @@
|
||||
/*
|
||||
* Prototypes for library-wide functions provided by multi.c
|
||||
*/
|
||||
void Curl_expire(struct SessionHandle *data, long milli);
|
||||
|
||||
void Curl_multi_rmeasy(void *multi, CURL *data);
|
||||
|
||||
/* the write bits start at bit 16 for the *getsock() bitmap */
|
||||
#define GETSOCK_WRITEBITSTART 16
|
||||
|
||||
#define GETSOCK_BLANK 0 /* no bits set */
|
||||
|
||||
/* set the bit for the given sock number to make the bitmap for writable */
|
||||
#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x)))
|
||||
|
||||
/* set the bit for the given sock number to make the bitmap for readable */
|
||||
#define GETSOCK_READSOCK(x) (1 << (x))
|
||||
|
||||
#endif /* __MULTIIF_H */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <curl/curl.h>
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "multiif.h"
|
||||
#include "speedcheck.h"
|
||||
|
||||
void Curl_speedinit(struct SessionHandle *data)
|
||||
@ -43,13 +44,13 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
|
||||
data->set.low_speed_time &&
|
||||
(Curl_tvlong(data->state.keeps_speed) != 0) &&
|
||||
(data->progress.current_speed < data->set.low_speed_limit)) {
|
||||
long howlong = Curl_tvdiff(now, data->state.keeps_speed);
|
||||
|
||||
/* We are now below the "low speed limit". If we are below it
|
||||
for "low speed time" seconds we consider that enough reason
|
||||
to abort the download. */
|
||||
|
||||
if( (Curl_tvdiff(now, data->state.keeps_speed)/1000) >
|
||||
data->set.low_speed_time) {
|
||||
if( (howlong/1000) > data->set.low_speed_time) {
|
||||
/* we have been this slow for long enough, now die */
|
||||
failf(data,
|
||||
"Operation too slow. "
|
||||
@ -58,6 +59,7 @@ CURLcode Curl_speedcheck(struct SessionHandle *data,
|
||||
data->set.low_speed_time);
|
||||
return CURLE_OPERATION_TIMEOUTED;
|
||||
}
|
||||
Curl_expire(data, howlong);
|
||||
}
|
||||
else {
|
||||
/* we keep up the required speed all right */
|
||||
|
406
lib/splay.c
Normal file
406
lib/splay.c
Normal file
@ -0,0 +1,406 @@
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1997 - 2006, 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
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "splay.h"
|
||||
|
||||
#define compare(i,j) ((i)-(j))
|
||||
|
||||
/* Set this to a key value that will *NEVER* appear otherwise */
|
||||
#define KEY_NOTUSED -1
|
||||
|
||||
/*
|
||||
* Splay using the key i (which may or may not be in the tree.) The starting
|
||||
* root is t.
|
||||
*/
|
||||
struct Curl_tree *Curl_splay(int i, struct Curl_tree *t)
|
||||
{
|
||||
struct Curl_tree N, *l, *r, *y;
|
||||
int comp;
|
||||
|
||||
if (t == NULL)
|
||||
return t;
|
||||
N.smaller = N.larger = NULL;
|
||||
l = r = &N;
|
||||
|
||||
for (;;) {
|
||||
comp = compare(i, t->key);
|
||||
if (comp < 0) {
|
||||
if (t->smaller == NULL)
|
||||
break;
|
||||
if (compare(i, t->smaller->key) < 0) {
|
||||
y = t->smaller; /* rotate smaller */
|
||||
t->smaller = y->larger;
|
||||
y->larger = t;
|
||||
t = y;
|
||||
if (t->smaller == NULL)
|
||||
break;
|
||||
}
|
||||
r->smaller = t; /* link smaller */
|
||||
r = t;
|
||||
t = t->smaller;
|
||||
}
|
||||
else if (comp > 0) {
|
||||
if (t->larger == NULL)
|
||||
break;
|
||||
if (compare(i, t->larger->key) > 0) {
|
||||
y = t->larger; /* rotate larger */
|
||||
t->larger = y->smaller;
|
||||
y->smaller = t;
|
||||
t = y;
|
||||
if (t->larger == NULL)
|
||||
break;
|
||||
}
|
||||
l->larger = t; /* link larger */
|
||||
l = t;
|
||||
t = t->larger;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
l->larger = r->smaller = NULL;
|
||||
|
||||
l->larger = t->smaller; /* assemble */
|
||||
r->smaller = t->larger;
|
||||
t->smaller = N.larger;
|
||||
t->larger = N.smaller;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Insert key i into the tree t. Return a pointer to the resulting tree or
|
||||
NULL if something went wrong. */
|
||||
struct Curl_tree *Curl_splayinsert(int i, struct Curl_tree *t,
|
||||
struct Curl_tree *area)
|
||||
{
|
||||
if (area == NULL)
|
||||
return t;
|
||||
|
||||
if (t != NULL) {
|
||||
t = Curl_splay(i,t);
|
||||
if (compare(i, t->key)==0) {
|
||||
/* it already exists one of this size */
|
||||
|
||||
area->same = t;
|
||||
area->key = i;
|
||||
area->smaller = t->smaller;
|
||||
area->larger = t->larger;
|
||||
|
||||
t->smaller = area;
|
||||
t->key = KEY_NOTUSED;
|
||||
|
||||
return area; /* new root node */
|
||||
}
|
||||
}
|
||||
|
||||
if (t == NULL) {
|
||||
area->smaller = area->larger = NULL;
|
||||
}
|
||||
else if (compare(i, t->key) < 0) {
|
||||
area->smaller = t->smaller;
|
||||
area->larger = t;
|
||||
t->smaller = NULL;
|
||||
|
||||
}
|
||||
else {
|
||||
area->larger = t->larger;
|
||||
area->smaller = t;
|
||||
t->larger = NULL;
|
||||
}
|
||||
area->key = i;
|
||||
|
||||
area->same = NULL; /* no identical node (yet) */
|
||||
return area;
|
||||
}
|
||||
|
||||
/* Deletes 'i' from the tree if it's there (with an exact match). Returns a
|
||||
pointer to the resulting tree. */
|
||||
struct Curl_tree *Curl_splayremove(int i, struct Curl_tree *t,
|
||||
struct Curl_tree **removed)
|
||||
{
|
||||
struct Curl_tree *x;
|
||||
|
||||
if (t==NULL)
|
||||
return NULL;
|
||||
|
||||
t = Curl_splay(i,t);
|
||||
if (compare(i, t->key) == 0) { /* found it */
|
||||
|
||||
/* FIRST! Check if there is a list with identical sizes */
|
||||
if((x = t->same)) {
|
||||
/* there is, pick one from the list */
|
||||
|
||||
/* 'x' is the new root node */
|
||||
|
||||
x->key = t->key;
|
||||
x->larger = t->larger;
|
||||
x->smaller = t->smaller;
|
||||
|
||||
*removed = t;
|
||||
return x; /* new root */
|
||||
}
|
||||
|
||||
if (t->smaller == NULL) {
|
||||
x = t->larger;
|
||||
}
|
||||
else {
|
||||
x = Curl_splay(i, t->smaller);
|
||||
x->larger = t->larger;
|
||||
}
|
||||
*removed = t;
|
||||
|
||||
return x;
|
||||
}
|
||||
else {
|
||||
*removed = NULL; /* no match */
|
||||
return t; /* It wasn't there */
|
||||
}
|
||||
}
|
||||
|
||||
/* Finds and deletes the best-fit node from the tree. Return a pointer to the
|
||||
resulting tree. best-fit means the node with the given or lower number */
|
||||
struct Curl_tree *Curl_splaygetbest(int i, struct Curl_tree *t,
|
||||
struct Curl_tree **removed)
|
||||
{
|
||||
struct Curl_tree *x;
|
||||
|
||||
if (!t) {
|
||||
*removed = NULL; /* none removed since there was no root */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t = Curl_splay(i,t);
|
||||
if(compare(i, t->key) < 0) {
|
||||
/* too big node, try the smaller chain */
|
||||
if(t->smaller)
|
||||
t=Curl_splay(t->smaller->key, t);
|
||||
else {
|
||||
/* fail */
|
||||
*removed = NULL;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
if (compare(i, t->key) >= 0) { /* found it */
|
||||
/* FIRST! Check if there is a list with identical sizes */
|
||||
x = t->same;
|
||||
if(x) {
|
||||
/* there is, pick one from the list */
|
||||
|
||||
/* 'x' is the new root node */
|
||||
|
||||
x->key = t->key;
|
||||
x->larger = t->larger;
|
||||
x->smaller = t->smaller;
|
||||
|
||||
*removed = t;
|
||||
return x; /* new root */
|
||||
}
|
||||
|
||||
if (t->smaller == NULL) {
|
||||
x = t->larger;
|
||||
}
|
||||
else {
|
||||
x = Curl_splay(i, t->smaller);
|
||||
x->larger = t->larger;
|
||||
}
|
||||
*removed = t;
|
||||
|
||||
return x;
|
||||
}
|
||||
else {
|
||||
*removed = NULL; /* no match */
|
||||
return t; /* It wasn't there */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Deletes the node we point out from the tree if it's there. Return a pointer
|
||||
to the resulting tree. */
|
||||
struct Curl_tree *Curl_splayremovebyaddr(struct Curl_tree *t,
|
||||
struct Curl_tree *remove)
|
||||
{
|
||||
struct Curl_tree *x;
|
||||
|
||||
if (!t || !remove)
|
||||
return NULL;
|
||||
|
||||
if(KEY_NOTUSED == remove->key) {
|
||||
/* just unlink ourselves nice and quickly: */
|
||||
remove->smaller->same = remove->same;
|
||||
if(remove->same)
|
||||
remove->same->smaller = remove->smaller;
|
||||
/* voila, we're done! */
|
||||
return t;
|
||||
}
|
||||
|
||||
t = Curl_splay(remove->key, t);
|
||||
|
||||
/* Check if there is a list with identical sizes */
|
||||
|
||||
x = t->same;
|
||||
if(x) {
|
||||
/* 'x' is the new root node */
|
||||
|
||||
x->key = t->key;
|
||||
x->larger = t->larger;
|
||||
x->smaller = t->smaller;
|
||||
|
||||
return x; /* new root */
|
||||
}
|
||||
|
||||
/* Remove the actualy root node: */
|
||||
if (t->smaller == NULL)
|
||||
x = t->larger;
|
||||
else {
|
||||
x = Curl_splay(remove->key, t->smaller);
|
||||
x->larger = t->larger;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
|
||||
int Curl_splayprint(struct Curl_tree * t, int d, char output)
|
||||
{
|
||||
int distance=0;
|
||||
struct Curl_tree *node;
|
||||
int i;
|
||||
if (t == NULL)
|
||||
return 0;
|
||||
distance += Curl_splayprint(t->larger, d+1, output);
|
||||
for (i=0; i<d; i++)
|
||||
if(output)
|
||||
printf(" ");
|
||||
|
||||
if(output) {
|
||||
printf("%d[%d]", t->key, i);
|
||||
}
|
||||
|
||||
for(node = t->same; node; node = node->same) {
|
||||
distance += i; /* this has the same "virtual" distance */
|
||||
|
||||
if(output)
|
||||
printf(" [+]");
|
||||
}
|
||||
if(output)
|
||||
puts("");
|
||||
|
||||
distance += i;
|
||||
|
||||
distance += Curl_splayprint(t->smaller, d+1, output);
|
||||
|
||||
return distance;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TEST_SPLAY
|
||||
|
||||
/*#define TEST2 */
|
||||
#define MAX 50
|
||||
#define OUTPUT 0 /* 1 enables, 0 disables */
|
||||
|
||||
/* A sample use of these functions. Start with the empty tree, insert some
|
||||
stuff into it, and then delete it */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct Curl_tree *root, *t;
|
||||
void *ptrs[MAX];
|
||||
|
||||
long sizes[]={
|
||||
50, 60, 50, 100, 60, 200, 120, 300, 400, 200, 256, 122, 60, 120, 200, 300,
|
||||
220, 80, 90, 50, 100, 60, 200, 120, 300, 400, 200, 256, 122, 60, 120, 200,
|
||||
300, 220, 80, 90, 50, 100, 60, 200, 120, 300, 400, 200, 256, 122, 60, 120,
|
||||
200, 300, 220, 80, 90};
|
||||
int i;
|
||||
root = NULL; /* the empty tree */
|
||||
|
||||
for (i = 0; i < MAX; i++) {
|
||||
ptrs[i] = t = (struct Curl_tree *)malloc(sizeof(struct Curl_tree));
|
||||
if(!t) {
|
||||
puts("out of memory!");
|
||||
return 0;
|
||||
}
|
||||
#ifdef TEST2
|
||||
root = Curl_splayinsert(sizes[i], root, t);
|
||||
#else
|
||||
root = Curl_splayinsert((541*i)&1023, root, t);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
puts("Result:");
|
||||
printtree(root, 0, 1);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
for (i=0; root; i+=30) {
|
||||
Curl_splayprint(root, 0, 1);
|
||||
do {
|
||||
root = Curl_splaygetbest(i, root, &t);
|
||||
if(t)
|
||||
printf("bestfit %d became %d\n", i, t->key);
|
||||
else
|
||||
printf("bestfit %d failed!\n", i);
|
||||
} while(t && root);
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
for (i = 0; i < MAX; i++) {
|
||||
printf("remove pointer %d size %d\n", i, sizes[i]);
|
||||
root = removebyaddr(root, (struct Curl_tree *)ptrs[i]);
|
||||
Curl_splayprint(root, 0, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifdef WEIGHT
|
||||
for (i = -1; i<=root->weight; i++) {
|
||||
t = find_rank(i, root);
|
||||
if (t == NULL) {
|
||||
printf("could not find a node of rank %d.\n", i);
|
||||
} else {
|
||||
printf("%d is of rank %d\n", t->key, i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifdef TEST2
|
||||
for (i = 0; i < MAX; i++) {
|
||||
printf("remove size %d\n", sizes[i]);
|
||||
root = Curl_splayremove(sizes[i], root, &t);
|
||||
free(t);
|
||||
Curl_splayprint(root, 0, 1);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TEST_SPLAY */
|
50
lib/splay.h
Normal file
50
lib/splay.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef __SPLAY_H
|
||||
#define __SPLAY_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1997 - 2006, 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
|
||||
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* $Id$
|
||||
***************************************************************************/
|
||||
|
||||
struct Curl_tree {
|
||||
struct Curl_tree *smaller; /* smaller node */
|
||||
struct Curl_tree *larger; /* larger node */
|
||||
struct Curl_tree *same; /* points to a node with identical key */
|
||||
int key; /* the "sort" key */
|
||||
void *payload; /* data the splay code doesn't care about */
|
||||
};
|
||||
|
||||
struct Curl_tree *Curl_splay(int i, struct Curl_tree *t);
|
||||
struct Curl_tree *Curl_splayinsert(int key, struct Curl_tree *t,
|
||||
struct Curl_tree *new);
|
||||
struct Curl_tree *Curl_splayremove(int key, struct Curl_tree *t,
|
||||
struct Curl_tree **removed);
|
||||
struct Curl_tree *Curl_splaygetbest(int key, struct Curl_tree *t,
|
||||
struct Curl_tree **removed);
|
||||
struct Curl_tree *Curl_splayremovebyaddr(struct Curl_tree *t,
|
||||
struct Curl_tree *remove);
|
||||
|
||||
#ifdef CURLDEBUG
|
||||
int Curl_splayprint(struct Curl_tree * t, int d, char output);
|
||||
#else
|
||||
#define Curl_splayprint(x,y,z)
|
||||
#endif
|
||||
|
||||
#endif
|
@ -329,6 +329,12 @@ curl_multi_strerror(CURLMcode error)
|
||||
case CURLM_INTERNAL_ERROR:
|
||||
return "internal error";
|
||||
|
||||
case CURLM_BAD_SOCKET:
|
||||
return "invalid socket argument";
|
||||
|
||||
case CURLM_UNKNOWN_OPTION:
|
||||
return "unknown option";
|
||||
|
||||
case CURLM_LAST:
|
||||
break;
|
||||
}
|
||||
|
@ -101,6 +101,7 @@
|
||||
#include "share.h"
|
||||
#include "memory.h"
|
||||
#include "select.h"
|
||||
#include "multiif.h"
|
||||
#include "easyif.h" /* for Curl_convert_to_network prototype */
|
||||
|
||||
#define _MPRINTF_REPLACE /* use our functions only */
|
||||
@ -1522,34 +1523,42 @@ CURLcode Curl_readwrite_init(struct connectdata *conn)
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_single_fdset() gets called by the multi interface code when the app
|
||||
* has requested to get the fd_sets for the current connection. This function
|
||||
* Curl_single_getsock() gets called by the multi interface code when the app
|
||||
* has requested to get the sockets for the current connection. This function
|
||||
* will then be called once for every connection that the multi interface
|
||||
* keeps track of. This function will only be called for connections that are
|
||||
* in the proper state to have this information available.
|
||||
*/
|
||||
void Curl_single_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set,
|
||||
int *max_fd)
|
||||
int Curl_single_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock, /* points to numsocks number
|
||||
of sockets */
|
||||
int numsocks)
|
||||
{
|
||||
*max_fd = -1; /* init */
|
||||
int bitmap = GETSOCK_BLANK;
|
||||
int index = 0;
|
||||
|
||||
if(numsocks < 2)
|
||||
/* simple check but we might need two slots */
|
||||
return GETSOCK_BLANK;
|
||||
|
||||
if(conn->keep.keepon & KEEP_READ) {
|
||||
FD_SET(conn->sockfd, read_fd_set);
|
||||
*max_fd = (int)conn->sockfd;
|
||||
bitmap |= GETSOCK_READSOCK(index);
|
||||
sock[index] = conn->sockfd;
|
||||
}
|
||||
if(conn->keep.keepon & KEEP_WRITE) {
|
||||
FD_SET(conn->writesockfd, write_fd_set);
|
||||
|
||||
/* since sockets are curl_socket_t nowadays, we typecast it to int here
|
||||
to compare it nicely */
|
||||
if((int)conn->writesockfd > *max_fd)
|
||||
*max_fd = (int)conn->writesockfd;
|
||||
if((conn->sockfd != conn->writesockfd) &&
|
||||
(conn->keep.keepon & KEEP_READ)) {
|
||||
/* only if they are not the same socket and we had a readable one,
|
||||
we increase index */
|
||||
index++;
|
||||
sock[index] = conn->writesockfd;
|
||||
}
|
||||
|
||||
bitmap |= GETSOCK_WRITESOCK(index);
|
||||
}
|
||||
/* we don't use exceptions, only touch that one to prevent compiler
|
||||
warnings! */
|
||||
*exc_fd_set = *exc_fd_set;
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,11 +28,9 @@ CURLcode Curl_second_connect(struct connectdata *conn);
|
||||
CURLcode Curl_posttransfer(struct SessionHandle *data);
|
||||
CURLcode Curl_follow(struct SessionHandle *data, char *newurl, bool retry);
|
||||
CURLcode Curl_readwrite(struct connectdata *conn, bool *done);
|
||||
void Curl_single_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
fd_set *exc_fd_set,
|
||||
int *max_fd);
|
||||
int Curl_single_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
CURLcode Curl_readwrite_init(struct connectdata *conn);
|
||||
CURLcode Curl_readrewind(struct connectdata *conn);
|
||||
CURLcode Curl_fillreadbuffer(struct connectdata *conn, int bytes, int *nreadp);
|
||||
|
37
lib/url.c
37
lib/url.c
@ -1552,6 +1552,7 @@ CURLcode Curl_disconnect(struct connectdata *conn)
|
||||
NULL, Curl_scan_cache_used);
|
||||
#endif
|
||||
|
||||
Curl_expire(data, 0); /* shut off timers */
|
||||
Curl_hostcache_prune(data); /* kill old DNS cache entries */
|
||||
|
||||
/*
|
||||
@ -2318,26 +2319,22 @@ static void verboseconnect(struct connectdata *conn)
|
||||
conn->ip_addr_str, conn->port);
|
||||
}
|
||||
|
||||
CURLcode Curl_protocol_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_protocol_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
if(conn->curl_proto_fdset)
|
||||
res = conn->curl_proto_fdset(conn, read_fd_set, write_fd_set, max_fdp);
|
||||
return res;
|
||||
if(conn->curl_proto_getsock)
|
||||
return conn->curl_proto_getsock(conn, socks, numsocks);
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
|
||||
CURLcode Curl_doing_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp)
|
||||
int Curl_doing_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
if(conn && conn->curl_doing_fdset)
|
||||
res = conn->curl_doing_fdset(conn, read_fd_set, write_fd_set, max_fdp);
|
||||
return res;
|
||||
if(conn && conn->curl_doing_getsock)
|
||||
return conn->curl_doing_getsock(conn, socks, numsocks);
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3034,7 +3031,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
conn->curl_done = Curl_http_done;
|
||||
conn->curl_connect = Curl_http_connect;
|
||||
conn->curl_connecting = Curl_https_connecting;
|
||||
conn->curl_proto_fdset = Curl_https_proto_fdset;
|
||||
conn->curl_proto_getsock = Curl_https_getsock;
|
||||
|
||||
#else /* USE_SS */
|
||||
failf(data, LIBCURL_NAME
|
||||
@ -3086,8 +3083,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
||||
conn->curl_connect = Curl_ftp_connect;
|
||||
conn->curl_connecting = Curl_ftp_multi_statemach;
|
||||
conn->curl_doing = Curl_ftp_doing;
|
||||
conn->curl_proto_fdset = Curl_ftp_fdset;
|
||||
conn->curl_doing_fdset = Curl_ftp_fdset;
|
||||
conn->curl_proto_getsock = Curl_ftp_getsock;
|
||||
conn->curl_doing_getsock = Curl_ftp_getsock;
|
||||
conn->curl_disconnect = Curl_ftp_disconnect;
|
||||
}
|
||||
|
||||
@ -4027,6 +4024,8 @@ CURLcode Curl_done(struct connectdata **connp,
|
||||
struct connectdata *conn = *connp;
|
||||
struct SessionHandle *data=conn->data;
|
||||
|
||||
Curl_expire(data, 0); /* stop timer */
|
||||
|
||||
if(conn->bits.done)
|
||||
return CURLE_OK; /* Curl_done() has already been called */
|
||||
|
||||
|
12
lib/url.h
12
lib/url.h
@ -45,6 +45,16 @@ CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done);
|
||||
CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done);
|
||||
void Curl_safefree(void *ptr);
|
||||
|
||||
|
||||
int Curl_protocol_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
int Curl_doing_getsock(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
|
||||
#if 0
|
||||
CURLcode Curl_protocol_fdset(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
@ -54,3 +64,5 @@ CURLcode Curl_doing_fdset(struct connectdata *conn,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -96,6 +96,7 @@
|
||||
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||
#include "hostip.h"
|
||||
#include "hash.h"
|
||||
#include "splay.h"
|
||||
|
||||
#ifdef HAVE_GSSAPI
|
||||
# ifdef HAVE_GSSGNU
|
||||
@ -657,17 +658,15 @@ struct connectdata {
|
||||
|
||||
/* Called from the multi interface during the PROTOCONNECT phase, and it
|
||||
should then return a proper fd set */
|
||||
CURLcode (*curl_proto_fdset)(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
int (*curl_proto_getsock)(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
|
||||
/* Called from the multi interface during the DOING phase, and it should
|
||||
then return a proper fd set */
|
||||
CURLcode (*curl_doing_fdset)(struct connectdata *conn,
|
||||
fd_set *read_fd_set,
|
||||
fd_set *write_fd_set,
|
||||
int *max_fdp);
|
||||
int (*curl_doing_getsock)(struct connectdata *conn,
|
||||
curl_socket_t *socks,
|
||||
int numsocks);
|
||||
|
||||
/* This function *MAY* be set to a protocol-dependent function that is run
|
||||
* by the curl_disconnect(), as a step in the disconnection.
|
||||
@ -932,10 +931,11 @@ struct UrlState {
|
||||
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
|
||||
ENGINE *engine;
|
||||
#endif /* USE_SSLEAY */
|
||||
struct timeval expiretime; /* set this with Curl_expire() only */
|
||||
struct Curl_tree timenode; /* for the splay stuff */
|
||||
|
||||
/* a place to store the most recenlty set FTP entrypath */
|
||||
char *most_recent_ftp_entrypath;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -968,6 +968,8 @@ struct DynamicStatic {
|
||||
* 'struct UrlState' instead. The only exceptions MUST note the changes in
|
||||
* the 'DynamicStatic' struct.
|
||||
*/
|
||||
struct Curl_one_easy; /* declared and used only in multi.c */
|
||||
struct Curl_multi; /* declared and used only in multi.c */
|
||||
|
||||
struct UserDefined {
|
||||
FILE *err; /* the stderr user data goes here */
|
||||
@ -1071,6 +1073,12 @@ struct UserDefined {
|
||||
|
||||
char *private_data; /* Private data */
|
||||
|
||||
struct Curl_one_easy *one_easy; /* When adding an easy handle to a multi
|
||||
handle, an internal 'Curl_one_easy'
|
||||
struct is created and this is a pointer
|
||||
to the particular struct associated with
|
||||
this SessionHandle */
|
||||
|
||||
struct curl_slist *http200aliases; /* linked list of aliases for http200 */
|
||||
|
||||
long ip_version;
|
||||
@ -1139,7 +1147,7 @@ struct UserDefined {
|
||||
|
||||
struct SessionHandle {
|
||||
struct curl_hash *hostcache;
|
||||
void *multi; /* if non-NULL, points to the multi handle
|
||||
struct Curl_multi *multi; /* if non-NULL, points to the multi handle
|
||||
struct of which this "belongs" */
|
||||
struct Curl_share *share; /* Share, handles global variable mutexing */
|
||||
struct UserDefined set; /* values set by the libcurl user */
|
||||
|
Loading…
Reference in New Issue
Block a user