1
0
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:
Daniel Stenberg 2006-04-10 15:00:53 +00:00
parent 5dc02d53c3
commit 686d90745b
21 changed files with 1609 additions and 545 deletions

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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 */

View File

@ -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;

View File

@ -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;
}
/*

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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
View 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
View 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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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 */