#endif
#include "urldata.h"
+#include "url.h"
#include <curl/curl.h>
#include "transfer.h"
#include "sendf.h"
#define printoption(a,b,c,d) Curl_nop_stmt
#endif
-static
-CURLcode telrcv(struct Curl_easy *data,
- const unsigned char *inbuf, /* Data received from socket */
- ssize_t count); /* Number of bytes received */
-
-#ifndef CURL_DISABLE_VERBOSE_STRINGS
-static void printoption(struct Curl_easy *data,
- const char *direction,
- int cmd, int option);
-#endif
-
-static void negotiate(struct Curl_easy *data);
-static void send_negotiation(struct Curl_easy *data, int cmd, int option);
-static void set_local_option(struct Curl_easy *data,
- int option, int newstate);
-static void set_remote_option(struct Curl_easy *data,
- int option, int newstate);
-
-static void printsub(struct Curl_easy *data,
- int direction, unsigned char *pointer,
- size_t length);
-static void suboption(struct Curl_easy *data);
-static void sendsuboption(struct Curl_easy *data, 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,
- char *buffer, ssize_t nread);
-
/* For negotiation compliant to RFC 1143 */
#define CURL_NO 0
#define CURL_YES 1
#define CURL_EMPTY 0
#define CURL_OPPOSITE 1
+
+/* meta key for storing protocol meta at easy handle */
+#define CURL_META_TELNET_EASY "meta:proto:telnet:easy"
+
/*
* Telnet receiver states for fsm
*/
};
+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
+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 void 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.
*/
};
+static void telnet_easy_dtor(void *key, size_t klen, void *entry)
+{
+ struct TELNET *tn = entry;
+ (void)key;
+ (void)klen;
+ curl_slist_free_all(tn->telnet_vars);
+ curlx_dyn_free(&tn->out);
+ free(tn);
+}
+
static
CURLcode init_telnet(struct Curl_easy *data)
{
return CURLE_OUT_OF_MEMORY;
curlx_dyn_init(&tn->out, 0xffff);
- data->req.p.telnet = tn; /* make us known */
tn->telrcv_state = CURL_TS_DATA;
based upon the terminal type information that may have been sent
using the TERMINAL TYPE Telnet option). */
tn->subnegotiation[CURL_TELOPT_NAWS] = CURL_YES;
- return CURLE_OK;
+
+ return Curl_meta_set(data, CURL_META_TELNET_EASY, tn, telnet_easy_dtor);
}
-static void negotiate(struct Curl_easy *data)
+static void telnet_negotiate(struct Curl_easy *data, struct TELNET *tn)
{
int i;
- struct TELNET *tn = data->req.p.telnet;
for(i = 0; i < CURL_NTELOPTS; i++) {
if(i == CURL_TELOPT_ECHO)
continue;
if(tn->us_preferred[i] == CURL_YES)
- set_local_option(data, i, CURL_YES);
+ set_local_option(data, tn, i, CURL_YES);
if(tn->him_preferred[i] == CURL_YES)
- set_remote_option(data, i, CURL_YES);
+ set_remote_option(data, tn, i, CURL_YES);
}
}
}
static
-void set_remote_option(struct Curl_easy *data, int option, int newstate)
+void set_remote_option(struct Curl_easy *data, struct TELNET *tn,
+ int option, int newstate)
{
- struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->him[option]) {
case CURL_NO:
}
static
-void rec_will(struct Curl_easy *data, int option)
+void rec_will(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
if(tn->him_preferred[option] == CURL_YES) {
}
static
-void rec_wont(struct Curl_easy *data, int option)
+void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->him[option]) {
case CURL_NO:
/* Already disabled */
}
static void
-set_local_option(struct Curl_easy *data, int option, int newstate)
+set_local_option(struct Curl_easy *data, struct TELNET *tn,
+ int option, int newstate)
{
- struct TELNET *tn = data->req.p.telnet;
if(newstate == CURL_YES) {
switch(tn->us[option]) {
case CURL_NO:
}
static
-void rec_do(struct Curl_easy *data, int option)
+void rec_do(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
if(tn->us_preferred[option] == CURL_YES) {
send_negotiation(data, CURL_WILL, option);
if(tn->subnegotiation[option] == CURL_YES)
/* transmission of data option */
- sendsuboption(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, option);
+ sendsuboption(data, tn, option);
}
else
send_negotiation(data, CURL_WONT, option);
tn->us[option] = CURL_YES;
if(tn->subnegotiation[option] == CURL_YES) {
/* transmission of data option */
- sendsuboption(data, option);
+ sendsuboption(data, tn, option);
}
break;
case CURL_OPPOSITE:
}
static
-void rec_dont(struct Curl_easy *data, int option)
+void rec_dont(struct Curl_easy *data, struct TELNET *tn, int option)
{
- struct TELNET *tn = data->req.p.telnet;
switch(tn->us[option]) {
case CURL_NO:
/* Already disabled */
return FALSE;
}
-static CURLcode check_telnet_options(struct Curl_easy *data)
+static CURLcode check_telnet_options(struct Curl_easy *data,
+ struct TELNET *tn)
{
struct curl_slist *head;
struct curl_slist *beg;
- struct TELNET *tn = data->req.p.telnet;
CURLcode result = CURLE_OK;
/* Add the username as an environment variable if it
* side.
*/
-static void suboption(struct Curl_easy *data)
+static void suboption(struct Curl_easy *data, struct TELNET *tn)
{
struct curl_slist *v;
unsigned char temp[2048];
ssize_t bytes_written;
size_t len;
int err;
- struct TELNET *tn = data->req.p.telnet;
struct connectdata *conn = data->conn;
printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2);
* Send suboption information to the server side.
*/
-static void sendsuboption(struct Curl_easy *data, int option)
+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 TELNET *tn = data->req.p.telnet;
struct connectdata *conn = data->conn;
switch(option) {
}
/* ... then the window size with the send_telnet_data() function
to deal with 0xFF cases ... */
- send_telnet_data(data, (char *)tn->subbuffer + 3, 4);
+ 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) {
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 */
{
CURLcode result;
int in = 0;
int startwrite = -1;
- struct TELNET *tn = data->req.p.telnet;
#define startskipping() \
if(startwrite >= 0) { \
case CURL_TS_WILL:
printoption(data, "RCVD", CURL_WILL, c);
tn->please_negotiate = 1;
- rec_will(data, c);
+ rec_will(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_WONT:
printoption(data, "RCVD", CURL_WONT, c);
tn->please_negotiate = 1;
- rec_wont(data, c);
+ rec_wont(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DO:
printoption(data, "RCVD", CURL_DO, c);
tn->please_negotiate = 1;
- rec_do(data, c);
+ rec_do(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
case CURL_TS_DONT:
printoption(data, "RCVD", CURL_DONT, c);
tn->please_negotiate = 1;
- rec_dont(data, c);
+ rec_dont(data, tn, c);
tn->telrcv_state = CURL_TS_DATA;
break;
CURL_SB_TERM(tn);
printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c);
- suboption(data); /* handle sub-option */
+ suboption(data, tn); /* handle sub-option */
tn->telrcv_state = CURL_TS_IAC;
goto process_iac;
}
CURL_SB_ACCUM(tn, CURL_SE);
tn->subpointer -= 2;
CURL_SB_TERM(tn);
- suboption(data); /* handle sub-option */
+ suboption(data, tn); /* handle sub-option */
tn->telrcv_state = CURL_TS_DATA;
}
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;
size_t bytes_written;
size_t total_written = 0;
struct connectdata *conn = data->conn;
- struct TELNET *tn = data->req.p.telnet;
DEBUGASSERT(tn);
DEBUGASSERT(nread > 0);
static CURLcode telnet_done(struct Curl_easy *data,
CURLcode status, bool premature)
{
- struct TELNET *tn = data->req.p.telnet;
(void)status; /* unused */
(void)premature; /* not used */
-
- if(!tn)
- return CURLE_OK;
-
- curl_slist_free_all(tn->telnet_vars);
- tn->telnet_vars = NULL;
- curlx_dyn_free(&tn->out);
+ Curl_meta_remove(data, CURL_META_TELNET_EASY);
return CURLE_OK;
}
if(result)
return result;
- tn = data->req.p.telnet;
+ tn = Curl_meta_get(data, CURL_META_TELNET_EASY);
+ if(!tn)
+ return CURLE_FAILED_INIT;
- result = check_telnet_options(data);
+ result = check_telnet_options(data, tn);
if(result)
return result;
}
}
- result = send_telnet_data(data, buffer, readfile_read);
+ result = send_telnet_data(data, tn, buffer, readfile_read);
if(result) {
keepon = FALSE;
break;
break;
}
- result = send_telnet_data(data, buffer, readfile_read);
+ result = send_telnet_data(data, tn, buffer, readfile_read);
if(result) {
keepon = FALSE;
break;
break;
}
- result = telrcv(data, (unsigned char *) buffer, nread);
+ result = telrcv(data, tn, (unsigned char *) buffer, nread);
if(result) {
keepon = FALSE;
break;
otherwise do not. We do not want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(data);
+ telnet_negotiate(data, tn);
tn->already_negotiated = 1;
}
}
total_dl += nread;
result = Curl_pgrsSetDownloadCounter(data, total_dl);
if(!result)
- result = telrcv(data, (unsigned char *)buffer, nread);
+ result = telrcv(data, tn, (unsigned char *)buffer, nread);
if(result) {
keepon = FALSE;
break;
otherwise do not. We do not want to speak telnet with
non-telnet servers, like POP or SMTP. */
if(tn->please_negotiate && !tn->already_negotiated) {
- negotiate(data);
+ telnet_negotiate(data, tn);
tn->already_negotiated = 1;
}
}
}
if(nread > 0) {
- result = send_telnet_data(data, buffer, nread);
+ result = send_telnet_data(data, tn, buffer, nread);
if(result) {
keepon = FALSE;
break;