handler: refactor connection checking

Add a new type of callback to Curl_handler which performs checks on
the connection. Alter RTSP so that it uses this callback to do its
own check on connection health.
This commit is contained in:
Max Dymond 2017-05-31 12:09:56 +01:00 committed by Daniel Stenberg
parent 192877058e
commit c75f63d7c4
20 changed files with 78 additions and 7 deletions

View File

@ -74,6 +74,7 @@ const struct Curl_handler Curl_handler_rtmp = {
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_RTMP, /* defport */
CURLPROTO_RTMP, /* protocol */
PROTOPT_NONE /* flags*/
@ -94,6 +95,7 @@ const struct Curl_handler Curl_handler_rtmpt = {
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPT, /* protocol */
PROTOPT_NONE /* flags*/
@ -114,6 +116,7 @@ const struct Curl_handler Curl_handler_rtmpe = {
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_RTMP, /* defport */
CURLPROTO_RTMPE, /* protocol */
PROTOPT_NONE /* flags*/
@ -134,6 +137,7 @@ const struct Curl_handler Curl_handler_rtmpte = {
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_RTMPT, /* defport */
CURLPROTO_RTMPTE, /* protocol */
PROTOPT_NONE /* flags*/
@ -154,6 +158,7 @@ const struct Curl_handler Curl_handler_rtmps = {
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPS, /* protocol */
PROTOPT_NONE /* flags*/
@ -174,6 +179,7 @@ const struct Curl_handler Curl_handler_rtmpts = {
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_RTMPS, /* defport */
CURLPROTO_RTMPTS, /* protocol */
PROTOPT_NONE /* flags*/

View File

@ -85,6 +85,7 @@ const struct Curl_handler Curl_handler_dict = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_DICT, /* defport */
CURLPROTO_DICT, /* protocol */
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */

View File

@ -108,6 +108,7 @@ const struct Curl_handler Curl_handler_file = {
ZERO_NULL, /* perform_getsock */
file_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
0, /* defport */
CURLPROTO_FILE, /* protocol */
PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */

View File

@ -178,6 +178,7 @@ const struct Curl_handler Curl_handler_ftp = {
ZERO_NULL, /* perform_getsock */
ftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_FTP, /* defport */
CURLPROTO_FTP, /* protocol */
PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD |
@ -205,6 +206,7 @@ const struct Curl_handler Curl_handler_ftps = {
ZERO_NULL, /* perform_getsock */
ftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_FTPS, /* defport */
CURLPROTO_FTPS, /* protocol */
PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION |

View File

@ -65,6 +65,7 @@ const struct Curl_handler Curl_handler_gopher = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_GOPHER, /* defport */
CURLPROTO_GOPHER, /* protocol */
PROTOPT_NONE /* flags */

View File

@ -119,6 +119,7 @@ const struct Curl_handler Curl_handler_http = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
PROTOPT_CREDSPERREQUEST /* flags */
@ -143,6 +144,7 @@ const struct Curl_handler Curl_handler_https = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */

View File

@ -196,6 +196,7 @@ static const struct Curl_handler Curl_handler_http2 = {
http2_perform_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTP, /* protocol */
PROTOPT_STREAM /* flags */
@ -216,6 +217,7 @@ static const struct Curl_handler Curl_handler_http2_ssl = {
http2_perform_getsock, /* perform_getsock */
http2_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_HTTP, /* defport */
CURLPROTO_HTTPS, /* protocol */
PROTOPT_SSL | PROTOPT_STREAM /* flags */

View File

@ -128,6 +128,7 @@ const struct Curl_handler Curl_handler_imap = {
ZERO_NULL, /* perform_getsock */
imap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_IMAP, /* defport */
CURLPROTO_IMAP, /* protocol */
PROTOPT_CLOSEACTION| /* flags */
@ -154,6 +155,7 @@ const struct Curl_handler Curl_handler_imaps = {
ZERO_NULL, /* perform_getsock */
imap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_IMAPS, /* defport */
CURLPROTO_IMAPS, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_SSL /* flags */

View File

@ -150,6 +150,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
PROTOPT_NONE /* flags */
@ -175,6 +176,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_LDAPS, /* defport */
CURLPROTO_LDAPS, /* protocol */
PROTOPT_SSL /* flags */

View File

@ -85,6 +85,7 @@ const struct Curl_handler Curl_handler_ldap = {
ZERO_NULL, /* perform_getsock */
ldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_LDAP, /* defport */
CURLPROTO_LDAP, /* protocol */
PROTOPT_NONE /* flags */
@ -110,6 +111,7 @@ const struct Curl_handler Curl_handler_ldaps = {
ZERO_NULL, /* perform_getsock */
ldap_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_LDAPS, /* defport */
CURLPROTO_LDAP, /* protocol */
PROTOPT_SSL /* flags */

View File

@ -125,6 +125,7 @@ const struct Curl_handler Curl_handler_pop3 = {
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_POP3, /* defport */
CURLPROTO_POP3, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
@ -151,6 +152,7 @@ const struct Curl_handler Curl_handler_pop3s = {
ZERO_NULL, /* perform_getsock */
pop3_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_POP3S, /* defport */
CURLPROTO_POP3S, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_SSL

View File

@ -81,6 +81,9 @@ static CURLcode rtsp_rtp_readwrite(struct Curl_easy *data,
static CURLcode rtsp_setup_connection(struct connectdata *conn);
bool rtsp_connisdead(struct connectdata *check);
static unsigned int rtsp_conncheck(struct connectdata *check,
unsigned int checks_to_perform);
/* this returns the socket to wait for in the DO and DOING state for the multi
interface and then we're always _sending_ a request and thus we wait for
@ -117,6 +120,7 @@ const struct Curl_handler Curl_handler_rtsp = {
ZERO_NULL, /* perform_getsock */
rtsp_disconnect, /* disconnect */
rtsp_rtp_readwrite, /* readwrite */
rtsp_conncheck, /* connection_check */
PORT_RTSP, /* defport */
CURLPROTO_RTSP, /* protocol */
PROTOPT_NONE /* flags */
@ -143,7 +147,7 @@ static CURLcode rtsp_setup_connection(struct connectdata *conn)
* Instead, if it is readable, run Curl_connalive() to peek at the socket
* and distinguish between closed and data.
*/
bool Curl_rtsp_connisdead(struct connectdata *check)
bool rtsp_connisdead(struct connectdata *check)
{
int sval;
bool ret_val = TRUE;
@ -165,6 +169,23 @@ bool Curl_rtsp_connisdead(struct connectdata *check)
return ret_val;
}
/*
* Function to check on various aspects of a connection.
*/
static unsigned int rtsp_conncheck(struct connectdata *check,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
if(checks_to_perform & CONNCHECK_ISDEAD) {
if(rtsp_connisdead(check))
ret_val |= CONNRESULT_DEAD;
}
return ret_val;
}
static CURLcode rtsp_connect(struct connectdata *conn, bool *done)
{
CURLcode httpStatus;

View File

@ -25,13 +25,11 @@
extern const struct Curl_handler Curl_handler_rtsp;
bool Curl_rtsp_connisdead(struct connectdata *check);
CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header);
#else
/* disabled */
#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN
#define Curl_rtsp_connisdead(x) TRUE
#endif /* CURL_DISABLE_RTSP */

View File

@ -85,6 +85,7 @@ const struct Curl_handler Curl_handler_smb = {
ZERO_NULL, /* perform_getsock */
smb_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SMB, /* defport */
CURLPROTO_SMB, /* protocol */
PROTOPT_NONE /* flags */
@ -109,6 +110,7 @@ const struct Curl_handler Curl_handler_smbs = {
ZERO_NULL, /* perform_getsock */
smb_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SMBS, /* defport */
CURLPROTO_SMBS, /* protocol */
PROTOPT_SSL /* flags */

View File

@ -124,6 +124,7 @@ const struct Curl_handler Curl_handler_smtp = {
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SMTP, /* defport */
CURLPROTO_SMTP, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */
@ -150,6 +151,7 @@ const struct Curl_handler Curl_handler_smtps = {
ZERO_NULL, /* perform_getsock */
smtp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SMTPS, /* defport */
CURLPROTO_SMTPS, /* protocol */
PROTOPT_CLOSEACTION | PROTOPT_SSL

View File

@ -177,6 +177,7 @@ const struct Curl_handler Curl_handler_scp = {
ssh_perform_getsock, /* perform_getsock */
scp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SCP, /* protocol */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
@ -203,6 +204,7 @@ const struct Curl_handler Curl_handler_sftp = {
ssh_perform_getsock, /* perform_getsock */
sftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_SSH, /* defport */
CURLPROTO_SFTP, /* protocol */
PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION

View File

@ -192,6 +192,7 @@ const struct Curl_handler Curl_handler_telnet = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_TELNET, /* defport */
CURLPROTO_TELNET, /* protocol */
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */

View File

@ -181,6 +181,7 @@ const struct Curl_handler Curl_handler_tftp = {
ZERO_NULL, /* perform_getsock */
tftp_disconnect, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
PORT_TFTP, /* defport */
CURLPROTO_TFTP, /* protocol */
PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */

View File

@ -274,6 +274,7 @@ static const struct Curl_handler Curl_handler_dummy = {
ZERO_NULL, /* perform_getsock */
ZERO_NULL, /* disconnect */
ZERO_NULL, /* readwrite */
ZERO_NULL, /* connection_check */
0, /* defport */
0, /* protocol */
PROTOPT_NONE /* flags */
@ -3379,11 +3380,19 @@ static bool disconnect_if_dead(struct connectdata *conn,
handles in pipeline and the connection isn't already marked in
use */
bool dead;
if(conn->handler->protocol & CURLPROTO_RTSP)
/* RTSP is a special case due to RTP interleaving */
dead = Curl_rtsp_connisdead(conn);
else
if(conn->handler->connection_check) {
/* The protocol has a special method for checking the state of the
connection. Use it to check if the connection is dead. */
unsigned int state;
state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
dead = (state & CONNRESULT_DEAD);
}
else {
/* Use the general method for determining the death of a connection */
dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
}
if(dead) {
conn->data = data;

View File

@ -829,6 +829,12 @@ struct Curl_handler {
CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn,
ssize_t *nread, bool *readmore);
/* This function can perform various checks on the connection. See
CONNCHECK_* for more information about the checks that can be performed,
and CONNRESULT_* for the results that can be returned. */
unsigned int (*connection_check)(struct connectdata *conn,
unsigned int checks_to_perform);
long defport; /* Default port. */
unsigned int protocol; /* See CURLPROTO_* - this needs to be the single
specific protocol bit */
@ -859,6 +865,12 @@ struct Curl_handler {
HTTP proxy as HTTP proxies may know
this protocol and act as a gateway */
#define CONNCHECK_NONE 0 /* No checks */
#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */
#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
/* return the count of bytes sent, or -1 on error */
typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */