From c75f63d7c432ab42614c05f8a8081edf4beb9ee9 Mon Sep 17 00:00:00 2001 From: Max Dymond Date: Wed, 31 May 2017 12:09:56 +0100 Subject: [PATCH] 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. --- lib/curl_rtmp.c | 6 ++++++ lib/dict.c | 1 + lib/file.c | 1 + lib/ftp.c | 2 ++ lib/gopher.c | 1 + lib/http.c | 2 ++ lib/http2.c | 2 ++ lib/imap.c | 2 ++ lib/ldap.c | 2 ++ lib/openldap.c | 2 ++ lib/pop3.c | 2 ++ lib/rtsp.c | 23 ++++++++++++++++++++++- lib/rtsp.h | 2 -- lib/smb.c | 2 ++ lib/smtp.c | 2 ++ lib/ssh.c | 2 ++ lib/telnet.c | 1 + lib/tftp.c | 1 + lib/url.c | 17 +++++++++++++---- lib/urldata.h | 12 ++++++++++++ 20 files changed, 78 insertions(+), 7 deletions(-) diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index 87a6caf9e..2d7ce5ed2 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -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*/ diff --git a/lib/dict.c b/lib/dict.c index 451ec389a..81d89fc48 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -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 */ diff --git a/lib/file.c b/lib/file.c index c804d75e1..bd426eac2 100644 --- a/lib/file.c +++ b/lib/file.c @@ -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 */ diff --git a/lib/ftp.c b/lib/ftp.c index 1e3aa8d7c..6d1f24a32 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -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 | diff --git a/lib/gopher.c b/lib/gopher.c index e6d274648..836f72550 100644 --- a/lib/gopher.c +++ b/lib/gopher.c @@ -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 */ diff --git a/lib/http.c b/lib/http.c index b8f4c8a21..e611214fb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -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 */ diff --git a/lib/http2.c b/lib/http2.c index 98fc147a9..a93348641 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -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 */ diff --git a/lib/imap.c b/lib/imap.c index 18b1760fc..48af2902a 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -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 */ diff --git a/lib/ldap.c b/lib/ldap.c index 79e84d94e..421393f11 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -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 */ diff --git a/lib/openldap.c b/lib/openldap.c index 4b8cfb9c2..369309cf5 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -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 */ diff --git a/lib/pop3.c b/lib/pop3.c index 4aff6031c..5792a4a6f 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -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 diff --git a/lib/rtsp.c b/lib/rtsp.c index 1810cdafb..9bd935fd5 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -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; diff --git a/lib/rtsp.h b/lib/rtsp.h index 5a8d5556f..8375a5317 100644 --- a/lib/rtsp.h +++ b/lib/rtsp.h @@ -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 */ diff --git a/lib/smb.c b/lib/smb.c index 5b1ffa9b7..c2df43b70 100644 --- a/lib/smb.c +++ b/lib/smb.c @@ -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 */ diff --git a/lib/smtp.c b/lib/smtp.c index e609ec9d9..4e2c3361e 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -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 diff --git a/lib/ssh.c b/lib/ssh.c index 00aeca978..d6620770d 100644 --- a/lib/ssh.c +++ b/lib/ssh.c @@ -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 diff --git a/lib/telnet.c b/lib/telnet.c index 155d4b260..122100523 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -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 */ diff --git a/lib/tftp.c b/lib/tftp.c index b2b3efe0c..336beb512 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -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 */ diff --git a/lib/url.c b/lib/url.c index 07bdea129..e4aa515be 100644 --- a/lib/url.c +++ b/lib/url.c @@ -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; diff --git a/lib/urldata.h b/lib/urldata.h index e89d1d706..41f9408ba 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -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 */