From: Viktor Szakats Date: Tue, 13 Jan 2026 14:27:36 +0000 (+0100) Subject: lib: reorder protocol functions to avoid forward declarations (misc cont.) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7d2c65e6ee258b5800bbb93de2228d0550089c18;p=thirdparty%2Fcurl.git lib: reorder protocol functions to avoid forward declarations (misc cont.) For protocols: ldap, openldap, rtmp, rtsp, telnet Move protocol handler table to the end of sources, rearrange static functions in reverse dependency order as necessary. Closes #20289 --- diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index 98816f8269..245ce04f6e 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -47,172 +47,9 @@ /* meta key for storing RTMP* at connection */ #define CURL_META_RTMP_CONN "meta:proto:rtmp:conn" - -static CURLcode rtmp_setup_connection(struct Curl_easy *data, - struct connectdata *conn); -static CURLcode rtmp_do(struct Curl_easy *data, bool *done); -static CURLcode rtmp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode rtmp_connect(struct Curl_easy *data, bool *done); -static CURLcode rtmp_disconnect(struct Curl_easy *data, - struct connectdata *conn, bool dead); - static Curl_recv rtmp_recv; static Curl_send rtmp_send; -/* - * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu/ - */ - -const struct Curl_handler Curl_handler_rtmp = { - "rtmp", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMP, /* defport */ - CURLPROTO_RTMP, /* protocol */ - CURLPROTO_RTMP, /* family */ - PROTOPT_NONE /* flags */ -}; - -const struct Curl_handler Curl_handler_rtmpt = { - "rtmpt", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPT, /* defport */ - CURLPROTO_RTMPT, /* protocol */ - CURLPROTO_RTMPT, /* family */ - PROTOPT_NONE /* flags */ -}; - -const struct Curl_handler Curl_handler_rtmpe = { - "rtmpe", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMP, /* defport */ - CURLPROTO_RTMPE, /* protocol */ - CURLPROTO_RTMPE, /* family */ - PROTOPT_NONE /* flags */ -}; - -const struct Curl_handler Curl_handler_rtmpte = { - "rtmpte", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPT, /* defport */ - CURLPROTO_RTMPTE, /* protocol */ - CURLPROTO_RTMPTE, /* family */ - PROTOPT_NONE /* flags */ -}; - -const struct Curl_handler Curl_handler_rtmps = { - "rtmps", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPS, /* defport */ - CURLPROTO_RTMPS, /* protocol */ - CURLPROTO_RTMP, /* family */ - PROTOPT_NONE /* flags */ -}; - -const struct Curl_handler Curl_handler_rtmpts = { - "rtmpts", /* scheme */ - rtmp_setup_connection, /* setup_connection */ - rtmp_do, /* do_it */ - rtmp_done, /* done */ - ZERO_NULL, /* do_more */ - rtmp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - rtmp_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_RTMPS, /* defport */ - CURLPROTO_RTMPTS, /* protocol */ - CURLPROTO_RTMPT, /* family */ - PROTOPT_NONE /* flags */ -}; - static void rtmp_conn_dtor(void *key, size_t klen, void *entry) { RTMP *r = entry; @@ -383,4 +220,158 @@ void Curl_rtmp_version(char *version, size_t len) suff); } +/* + * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu/ + */ + +const struct Curl_handler Curl_handler_rtmp = { + "rtmp", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMP, /* protocol */ + CURLPROTO_RTMP, /* family */ + PROTOPT_NONE /* flags */ +}; + +const struct Curl_handler Curl_handler_rtmpt = { + "rtmpt", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPT, /* protocol */ + CURLPROTO_RTMPT, /* family */ + PROTOPT_NONE /* flags */ +}; + +const struct Curl_handler Curl_handler_rtmpe = { + "rtmpe", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_RTMP, /* defport */ + CURLPROTO_RTMPE, /* protocol */ + CURLPROTO_RTMPE, /* family */ + PROTOPT_NONE /* flags */ +}; + +const struct Curl_handler Curl_handler_rtmpte = { + "rtmpte", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_RTMPT, /* defport */ + CURLPROTO_RTMPTE, /* protocol */ + CURLPROTO_RTMPTE, /* family */ + PROTOPT_NONE /* flags */ +}; + +const struct Curl_handler Curl_handler_rtmps = { + "rtmps", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPS, /* protocol */ + CURLPROTO_RTMP, /* family */ + PROTOPT_NONE /* flags */ +}; + +const struct Curl_handler Curl_handler_rtmpts = { + "rtmpts", /* scheme */ + rtmp_setup_connection, /* setup_connection */ + rtmp_do, /* do_it */ + rtmp_done, /* done */ + ZERO_NULL, /* do_more */ + rtmp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + rtmp_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_RTMPS, /* defport */ + CURLPROTO_RTMPTS, /* protocol */ + CURLPROTO_RTMPT, /* family */ + PROTOPT_NONE /* flags */ +}; + #endif /* USE_LIBRTMP */ diff --git a/lib/ldap.c b/lib/ldap.c index 95a982f353..616600ce35 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -163,66 +163,6 @@ static void ldap_trace_low(const char *fmt, ...) CURL_PRINTF(1, 2); #define LDAP_OPT_OFF ((void *)(size_t)0) #endif -static CURLcode ldap_do(struct Curl_easy *data, bool *done); - -/* - * LDAP protocol handler. - */ -const struct Curl_handler Curl_handler_ldap = { - "ldap", /* scheme */ - ZERO_NULL, /* setup_connection */ - ldap_do, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_LDAP, /* defport */ - CURLPROTO_LDAP, /* protocol */ - CURLPROTO_LDAP, /* family */ - PROTOPT_SSL_REUSE /* flags */ -}; - -#ifdef HAVE_LDAP_SSL -/* - * LDAPS protocol handler. - */ -const struct Curl_handler Curl_handler_ldaps = { - "ldaps", /* scheme */ - ZERO_NULL, /* setup_connection */ - ldap_do, /* do_it */ - ZERO_NULL, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_LDAPS, /* defport */ - CURLPROTO_LDAPS, /* protocol */ - CURLPROTO_LDAP, /* family */ - PROTOPT_SSL /* flags */ -}; -#endif - #ifdef USE_WIN32_LDAP #ifdef USE_WINDOWS_SSPI @@ -1049,6 +989,64 @@ void Curl_ldap_version(char *buf, size_t bufsz) #endif } +/* + * LDAP protocol handler. + */ +const struct Curl_handler Curl_handler_ldap = { + "ldap", /* scheme */ + ZERO_NULL, /* setup_connection */ + ldap_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + CURLPROTO_LDAP, /* family */ + PROTOPT_SSL_REUSE /* flags */ +}; + +#ifdef HAVE_LDAP_SSL +/* + * LDAPS protocol handler. + */ +const struct Curl_handler Curl_handler_ldaps = { + "ldaps", /* scheme */ + ZERO_NULL, /* setup_connection */ + ldap_do, /* do_it */ + ZERO_NULL, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAPS, /* protocol */ + CURLPROTO_LDAP, /* family */ + PROTOPT_SSL /* flags */ +}; +#endif + #if defined(__GNUC__) && defined(__APPLE__) #pragma GCC diagnostic pop #endif diff --git a/lib/openldap.c b/lib/openldap.c index f826a4d006..59a2ed6e65 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -91,98 +91,8 @@ extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld); #endif -static CURLcode oldap_setup_connection(struct Curl_easy *data, - struct connectdata *conn); -static CURLcode oldap_do(struct Curl_easy *data, bool *done); -static CURLcode oldap_done(struct Curl_easy *data, CURLcode, bool); -static CURLcode oldap_connect(struct Curl_easy *data, bool *done); -static CURLcode oldap_connecting(struct Curl_easy *data, bool *done); -static CURLcode oldap_disconnect(struct Curl_easy *data, - struct connectdata *conn, bool dead); - -static CURLcode oldap_perform_auth(struct Curl_easy *data, const char *mech, - const struct bufref *initresp); -static CURLcode oldap_continue_auth(struct Curl_easy *data, const char *mech, - const struct bufref *resp); -static CURLcode oldap_cancel_auth(struct Curl_easy *data, const char *mech); -static CURLcode oldap_get_message(struct Curl_easy *data, struct bufref *out); - static Curl_recv oldap_recv; -/* - * LDAP protocol handler. - */ -const struct Curl_handler Curl_handler_ldap = { - "ldap", /* scheme */ - oldap_setup_connection, /* setup_connection */ - oldap_do, /* do_it */ - oldap_done, /* done */ - ZERO_NULL, /* do_more */ - oldap_connect, /* connect_it */ - oldap_connecting, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - oldap_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_LDAP, /* defport */ - CURLPROTO_LDAP, /* protocol */ - CURLPROTO_LDAP, /* family */ - PROTOPT_SSL_REUSE | /* flags */ - PROTOPT_CONN_REUSE -}; - -#ifdef USE_SSL -/* - * LDAPS protocol handler. - */ -const struct Curl_handler Curl_handler_ldaps = { - "ldaps", /* scheme */ - oldap_setup_connection, /* setup_connection */ - oldap_do, /* do_it */ - oldap_done, /* done */ - ZERO_NULL, /* do_more */ - oldap_connect, /* connect_it */ - oldap_connecting, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - oldap_disconnect, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_LDAPS, /* defport */ - CURLPROTO_LDAPS, /* protocol */ - CURLPROTO_LDAP, /* family */ - PROTOPT_SSL | /* flags */ - PROTOPT_CONN_REUSE -}; -#endif - -/* SASL parameters for the ldap protocol */ -static const struct SASLproto saslldap = { - "ldap", /* The service name */ - oldap_perform_auth, /* Send authentication command */ - oldap_continue_auth, /* Send authentication continuation */ - oldap_cancel_auth, /* Send authentication cancellation */ - oldap_get_message, /* Get SASL response message */ - 0, /* Maximum initial response length (no max) */ - LDAP_SASL_BIND_IN_PROGRESS, /* Code received when continuation is expected */ - LDAP_SUCCESS, /* Code to receive upon authentication success */ - SASL_AUTH_NONE, /* Default mechanisms */ - 0 /* Configuration flags */ -}; - struct ldapconninfo { struct SASL sasl; /* SASL-related parameters */ LDAP *ld; /* Openldap connection handle. */ @@ -585,6 +495,20 @@ static void oldap_conn_dtor(void *key, size_t klen, void *entry) curlx_free(li); } +/* SASL parameters for the ldap protocol */ +static const struct SASLproto saslldap = { + "ldap", /* The service name */ + oldap_perform_auth, /* Send authentication command */ + oldap_continue_auth, /* Send authentication continuation */ + oldap_cancel_auth, /* Send authentication cancellation */ + oldap_get_message, /* Get SASL response message */ + 0, /* Maximum initial response length (no max) */ + LDAP_SASL_BIND_IN_PROGRESS, /* Code received when continuation is expected */ + LDAP_SUCCESS, /* Code to receive upon authentication success */ + SASL_AUTH_NONE, /* Default mechanisms */ + 0 /* Configuration flags */ +}; + static CURLcode oldap_connect(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; @@ -1344,4 +1268,64 @@ void Curl_ldap_version(char *buf, size_t bufsz) curl_msnprintf(buf, bufsz, "OpenLDAP"); } +/* + * LDAP protocol handler. + */ +const struct Curl_handler Curl_handler_ldap = { + "ldap", /* scheme */ + oldap_setup_connection, /* setup_connection */ + oldap_do, /* do_it */ + oldap_done, /* done */ + ZERO_NULL, /* do_more */ + oldap_connect, /* connect_it */ + oldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + oldap_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_LDAP, /* defport */ + CURLPROTO_LDAP, /* protocol */ + CURLPROTO_LDAP, /* family */ + PROTOPT_SSL_REUSE | /* flags */ + PROTOPT_CONN_REUSE +}; + +#ifdef USE_SSL +/* + * LDAPS protocol handler. + */ +const struct Curl_handler Curl_handler_ldaps = { + "ldaps", /* scheme */ + oldap_setup_connection, /* setup_connection */ + oldap_do, /* do_it */ + oldap_done, /* done */ + ZERO_NULL, /* do_more */ + oldap_connect, /* connect_it */ + oldap_connecting, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + oldap_disconnect, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_LDAPS, /* defport */ + CURLPROTO_LDAPS, /* protocol */ + CURLPROTO_LDAP, /* family */ + PROTOPT_SSL | /* flags */ + PROTOPT_CONN_REUSE +}; +#endif + #endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ diff --git a/lib/rtsp.c b/lib/rtsp.c index 35dc049778..8712a456cc 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -73,13 +73,6 @@ struct RTSP { #define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \ ((unsigned int)((unsigned char)((p)[3])))) -/* protocol-specific functions set up to be called by the main engine */ -static CURLcode rtsp_do(struct Curl_easy *data, bool *done); -static CURLcode rtsp_done(struct Curl_easy *data, CURLcode, bool premature); -static CURLcode rtsp_connect(struct Curl_easy *data, bool *done); -static CURLcode rtsp_do_pollset(struct Curl_easy *data, - struct easy_pollset *ps); - /* * Parse and write out an RTSP response. * @param data the transfer @@ -120,34 +113,6 @@ static CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, static CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport); -/* - * RTSP handler interface. - */ -const struct Curl_handler Curl_handler_rtsp = { - "rtsp", /* scheme */ - rtsp_setup_connection, /* setup_connection */ - rtsp_do, /* do_it */ - rtsp_done, /* done */ - ZERO_NULL, /* do_more */ - rtsp_connect, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - rtsp_do_pollset, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - Curl_http_perform_pollset, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - rtsp_rtp_write_resp, /* write_resp */ - rtsp_rtp_write_resp_hd, /* write_resp_hd */ - rtsp_conncheck, /* connection_check */ - ZERO_NULL, /* attach connection */ - Curl_http_follow, /* follow */ - PORT_RTSP, /* defport */ - CURLPROTO_RTSP, /* protocol */ - CURLPROTO_RTSP, /* family */ - PROTOPT_CONN_REUSE /* flags */ -}; - #define MAX_RTP_BUFFERSIZE 1000000 /* arbitrary */ static void rtsp_easy_dtor(void *key, size_t klen, void *entry) @@ -1098,4 +1063,32 @@ static CURLcode rtsp_parse_transport(struct Curl_easy *data, return CURLE_OK; } +/* + * RTSP handler interface. + */ +const struct Curl_handler Curl_handler_rtsp = { + "rtsp", /* scheme */ + rtsp_setup_connection, /* setup_connection */ + rtsp_do, /* do_it */ + rtsp_done, /* done */ + ZERO_NULL, /* do_more */ + rtsp_connect, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + rtsp_do_pollset, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + Curl_http_perform_pollset, /* perform_pollset */ + ZERO_NULL, /* disconnect */ + rtsp_rtp_write_resp, /* write_resp */ + rtsp_rtp_write_resp_hd, /* write_resp_hd */ + rtsp_conncheck, /* connection_check */ + ZERO_NULL, /* attach connection */ + Curl_http_follow, /* follow */ + PORT_RTSP, /* defport */ + CURLPROTO_RTSP, /* protocol */ + CURLPROTO_RTSP, /* family */ + PROTOPT_CONN_REUSE /* flags */ +}; + #endif /* CURL_DISABLE_RTSP */ diff --git a/lib/telnet.c b/lib/telnet.c index cca97cfc1c..02fc3a1edc 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -78,10 +78,6 @@ #define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) #define CURL_SB_EOF(x) (x->subpointer >= x->subend) */ -#ifdef CURL_DISABLE_VERBOSE_STRINGS -#define printoption(a, b, c, d) Curl_nop_stmt -#endif - /* For negotiation compliant to RFC 1143 */ #define CURL_NO 0 #define CURL_YES 1 @@ -132,67 +128,44 @@ struct TELNET { unsigned char *subpointer, *subend; /* buffer for sub-options */ }; -static CURLcode telrcv(struct Curl_easy *data, - struct TELNET *tn, - const unsigned char *inbuf, /* Data received from - socket */ - ssize_t count); /* Number of bytes - received */ - -#ifndef CURL_DISABLE_VERBOSE_STRINGS +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define printoption(a, b, c, d) Curl_nop_stmt +#else static void printoption(struct Curl_easy *data, - const char *direction, - int cmd, int option); -#endif - -static void send_negotiation(struct Curl_easy *data, int cmd, int option); -static void set_local_option(struct Curl_easy *data, struct TELNET *tn, - int option, int newstate); -static void set_remote_option(struct Curl_easy *data, struct TELNET *tn, - int option, int newstate); - -static void printsub(struct Curl_easy *data, - int direction, unsigned char *pointer, - size_t length); -static CURLcode suboption(struct Curl_easy *data, struct TELNET *tn); -static void sendsuboption(struct Curl_easy *data, - struct TELNET *tn, int option); - -static CURLcode telnet_do(struct Curl_easy *data, bool *done); -static CURLcode telnet_done(struct Curl_easy *data, - CURLcode, bool premature); -static CURLcode send_telnet_data(struct Curl_easy *data, - struct TELNET *tn, - char *buffer, ssize_t nread); - -/* - * TELNET protocol handler. - */ + const char *direction, int cmd, int option) +{ + if(data->set.verbose) { + if(cmd == CURL_IAC) { + if(CURL_TELCMD_OK(option)) + infof(data, "%s IAC %s", direction, CURL_TELCMD(option)); + else + infof(data, "%s IAC %d", direction, option); + } + else { + const char *fmt = (cmd == CURL_WILL) ? "WILL" : + (cmd == CURL_WONT) ? "WONT" : + (cmd == CURL_DO) ? "DO" : + (cmd == CURL_DONT) ? "DONT" : 0; + if(fmt) { + const char *opt; + if(CURL_TELOPT_OK(option)) + opt = CURL_TELOPT(option); + else if(option == CURL_TELOPT_EXOPL) + opt = "EXOPL"; + else + opt = NULL; -const struct Curl_handler Curl_handler_telnet = { - "telnet", /* scheme */ - ZERO_NULL, /* setup_connection */ - telnet_do, /* do_it */ - telnet_done, /* done */ - ZERO_NULL, /* do_more */ - ZERO_NULL, /* connect_it */ - ZERO_NULL, /* connecting */ - ZERO_NULL, /* doing */ - ZERO_NULL, /* proto_pollset */ - ZERO_NULL, /* doing_pollset */ - ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ - ZERO_NULL, /* disconnect */ - ZERO_NULL, /* write_resp */ - ZERO_NULL, /* write_resp_hd */ - ZERO_NULL, /* connection_check */ - ZERO_NULL, /* attach connection */ - ZERO_NULL, /* follow */ - PORT_TELNET, /* defport */ - CURLPROTO_TELNET, /* protocol */ - CURLPROTO_TELNET, /* family */ - PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ -}; + if(opt) + infof(data, "%s %s %s", direction, fmt, opt); + else + infof(data, "%s %s %d", direction, fmt, option); + } + else + infof(data, "%s %d %d", direction, cmd, option); + } + } +} +#endif /* CURL_DISABLE_VERBOSE_STRINGS */ static void telnet_easy_dtor(void *key, size_t klen, void *entry) { @@ -255,59 +228,6 @@ static CURLcode init_telnet(struct Curl_easy *data) return Curl_meta_set(data, CURL_META_TELNET_EASY, tn, telnet_easy_dtor); } -static void telnet_negotiate(struct Curl_easy *data, struct TELNET *tn) -{ - int i; - - for(i = 0; i < CURL_NTELOPTS; i++) { - if(i == CURL_TELOPT_ECHO) - continue; - - if(tn->us_preferred[i] == CURL_YES) - set_local_option(data, tn, i, CURL_YES); - - if(tn->him_preferred[i] == CURL_YES) - set_remote_option(data, tn, i, CURL_YES); - } -} - -#ifndef CURL_DISABLE_VERBOSE_STRINGS -static void printoption(struct Curl_easy *data, - const char *direction, int cmd, int option) -{ - if(data->set.verbose) { - if(cmd == CURL_IAC) { - if(CURL_TELCMD_OK(option)) - infof(data, "%s IAC %s", direction, CURL_TELCMD(option)); - else - infof(data, "%s IAC %d", direction, option); - } - else { - const char *fmt = (cmd == CURL_WILL) ? "WILL" : - (cmd == CURL_WONT) ? "WONT" : - (cmd == CURL_DO) ? "DO" : - (cmd == CURL_DONT) ? "DONT" : 0; - if(fmt) { - const char *opt; - if(CURL_TELOPT_OK(option)) - opt = CURL_TELOPT(option); - else if(option == CURL_TELOPT_EXOPL) - opt = "EXOPL"; - else - opt = NULL; - - if(opt) - infof(data, "%s %s %s", direction, fmt, opt); - else - infof(data, "%s %s %d", direction, fmt, option); - } - else - infof(data, "%s %d %d", direction, cmd, option); - } - } -} -#endif - static void send_negotiation(struct Curl_easy *data, int cmd, int option) { unsigned char buf[3]; @@ -400,92 +320,6 @@ static void set_remote_option(struct Curl_easy *data, struct TELNET *tn, } } -static void rec_will(struct Curl_easy *data, struct TELNET *tn, int option) -{ - switch(tn->him[option]) { - case CURL_NO: - if(tn->him_preferred[option] == CURL_YES) { - tn->him[option] = CURL_YES; - send_negotiation(data, CURL_DO, option); - } - else - send_negotiation(data, CURL_DONT, option); - - break; - - case CURL_YES: - /* Already enabled */ - break; - - case CURL_WANTNO: - switch(tn->himq[option]) { - case CURL_EMPTY: - /* Error: DONT answered by WILL */ - tn->him[option] = CURL_NO; - break; - case CURL_OPPOSITE: - /* Error: DONT answered by WILL */ - tn->him[option] = CURL_YES; - tn->himq[option] = CURL_EMPTY; - break; - } - break; - - case CURL_WANTYES: - switch(tn->himq[option]) { - case CURL_EMPTY: - tn->him[option] = CURL_YES; - break; - case CURL_OPPOSITE: - tn->him[option] = CURL_WANTNO; - tn->himq[option] = CURL_EMPTY; - send_negotiation(data, CURL_DONT, option); - break; - } - break; - } -} - -static void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option) -{ - switch(tn->him[option]) { - case CURL_NO: - /* Already disabled */ - break; - - case CURL_YES: - tn->him[option] = CURL_NO; - send_negotiation(data, CURL_DONT, option); - break; - - case CURL_WANTNO: - switch(tn->himq[option]) { - case CURL_EMPTY: - tn->him[option] = CURL_NO; - break; - - case CURL_OPPOSITE: - tn->him[option] = CURL_WANTYES; - tn->himq[option] = CURL_EMPTY; - send_negotiation(data, CURL_DO, option); - break; - } - break; - - case CURL_WANTYES: - switch(tn->himq[option]) { - case CURL_EMPTY: - tn->him[option] = CURL_NO; - break; - case CURL_OPPOSITE: - tn->him[option] = CURL_NO; - tn->himq[option] = CURL_EMPTY; - break; - } - break; - } -} - static void set_local_option(struct Curl_easy *data, struct TELNET *tn, int option, int newstate) { @@ -559,25 +393,33 @@ static void set_local_option(struct Curl_easy *data, struct TELNET *tn, } } -static void rec_do(struct Curl_easy *data, struct TELNET *tn, int option) +static void telnet_negotiate(struct Curl_easy *data, struct TELNET *tn) { - switch(tn->us[option]) { + int i; + + for(i = 0; i < CURL_NTELOPTS; i++) { + if(i == CURL_TELOPT_ECHO) + continue; + + if(tn->us_preferred[i] == CURL_YES) + set_local_option(data, tn, i, CURL_YES); + + if(tn->him_preferred[i] == CURL_YES) + set_remote_option(data, tn, i, CURL_YES); + } +} + +static void rec_will(struct Curl_easy *data, struct TELNET *tn, int option) +{ + switch(tn->him[option]) { case CURL_NO: - if(tn->us_preferred[option] == CURL_YES) { - tn->us[option] = CURL_YES; - send_negotiation(data, CURL_WILL, option); - if(tn->subnegotiation[option] == CURL_YES) - /* transmission of data option */ - sendsuboption(data, tn, option); - } - else if(tn->subnegotiation[option] == CURL_YES) { - /* send information to achieve this option */ - tn->us[option] = CURL_YES; - send_negotiation(data, CURL_WILL, option); - sendsuboption(data, tn, option); + if(tn->him_preferred[option] == CURL_YES) { + tn->him[option] = CURL_YES; + send_negotiation(data, CURL_DO, option); } else - send_negotiation(data, CURL_WONT, option); + send_negotiation(data, CURL_DONT, option); + break; case CURL_YES: @@ -585,72 +427,68 @@ static void rec_do(struct Curl_easy *data, struct TELNET *tn, int option) break; case CURL_WANTNO: - switch(tn->usq[option]) { + switch(tn->himq[option]) { case CURL_EMPTY: /* Error: DONT answered by WILL */ - tn->us[option] = CURL_NO; + tn->him[option] = CURL_NO; break; case CURL_OPPOSITE: /* Error: DONT answered by WILL */ - tn->us[option] = CURL_YES; - tn->usq[option] = CURL_EMPTY; + tn->him[option] = CURL_YES; + tn->himq[option] = CURL_EMPTY; break; } break; case CURL_WANTYES: - switch(tn->usq[option]) { + switch(tn->himq[option]) { case CURL_EMPTY: - tn->us[option] = CURL_YES; - if(tn->subnegotiation[option] == CURL_YES) { - /* transmission of data option */ - sendsuboption(data, tn, option); - } + tn->him[option] = CURL_YES; break; case CURL_OPPOSITE: - tn->us[option] = CURL_WANTNO; + tn->him[option] = CURL_WANTNO; tn->himq[option] = CURL_EMPTY; - send_negotiation(data, CURL_WONT, option); + send_negotiation(data, CURL_DONT, option); break; } break; } } -static void rec_dont(struct Curl_easy *data, struct TELNET *tn, int option) +static void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option) { - switch(tn->us[option]) { + switch(tn->him[option]) { case CURL_NO: /* Already disabled */ break; case CURL_YES: - tn->us[option] = CURL_NO; - send_negotiation(data, CURL_WONT, option); + tn->him[option] = CURL_NO; + send_negotiation(data, CURL_DONT, option); break; case CURL_WANTNO: - switch(tn->usq[option]) { + switch(tn->himq[option]) { case CURL_EMPTY: - tn->us[option] = CURL_NO; + tn->him[option] = CURL_NO; break; case CURL_OPPOSITE: - tn->us[option] = CURL_WANTYES; - tn->usq[option] = CURL_EMPTY; - send_negotiation(data, CURL_WILL, option); + tn->him[option] = CURL_WANTYES; + tn->himq[option] = CURL_EMPTY; + send_negotiation(data, CURL_DO, option); break; } break; case CURL_WANTYES: - switch(tn->usq[option]) { + switch(tn->himq[option]) { case CURL_EMPTY: - tn->us[option] = CURL_NO; + tn->him[option] = CURL_NO; break; case CURL_OPPOSITE: - tn->us[option] = CURL_NO; - tn->usq[option] = CURL_EMPTY; + tn->him[option] = CURL_NO; + tn->himq[option] = CURL_EMPTY; break; } break; @@ -712,61 +550,275 @@ static void printsub(struct Curl_easy *data, break; } } - else - infof(data, "%d (unknown)", pointer[0]); + else + infof(data, "%d (unknown)", pointer[0]); + + switch(pointer[0]) { + case CURL_TELOPT_NAWS: + if(length > 4) + infof(data, "Width: %d ; Height: %d", (pointer[1] << 8) | pointer[2], + (pointer[3] << 8) | pointer[4]); + break; + default: + switch(pointer[1]) { + case CURL_TELQUAL_IS: + infof(data, " IS"); + break; + case CURL_TELQUAL_SEND: + infof(data, " SEND"); + break; + case CURL_TELQUAL_INFO: + infof(data, " INFO/REPLY"); + break; + case CURL_TELQUAL_NAME: + infof(data, " NAME"); + break; + } + + switch(pointer[0]) { + case CURL_TELOPT_TTYPE: + case CURL_TELOPT_XDISPLOC: + infof(data, " \"%.*s\"", + (int)((length > 2) ? (length - 2) : 0), &pointer[2]); + break; + case CURL_TELOPT_NEW_ENVIRON: + if(pointer[1] == CURL_TELQUAL_IS) { + infof(data, " "); + for(i = 3; i < length; i++) { + switch(pointer[i]) { + case CURL_NEW_ENV_VAR: + infof(data, ", "); + break; + case CURL_NEW_ENV_VALUE: + infof(data, " = "); + break; + default: + infof(data, "%c", pointer[i]); + break; + } + } + } + break; + default: + for(i = 2; i < length; i++) + infof(data, " %.2x", pointer[i]); + break; + } + } + } +} + +/* Escape and send a telnet data block */ +static CURLcode send_telnet_data(struct Curl_easy *data, + struct TELNET *tn, + char *buffer, ssize_t nread) +{ + size_t i, outlen; + unsigned char *outbuf; + CURLcode result = CURLE_OK; + size_t bytes_written; + size_t total_written = 0; + struct connectdata *conn = data->conn; + + DEBUGASSERT(tn); + DEBUGASSERT(nread > 0); + if(nread < 0) + return CURLE_TOO_LARGE; + + if(memchr(buffer, CURL_IAC, nread)) { + /* only use the escape buffer when necessary */ + curlx_dyn_reset(&tn->out); + + for(i = 0; i < (size_t)nread && !result; i++) { + result = curlx_dyn_addn(&tn->out, &buffer[i], 1); + if(!result && ((unsigned char)buffer[i] == CURL_IAC)) + /* IAC is FF in hex */ + result = curlx_dyn_addn(&tn->out, "\xff", 1); + } + + outlen = curlx_dyn_len(&tn->out); + outbuf = curlx_dyn_uptr(&tn->out); + } + else { + outlen = (size_t)nread; + outbuf = (unsigned char *)buffer; + } + while(!result && total_written < outlen) { + /* Make sure socket is writable to avoid EWOULDBLOCK condition */ + struct pollfd pfd[1]; + pfd[0].fd = conn->sock[FIRSTSOCKET]; + pfd[0].events = POLLOUT; + switch(Curl_poll(pfd, 1, -1)) { + case -1: /* error, abort writing */ + case 0: /* timeout (will never happen) */ + result = CURLE_SEND_ERROR; + break; + default: /* write! */ + bytes_written = 0; + result = Curl_xfer_send(data, outbuf + total_written, + outlen - total_written, FALSE, &bytes_written); + total_written += bytes_written; + break; + } + } + + return result; +} + +/* + * sendsuboption() + * + * Send suboption information to the server side. + */ +static void sendsuboption(struct Curl_easy *data, + struct TELNET *tn, int option) +{ + ssize_t bytes_written; + int err; + unsigned short x, y; + unsigned char *uc1, *uc2; + struct connectdata *conn = data->conn; + + switch(option) { + case CURL_TELOPT_NAWS: + /* We prepare data to be sent */ + CURL_SB_CLEAR(tn); + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SB); + CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS); + /* We must deal either with little or big endian processors */ + /* Window size must be sent according to the 'network order' */ + x = htons(tn->subopt_wsx); + y = htons(tn->subopt_wsy); + uc1 = (unsigned char *)&x; + uc2 = (unsigned char *)&y; + CURL_SB_ACCUM(tn, uc1[0]); + CURL_SB_ACCUM(tn, uc1[1]); + CURL_SB_ACCUM(tn, uc2[0]); + CURL_SB_ACCUM(tn, uc2[1]); + + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + CURL_SB_TERM(tn); + /* data suboption is now ready */ + + printsub(data, '>', (unsigned char *)tn->subbuffer + 2, + CURL_SB_LEN(tn) - 2); + + /* we send the header of the suboption... */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + /* ... then the window size with the send_telnet_data() function + to deal with 0xFF cases ... */ + send_telnet_data(data, tn, (char *)tn->subbuffer + 3, 4); + /* ... and the footer */ + bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + break; + } +} + +static void rec_do(struct Curl_easy *data, struct TELNET *tn, int option) +{ + switch(tn->us[option]) { + case CURL_NO: + if(tn->us_preferred[option] == CURL_YES) { + tn->us[option] = CURL_YES; + send_negotiation(data, CURL_WILL, option); + if(tn->subnegotiation[option] == CURL_YES) + /* transmission of data option */ + sendsuboption(data, tn, option); + } + else if(tn->subnegotiation[option] == CURL_YES) { + /* send information to achieve this option */ + tn->us[option] = CURL_YES; + send_negotiation(data, CURL_WILL, option); + sendsuboption(data, tn, option); + } + else + send_negotiation(data, CURL_WONT, option); + break; + + case CURL_YES: + /* Already enabled */ + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + /* Error: DONT answered by WILL */ + tn->us[option] = CURL_YES; + tn->usq[option] = CURL_EMPTY; + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_YES; + if(tn->subnegotiation[option] == CURL_YES) { + /* transmission of data option */ + sendsuboption(data, tn, option); + } + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTNO; + tn->himq[option] = CURL_EMPTY; + send_negotiation(data, CURL_WONT, option); + break; + } + break; + } +} - switch(pointer[0]) { - case CURL_TELOPT_NAWS: - if(length > 4) - infof(data, "Width: %d ; Height: %d", (pointer[1] << 8) | pointer[2], - (pointer[3] << 8) | pointer[4]); +static void rec_dont(struct Curl_easy *data, struct TELNET *tn, int option) +{ + switch(tn->us[option]) { + case CURL_NO: + /* Already disabled */ + break; + + case CURL_YES: + tn->us[option] = CURL_NO; + send_negotiation(data, CURL_WONT, option); + break; + + case CURL_WANTNO: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; break; - default: - switch(pointer[1]) { - case CURL_TELQUAL_IS: - infof(data, " IS"); - break; - case CURL_TELQUAL_SEND: - infof(data, " SEND"); - break; - case CURL_TELQUAL_INFO: - infof(data, " INFO/REPLY"); - break; - case CURL_TELQUAL_NAME: - infof(data, " NAME"); - break; - } - switch(pointer[0]) { - case CURL_TELOPT_TTYPE: - case CURL_TELOPT_XDISPLOC: - infof(data, " \"%.*s\"", - (int)((length > 2) ? (length - 2) : 0), &pointer[2]); - break; - case CURL_TELOPT_NEW_ENVIRON: - if(pointer[1] == CURL_TELQUAL_IS) { - infof(data, " "); - for(i = 3; i < length; i++) { - switch(pointer[i]) { - case CURL_NEW_ENV_VAR: - infof(data, ", "); - break; - case CURL_NEW_ENV_VALUE: - infof(data, " = "); - break; - default: - infof(data, "%c", pointer[i]); - break; - } - } - } - break; - default: - for(i = 2; i < length; i++) - infof(data, " %.2x", pointer[i]); - break; - } + case CURL_OPPOSITE: + tn->us[option] = CURL_WANTYES; + tn->usq[option] = CURL_EMPTY; + send_negotiation(data, CURL_WILL, option); + break; + } + break; + + case CURL_WANTYES: + switch(tn->usq[option]) { + case CURL_EMPTY: + tn->us[option] = CURL_NO; + break; + case CURL_OPPOSITE: + tn->us[option] = CURL_NO; + tn->usq[option] = CURL_EMPTY; + break; } + break; } } @@ -1011,65 +1063,6 @@ static CURLcode suboption(struct Curl_easy *data, struct TELNET *tn) return CURLE_OK; } -/* - * sendsuboption() - * - * Send suboption information to the server side. - */ -static void sendsuboption(struct Curl_easy *data, - struct TELNET *tn, int option) -{ - ssize_t bytes_written; - int err; - unsigned short x, y; - unsigned char *uc1, *uc2; - struct connectdata *conn = data->conn; - - switch(option) { - case CURL_TELOPT_NAWS: - /* We prepare data to be sent */ - CURL_SB_CLEAR(tn); - CURL_SB_ACCUM(tn, CURL_IAC); - CURL_SB_ACCUM(tn, CURL_SB); - CURL_SB_ACCUM(tn, CURL_TELOPT_NAWS); - /* We must deal either with little or big endian processors */ - /* Window size must be sent according to the 'network order' */ - x = htons(tn->subopt_wsx); - y = htons(tn->subopt_wsy); - uc1 = (unsigned char *)&x; - uc2 = (unsigned char *)&y; - CURL_SB_ACCUM(tn, uc1[0]); - CURL_SB_ACCUM(tn, uc1[1]); - CURL_SB_ACCUM(tn, uc2[0]); - CURL_SB_ACCUM(tn, uc2[1]); - - CURL_SB_ACCUM(tn, CURL_IAC); - CURL_SB_ACCUM(tn, CURL_SE); - CURL_SB_TERM(tn); - /* data suboption is now ready */ - - printsub(data, '>', (unsigned char *)tn->subbuffer + 2, - CURL_SB_LEN(tn) - 2); - - /* we send the header of the suboption... */ - bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data, "Sending data failed (%d)", err); - } - /* ... then the window size with the send_telnet_data() function - to deal with 0xFF cases ... */ - send_telnet_data(data, tn, (char *)tn->subbuffer + 3, 4); - /* ... and the footer */ - bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer + 7, 2); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data, "Sending data failed (%d)", err); - } - break; - } -} - static CURLcode telrcv(struct Curl_easy *data, struct TELNET *tn, const unsigned char *inbuf, /* Data received from @@ -1224,63 +1217,6 @@ static CURLcode telrcv(struct Curl_easy *data, return CURLE_OK; } -/* Escape and send a telnet data block */ -static CURLcode send_telnet_data(struct Curl_easy *data, - struct TELNET *tn, - char *buffer, ssize_t nread) -{ - size_t i, outlen; - unsigned char *outbuf; - CURLcode result = CURLE_OK; - size_t bytes_written; - size_t total_written = 0; - struct connectdata *conn = data->conn; - - DEBUGASSERT(tn); - DEBUGASSERT(nread > 0); - if(nread < 0) - return CURLE_TOO_LARGE; - - if(memchr(buffer, CURL_IAC, nread)) { - /* only use the escape buffer when necessary */ - curlx_dyn_reset(&tn->out); - - for(i = 0; i < (size_t)nread && !result; i++) { - result = curlx_dyn_addn(&tn->out, &buffer[i], 1); - if(!result && ((unsigned char)buffer[i] == CURL_IAC)) - /* IAC is FF in hex */ - result = curlx_dyn_addn(&tn->out, "\xff", 1); - } - - outlen = curlx_dyn_len(&tn->out); - outbuf = curlx_dyn_uptr(&tn->out); - } - else { - outlen = (size_t)nread; - outbuf = (unsigned char *)buffer; - } - while(!result && total_written < outlen) { - /* Make sure socket is writable to avoid EWOULDBLOCK condition */ - struct pollfd pfd[1]; - pfd[0].fd = conn->sock[FIRSTSOCKET]; - pfd[0].events = POLLOUT; - switch(Curl_poll(pfd, 1, -1)) { - case -1: /* error, abort writing */ - case 0: /* timeout (will never happen) */ - result = CURLE_SEND_ERROR; - break; - default: /* write! */ - bytes_written = 0; - result = Curl_xfer_send(data, outbuf + total_written, - outlen - total_written, FALSE, &bytes_written); - total_written += bytes_written; - break; - } - } - - return result; -} - static CURLcode telnet_done(struct Curl_easy *data, CURLcode status, bool premature) { @@ -1630,4 +1566,33 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) return result; } -#endif + +/* + * TELNET protocol handler. + */ +const struct Curl_handler Curl_handler_telnet = { + "telnet", /* scheme */ + ZERO_NULL, /* setup_connection */ + telnet_do, /* do_it */ + telnet_done, /* done */ + ZERO_NULL, /* do_more */ + ZERO_NULL, /* connect_it */ + ZERO_NULL, /* connecting */ + ZERO_NULL, /* doing */ + ZERO_NULL, /* proto_pollset */ + ZERO_NULL, /* doing_pollset */ + ZERO_NULL, /* domore_pollset */ + ZERO_NULL, /* perform_pollset */ + ZERO_NULL, /* disconnect */ + ZERO_NULL, /* write_resp */ + ZERO_NULL, /* write_resp_hd */ + ZERO_NULL, /* connection_check */ + ZERO_NULL, /* attach connection */ + ZERO_NULL, /* follow */ + PORT_TELNET, /* defport */ + CURLPROTO_TELNET, /* protocol */ + CURLPROTO_TELNET, /* family */ + PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ +}; + +#endif /* !CURL_DISABLE_TELNET */