Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
TLMSP curl
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
CYBER - Cyber Security
TS 103 523 MSP
TLMSP
TLMSP curl
Commits
0ec96e42
Commit
0ec96e42
authored
18 years ago
by
Daniel Stenberg
Browse files
Options
Downloads
Patches
Plain Diff
each socket is used by exactly one easy handle, but of course each easy handle
can and will use more than one socket
parent
6e520c4c
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
lib/README.multi_socket
+6
-9
6 additions, 9 deletions
lib/README.multi_socket
lib/multi.c
+35
-82
35 additions, 82 deletions
lib/multi.c
with
41 additions
and
91 deletions
lib/README.multi_socket
+
6
−
9
View file @
0ec96e42
...
...
@@ -43,15 +43,12 @@ Implementation of the curl_multi_socket API
handle conversion on its own. I find it very unlikely that applications
would want to do that and since libcurl would need such a lookup on its own
anyway since we didn't want to force applications to do that translation
code (it would be optional), it seemed like an unnecessary option. I also
realized that when we use underlying libraries such as c-ares (for DNS
asynch resolving) there might in fact be more than one transfer waiting for
action on the same socket and thus it makes the lookup even tricker and even
less likely to ever get done by applications. Instead I created an internal
"socket to easy handles" hash table that given a socket (file descriptor)
returns a list of easy handles that waits for some action on that socket.
This hash is made using the already existing hash code (previously only used
for the DNS cache).
code (it would be optional), it seemed like an unnecessary option.
Instead I created an internal "socket to easy handles" hash table that given
a socket (file descriptor) return the easy handle that waits for action on
that socket. This hash is made using the already existing hash code
(previously only used for the DNS cache).
To make libcurl be able to report plain sockets in the socket callback, I
had to re-organize the internals of the curl_multi_fdset() etc so that the
...
...
This diff is collapsed.
Click to expand it.
lib/multi.c
+
35
−
82
View file @
0ec96e42
...
...
@@ -83,7 +83,6 @@ typedef enum {
struct
socketstate
{
curl_socket_t
socks
[
MAX_SOCKSPEREASYHANDLE
];
long
action
;
/* socket action bitmap */
long
timeout
[
MAX_SOCKSPEREASYHANDLE
];
};
struct
Curl_one_easy
{
...
...
@@ -173,19 +172,20 @@ static void multistate(struct Curl_one_easy *easy, CURLMstate state)
}
/*
* We add one of these structs to the sockhash, and then if we add more easy
* handles for the same socket we just link them with the next/prev pointers
* from the node added to the hash. We only remove the node from the hash when
* the final easy handle/socket associated with the node is removed.
* We add one of these structs to the sockhash for a particular socket
*/
struct
Curl_sh_entry
{
struct
Curl_sh_entry
*
next
;
struct
Curl_sh_entry
*
prev
;
struct
SessionHandle
*
easy
;
time_t
timestamp
;
long
inuse
;
int
action
;
/* what action READ/WRITE this socket waits for */
void
*
userp
;
/* settable by users (not yet decided exactly how) */
};
/* bits for 'action' having no bits means this socket is not expecting any
action */
#define SH_READ 1
#define SG_WRITE 2
/* make sure this socket is present in the hash for this handle */
static
int
sh_addentry
(
struct
curl_hash
*
sh
,
...
...
@@ -196,16 +196,9 @@ static int sh_addentry(struct curl_hash *sh,
Curl_hash_pick
(
sh
,
(
char
*
)
&
s
,
sizeof
(
curl_socket_t
));
struct
Curl_sh_entry
*
check
;
if
(
there
)
{
/* verify that this particular handle is in here */
check
=
there
;
while
(
check
)
{
if
(
check
->
easy
==
data
)
/* it is, return fine */
return
0
;
check
=
check
->
next
;
}
}
if
(
there
)
/* it is present, return fine */
return
0
;
/* not present, add it */
check
=
calloc
(
sizeof
(
struct
Curl_sh_entry
),
1
);
...
...
@@ -213,57 +206,25 @@ static int sh_addentry(struct curl_hash *sh,
return
1
;
/* major failure */
check
->
easy
=
data
;
if
(
there
)
{
/* the node for this socket is already here, now link in the struct for
the new handle */
check
->
next
=
there
->
next
;
/* get the previous next to point to */
there
->
next
=
check
;
/* make the new next point to the new entry */
/* make/add new hash entry */
if
(
NULL
==
Curl_hash_add
(
sh
,
(
char
*
)
&
s
,
sizeof
(
curl_socket_t
),
check
))
return
1
;
/* major failure */
check
->
next
->
prev
=
check
;
/* make sure the next one points back to the
new one */
/* check->prev = NULL; is already cleared and we have no previous
node */
}
else
{
/* make/add new hash entry */
if
(
NULL
==
Curl_hash_add
(
sh
,
(
char
*
)
&
s
,
sizeof
(
curl_socket_t
),
check
))
return
1
;
/* major failure */
}
return
0
;
/* things are good in sockhash land */
}
/* delete the given socket + handle from the hash */
static
void
sh_delentry
(
struct
curl_hash
*
sh
,
curl_socket_t
s
,
struct
SessionHandle
*
data
)
static
void
sh_delentry
(
struct
curl_hash
*
sh
,
curl_socket_t
s
)
{
struct
Curl_sh_entry
*
there
=
Curl_hash_pick
(
sh
,
(
char
*
)
&
s
,
sizeof
(
curl_socket_t
));
while
(
there
)
{
/* this socket is in the hash, now scan the list at this point and see if
the given easy handle is in there and if so remote that singe entry */
if
(
there
->
easy
==
data
)
{
/* match! */
if
(
there
->
next
||
there
->
prev
)
{
/* it is not the only handle for this socket, so only unlink this
particular easy handle and leave the actional hash entry */
/* unlink */
there
->
next
->
prev
=
there
->
prev
;
there
->
prev
->
next
=
there
->
next
;
free
(
there
);
}
else
{
/* This is the only easy handle for this socket, we must remove the
hash entry. (This'll end up in a call to sh_freeentry().) */
Curl_hash_delete
(
sh
,
(
char
*
)
&
s
,
sizeof
(
curl_socket_t
));
}
break
;
}
there
=
there
->
next
;
if
(
there
)
{
/* this socket is in the hash */
/* We remove the hash entry. (This'll end up in a call to
sh_freeentry().) */
Curl_hash_delete
(
sh
,
(
char
*
)
&
s
,
sizeof
(
curl_socket_t
));
}
}
...
...
@@ -273,14 +234,6 @@ static void sh_delentry(struct curl_hash *sh,
static
void
sh_freeentry
(
void
*
freethis
)
{
struct
Curl_sh_entry
*
p
=
(
struct
Curl_sh_entry
*
)
freethis
;
struct
Curl_sh_entry
*
more
=
p
->
next
;
/* if there's a chain of more handles, remove that chain first */
while
(
more
)
{
struct
Curl_sh_entry
*
next
=
more
->
next
;
free
(
more
);
more
=
next
;
}
free
(
p
);
}
...
...
@@ -1034,8 +987,9 @@ CURLMsg *curl_multi_info_read(CURLM *multi_handle, int *msgs_in_queue)
}
/*
* Check what sockets we deal with and their "action state" and if we have a
* difference from last time we call the callback accordingly.
* singlesocket() checks what sockets we deal with and their "action state"
* and if we have a different state in any of those sockets from last time we
* call the callback accordingly.
*/
static
void
singlesocket
(
struct
Curl_multi
*
multi
,
struct
Curl_one_easy
*
easy
)
...
...
@@ -1050,9 +1004,11 @@ static void singlesocket(struct Curl_multi *multi,
/* first fill in the 'current' struct with the state as it is now */
current
.
action
=
multi_getsock
(
easy
,
current
.
socks
,
MAX_SOCKSPEREASYHANDLE
);
/* when filled in, we compare with the previous round's state */
/* when filled in, we compare with the previous round's state in a first
quick memory compare check */
if
(
memcmp
(
&
current
,
&
easy
->
sockstate
,
sizeof
(
struct
socketstate
)))
{
/* difference, call the callback once for every socket change ! */
/* there is difference, call the callback once for every socket change ! */
for
(
i
=
0
;
i
<
MAX_SOCKSPEREASYHANDLE
;
i
++
)
{
int
action
;
curl_socket_t
s
=
current
.
socks
[
i
];
...
...
@@ -1103,7 +1059,7 @@ static void singlesocket(struct Curl_multi *multi,
/* Update the sockhash accordingly */
if
(
action
==
CURL_POLL_REMOVE
)
/* remove from hash for this easy handle */
sh_delentry
(
multi
->
sockhash
,
s
,
easy
->
easy_handle
);
sh_delentry
(
multi
->
sockhash
,
s
);
else
/* make sure this socket is present in the hash for this handle */
sh_addentry
(
multi
->
sockhash
,
s
,
easy
->
easy_handle
);
...
...
@@ -1138,6 +1094,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
easyp
=
easyp
->
next
;
}
/* or should we fall-through and do the timer-based stuff? */
return
result
;
}
else
if
(
s
!=
CURL_SOCKET_TIMEOUT
)
{
...
...
@@ -1152,20 +1109,16 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
/* Now, there is potentially a chain of easy handles in this hash
entry struct and we need to deal with all of them */
do
{
data
=
entry
->
easy
;
result
=
multi_runsingle
(
multi
,
data
->
set
.
one_easy
,
&
running_handles
);
if
(
result
==
CURLM_OK
)
/* get the socket(s) and check if the state has been changed since
last */
singlesocket
(
multi
,
data
->
set
.
one_easy
);
data
=
entry
->
easy
;
entry
=
entry
->
next
;
result
=
multi_runsingle
(
multi
,
data
->
set
.
one_easy
,
&
running_handles
)
;
}
while
(
entry
);
if
(
result
==
CURLM_OK
)
/* get the socket(s) and check if the state has been changed since
last */
singlesocket
(
multi
,
data
->
set
.
one_easy
);
/* or should we fall-through and do the timer-based stuff? */
return
result
;
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment