From 657d43f453ffa4360d8716c49006bdd3297f86b4 Mon Sep 17 00:00:00 2001 From: piaip Date: Sun, 7 Jun 2009 16:02:40 +0000 Subject: * add client code detection to tunnel mode * refine telnet library to support write customization git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4517 63ad8ddf-47c3-0310-b6dd-a9e9d9715204 --- common/sys/telnet.c | 79 ++++++++++++++++++++++++++++++++++++----------------- include/cmsys.h | 17 ++++++++---- include/logind.h | 4 +++ mbbsd/mbbsd.c | 6 ++++ mbbsd/telnet.c | 3 +- 5 files changed, 78 insertions(+), 31 deletions(-) diff --git a/common/sys/telnet.c b/common/sys/telnet.c index 2f462867..ddb3de07 100644 --- a/common/sys/telnet.c +++ b/common/sys/telnet.c @@ -1,6 +1,9 @@ /* * piaip's simplified implementation of TELNET protocol + * Copyright (c) 2005-2009 Hung-Te Lin + * Improved by Kuang 2009 */ + #include #include #include @@ -15,6 +18,7 @@ #include "cmsys.h" static unsigned int telnet_handler(TelnetCtx *ctx, unsigned char c) ; +static void telnet_write (TelnetCtx *ctx, const void *buf, size_t nbytes); enum TELNET_IAC_STATES { IAC_NONE, @@ -25,7 +29,6 @@ enum TELNET_IAC_STATES { IAC_ERROR }; - /* We don't reply to most commands, so this maxlen can be minimal. * Warning: if you want to support ENV passing or other long commands, * remember to increase this value. Howver, some poorly implemented @@ -38,10 +41,17 @@ TelnetCtx *telnet_create_contex(void) return (TelnetCtx*) malloc(sizeof(TelnetCtx)); } +void telnet_free_context(TelnetCtx* ctx) +{ + free(ctx); +} + void telnet_ctx_init(TelnetCtx *ctx, const struct TelnetCallback *callback, int fd) { memset(ctx, 0, sizeof(TelnetCtx)); + // callback structure must be provided. + assert(callback); ctx->callback = callback; ctx->fd = fd; } @@ -51,6 +61,16 @@ void telnet_ctx_set_cc_arg(TelnetCtx *ctx, void *cc_arg) ctx->cc_arg = cc_arg; } +void telnet_ctx_set_write_arg(TelnetCtx *ctx, void *write_arg) +{ + ctx->write_arg = write_arg; +} + +void telnet_ctx_set_resize_arg(TelnetCtx *ctx, void *resize_arg) +{ + ctx->resize_arg = resize_arg; +} + /* We are the boss. We don't respect to client. * It's client's responsibility to follow us. * Please write these codes in i-dont-care opt handlers. @@ -74,9 +94,9 @@ static const char telnet_init_cmds[] = { IAC, DO, TELOPT_BINARY, }; -void telnet_send_init_cmds(int fd) +void telnet_ctx_send_init_cmds(TelnetCtx *ctx) { - write(fd, telnet_init_cmds, sizeof(telnet_init_cmds)); + telnet_write(ctx, telnet_init_cmds, sizeof(telnet_init_cmds)); } ssize_t telnet_process(TelnetCtx *ctx, unsigned char *buf, ssize_t size) @@ -106,6 +126,15 @@ ssize_t telnet_process(TelnetCtx *ctx, unsigned char *buf, ssize_t size) extern unsigned char fakeEscape; #endif // DBG_OUTRPT +static void +telnet_write (TelnetCtx *ctx, const void *buf, size_t nbytes) +{ + if (ctx->callback->write_data) + ctx->callback->write_data(ctx->write_arg, ctx->fd, buf, nbytes); + else + write(ctx->fd, buf, nbytes); +} + /* input: raw character * output: telnet command if c was handled, otherwise zero. */ @@ -150,10 +179,10 @@ telnet_handler(TelnetCtx *ctx, unsigned char c) #if 0 // def DEBUG { int cx = c; /* to make compiler happy */ - write(ctx->fd, "-", 1); + telnet_write(ctx, "-", 1); if(TELCMD_OK(cx)) - write(ctx->fd, TELCMD(c), strlen(TELCMD(c))); - write(ctx->fd, " ", 1); + telnet_write(ctx, TELCMD(c), strlen(TELCMD(c))); + telnet_write(ctx, " ", 1); } #endif ctx->iac_state = IAC_NONE; /* by default we restore state. */ @@ -192,18 +221,18 @@ telnet_handler(TelnetCtx *ctx, unsigned char c) case AYT: /* are you there */ { #if 0 - const char *alive = "I'm still alive, loading: "; - char buf[STRLEN]; - - /* respond as fast as we can */ - write(ctx->fd, alive, strlen(alive)); - cpuload(buf); - write(ctx->fd, buf, strlen(buf)); - write(ctx->fd, "\r\n", 2); + const char *alive = " I'm still alive, loading: "; + char buf[STRLEN]; + + /* respond as fast as we can */ + telnet_write(ctx, alive, strlen(alive)); + cpuload(buf); + telnet_write(ctx, buf, strlen(buf)); + telnet_write(ctx, "\r\n", 2); #else - const char *alive = "I'm still alive\r\n"; - /* respond as fast as we can */ - write(ctx->fd, alive, strlen(alive)); + const char *alive = " I'm still alive.\r\n"; + /* respond as fast as we can */ + telnet_write(ctx, alive, strlen(alive)); #endif } return NOP; @@ -229,10 +258,10 @@ telnet_handler(TelnetCtx *ctx, unsigned char c) case IAC_WAIT_OPT: #if 0 // def DEBUG - write(ctx->fd, "-", 1); + telnet_write(ctx, "-", 1); if(TELOPT_OK(c)) - write(ctx->fd, TELOPT(c), strlen(TELOPT(c))); - write(ctx->fd, " ", 1); + telnet_write(ctx, TELOPT(c), strlen(TELOPT(c))); + telnet_write(ctx, " ", 1); #endif ctx->iac_state = IAC_NONE; /* @@ -245,7 +274,7 @@ telnet_handler(TelnetCtx *ctx, unsigned char c) */ switch(c) { /* i-dont-care: i don't care about what client is. - * these should be clamed in init and + * these should be claimed in init and * client must follow me. */ case TELOPT_TTYPE: /* termtype or line. */ case TELOPT_NAWS: /* resize terminal */ @@ -265,7 +294,7 @@ telnet_handler(TelnetCtx *ctx, unsigned char c) unsigned char cmd[3] = { IAC, DONT, 0 }; if(ctx->iac_opt_req == DO) cmd[1] = WONT; cmd[2] = c; - write(ctx->fd, cmd, sizeof(cmd)); + telnet_write(ctx, cmd, sizeof(cmd)); } break; } @@ -288,10 +317,10 @@ telnet_handler(TelnetCtx *ctx, unsigned char c) case IAC_PROCESS_OPT: ctx->iac_state = IAC_NONE; #if 0 // def DEBUG - write(ctx->fd, "-", 1); + telnet_write(ctx, "-", 1); if(TELOPT_OK(ctx->iac_buf[0])) - write(ctx->fd, TELOPT(ctx->iac_buf[0]), strlen(TELOPT(ctx->iac_buf[0]))); - write(ctx->fd, " ", 1); + telnet_write(ctx, TELOPT(ctx->iac_buf[0]), strlen(TELOPT(ctx->iac_buf[0]))); + telnet_write(ctx, " ", 1); #endif switch(ctx->iac_buf[0]) { diff --git a/include/cmsys.h b/include/cmsys.h index 863aab3f..6ae2119f 100644 --- a/include/cmsys.h +++ b/include/cmsys.h @@ -178,6 +178,7 @@ extern int Vector_search(const struct Vector *self, const char *name); /* telnet.c */ struct TelnetCallback { + void (*write_data) (void *write_arg, int fd, const void *buf, size_t nbytes); void (*term_resize) (void *resize_arg, int w, int h); void (*update_client_code) (void *cc_arg, unsigned char seq); }; @@ -197,16 +198,22 @@ struct TelnetCtx { const struct TelnetCallback *callback; // callback parameters + void *write_arg; // write_data void *resize_arg; // term_resize void *cc_arg; // update_client_code }; typedef struct TelnetCtx TelnetCtx; -extern TelnetCtx *telnet_create_contex(void); -extern void telnet_ctx_init(TelnetCtx *ctx, const struct TelnetCallback *callback, int fd); -extern void telnet_ctx_set_cc_arg(TelnetCtx *ctx, void *cc_arg); +extern TelnetCtx *telnet_create_context(void); +extern void telnet_free_context (TelnetCtx *ctx); -extern void telnet_send_init_cmds(int fd); -extern ssize_t telnet_process(TelnetCtx *ctx, unsigned char *buf, ssize_t size); +extern void telnet_ctx_init (TelnetCtx *ctx, const struct TelnetCallback *callback, int fd); +extern void telnet_ctx_send_init_cmds(TelnetCtx *ctx); + +extern void telnet_ctx_set_cc_arg (TelnetCtx *ctx, void *cc_arg); +extern void telnet_ctx_set_write_arg (TelnetCtx *ctx, void *cc_arg); +extern void telnet_ctx_set_resize_arg(TelnetCtx *ctx, void *cc_arg); + +extern ssize_t telnet_process (TelnetCtx *ctx, unsigned char *buf, ssize_t size); #endif diff --git a/include/logind.h b/include/logind.h index 0b229faa..493d0c09 100644 --- a/include/logind.h +++ b/include/logind.h @@ -7,9 +7,13 @@ typedef struct login_data { + // size of current structure + size_t cb; + // terminal information int t_lines, t_cols; int encoding; + Fnv32_t client_code; // user authentication char userid[IDLEN+1]; diff --git a/mbbsd/mbbsd.c b/mbbsd/mbbsd.c index ff9188d8..6d86247b 100644 --- a/mbbsd/mbbsd.c +++ b/mbbsd/mbbsd.c @@ -1853,6 +1853,8 @@ tunnel_login(char *argv0, struct ProgramOption *option) towrite(tunnel, &success, sizeof(success)) < sizeof(success)) return 0; + assert(dat.cb == sizeof(dat)); + // optimize connection set_connection_opt(csock); @@ -1880,6 +1882,10 @@ tunnel_login(char *argv0, struct ProgramOption *option) option->term_width = dat.t_cols; option->term_height = dat.t_lines; telnet_init(0); +#ifdef DETECT_CLIENT + telnet_turnoff_client_detect(); + client_code = dat.client_code; // use the client code detected by remote daemon +#endif return 1; } diff --git a/mbbsd/telnet.c b/mbbsd/telnet.c index d60254ac..7cf1fee5 100644 --- a/mbbsd/telnet.c +++ b/mbbsd/telnet.c @@ -20,6 +20,7 @@ telnet_cb_resize_term(void *resize_arg, int w, int h) } const static struct TelnetCallback telnet_callback = { + NULL, telnet_cb_resize_term, #ifdef DETECT_CLIENT telnet_cb_update_client_code, @@ -39,7 +40,7 @@ telnet_init(int do_init_cmd) telnet_ctx_set_cc_arg(ctx, (void*)1); #endif if (do_init_cmd) - telnet_send_init_cmds(fd); + telnet_ctx_send_init_cmds(ctx); } /* tty_read -- cgit v1.2.3