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
This commit is contained in:
Viktor Szakats 2026-01-13 15:27:36 +01:00
parent 060e479a19
commit 7d2c65e6ee
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
5 changed files with 683 additions and 752 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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
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;
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 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,6 +320,95 @@ static void set_remote_option(struct Curl_easy *data, struct TELNET *tn,
}
}
static void set_local_option(struct Curl_easy *data, struct TELNET *tn,
int option, int newstate)
{
if(newstate == CURL_YES) {
switch(tn->us[option]) {
case CURL_NO:
tn->us[option] = CURL_WANTYES;
send_negotiation(data, CURL_WILL, option);
break;
case CURL_YES:
/* Already enabled */
break;
case CURL_WANTNO:
switch(tn->usq[option]) {
case CURL_EMPTY:
/* Already negotiating for CURL_YES, queue the request */
tn->usq[option] = CURL_OPPOSITE;
break;
case CURL_OPPOSITE:
/* Error: already queued an enable request */
break;
}
break;
case CURL_WANTYES:
switch(tn->usq[option]) {
case CURL_EMPTY:
/* Error: already negotiating for enable */
break;
case CURL_OPPOSITE:
tn->usq[option] = CURL_EMPTY;
break;
}
break;
}
}
else { /* NO */
switch(tn->us[option]) {
case CURL_NO:
/* Already disabled */
break;
case CURL_YES:
tn->us[option] = CURL_WANTNO;
send_negotiation(data, CURL_WONT, option);
break;
case CURL_WANTNO:
switch(tn->usq[option]) {
case CURL_EMPTY:
/* Already negotiating for NO */
break;
case CURL_OPPOSITE:
tn->usq[option] = CURL_EMPTY;
break;
}
break;
case CURL_WANTYES:
switch(tn->usq[option]) {
case CURL_EMPTY:
tn->usq[option] = CURL_OPPOSITE;
break;
case CURL_OPPOSITE:
break;
}
break;
}
}
}
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);
}
}
static void rec_will(struct Curl_easy *data, struct TELNET *tn, int option)
{
switch(tn->him[option]) {
@ -486,177 +495,6 @@ static void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option)
}
}
static void set_local_option(struct Curl_easy *data, struct TELNET *tn,
int option, int newstate)
{
if(newstate == CURL_YES) {
switch(tn->us[option]) {
case CURL_NO:
tn->us[option] = CURL_WANTYES;
send_negotiation(data, CURL_WILL, option);
break;
case CURL_YES:
/* Already enabled */
break;
case CURL_WANTNO:
switch(tn->usq[option]) {
case CURL_EMPTY:
/* Already negotiating for CURL_YES, queue the request */
tn->usq[option] = CURL_OPPOSITE;
break;
case CURL_OPPOSITE:
/* Error: already queued an enable request */
break;
}
break;
case CURL_WANTYES:
switch(tn->usq[option]) {
case CURL_EMPTY:
/* Error: already negotiating for enable */
break;
case CURL_OPPOSITE:
tn->usq[option] = CURL_EMPTY;
break;
}
break;
}
}
else { /* NO */
switch(tn->us[option]) {
case CURL_NO:
/* Already disabled */
break;
case CURL_YES:
tn->us[option] = CURL_WANTNO;
send_negotiation(data, CURL_WONT, option);
break;
case CURL_WANTNO:
switch(tn->usq[option]) {
case CURL_EMPTY:
/* Already negotiating for NO */
break;
case CURL_OPPOSITE:
tn->usq[option] = CURL_EMPTY;
break;
}
break;
case CURL_WANTYES:
switch(tn->usq[option]) {
case CURL_EMPTY:
tn->usq[option] = CURL_OPPOSITE;
break;
case CURL_OPPOSITE:
break;
}
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;
}
}
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;
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;
}
}
static void printsub(struct Curl_easy *data,
int direction, /* '<' or '>' */
unsigned char *pointer, /* where suboption data is */
@ -770,6 +608,220 @@ static void printsub(struct Curl_easy *data,
}
}
/* 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;
}
}
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;
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;
}
}
static bool str_is_nonascii(const char *str)
{
char c;
@ -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 */