From 1223da7d1010c9a322f7e9600104598b14f9cb9d Mon Sep 17 00:00:00 2001 From: rswindell <> Date: Sat, 27 Aug 2011 21:22:07 +0000 Subject: [PATCH] request_telnet_opt() can now (optionally) block with timeout for the ack. telnet_gate() now enables the telnet command pass-through after negotiating necessary options. This doesn't quite fix the problem reported with telgating to nethack.alt.org, but it's a step in the right direction. --- src/sbbs3/main.cpp | 24 ++++++++++++++++++------ src/sbbs3/sbbs.h | 4 +++- src/sbbs3/telgate.cpp | 14 +++++++------- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp index 93e689ba13..99433cddd6 100644 --- a/src/sbbs3/main.cpp +++ b/src/sbbs3/main.cpp @@ -1311,13 +1311,16 @@ static BYTE* telnet_interpret(sbbs_t* sbbs, BYTE* inbuf, int inlen, if(!(sbbs->telnet_mode&TELNET_MODE_GATE)) { if(command==TELNET_DO || command==TELNET_DONT) { /* local options */ - if(sbbs->telnet_local_option[option]!=command) { + if(sbbs->telnet_local_option[option]==command) + SetEvent(sbbs->telnet_ack_event); + else { sbbs->telnet_local_option[option]=command; sbbs->send_telnet_cmd(telnet_opt_ack(command),option); } } else { /* WILL/WONT (remote options) */ - if(sbbs->telnet_remote_option[option]!=command) { - + if(sbbs->telnet_remote_option[option]==command) + SetEvent(sbbs->telnet_ack_event); + else { switch(option) { case TELNET_BINARY_TX: case TELNET_ECHO: @@ -1413,18 +1416,23 @@ void sbbs_t::send_telnet_cmd(uchar cmd, uchar opt) } } -void sbbs_t::request_telnet_opt(uchar cmd, uchar opt) +bool sbbs_t::request_telnet_opt(uchar cmd, uchar opt, unsigned waitforack) { if(cmd==TELNET_DO || cmd==TELNET_DONT) { /* remote option */ if(telnet_remote_option[opt]==telnet_opt_ack(cmd)) - return; /* already set in this mode, do nothing */ + return true; /* already set in this mode, do nothing */ telnet_remote_option[opt]=telnet_opt_ack(cmd); } else { /* local option */ if(telnet_local_option[opt]==telnet_opt_ack(cmd)) - return; /* already set in this mode, do nothing */ + return true; /* already set in this mode, do nothing */ telnet_local_option[opt]=telnet_opt_ack(cmd); } + if(waitforack) + ResetEvent(telnet_ack_event); send_telnet_cmd(cmd,opt); + if(waitforack) + return WaitForEvent(telnet_ack_event, waitforack)==WAIT_OBJECT_0; + return true; } void input_thread(void *arg) @@ -2880,6 +2888,7 @@ sbbs_t::sbbs_t(ushort node_num, DWORD addr, const char* name, SOCKET sd, telnet_cmdlen=0; telnet_mode=0; telnet_last_rxch=0; + telnet_ack_event=CreateEvent(NULL, /* Manual Reset: */FALSE,/* InitialState */FALSE,NULL); sys_status=lncntr=tos=criterrs=slcnt=0L; column=0; @@ -3267,6 +3276,9 @@ sbbs_t::~sbbs_t() if(!output_thread_running) RingBufDispose(&outbuf); + if(telnet_ack_event!=NULL) + CloseEvent(telnet_ack_event); + /* Close all open files */ if(nodefile!=-1) { close(nodefile); diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index 1d5a92ee73..6afa8aeefd 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -135,6 +135,7 @@ extern int thread_suid_broken; /* NPTL is no longer broken */ #include "filewrap.h" #include "datewrap.h" #include "sockwrap.h" +#include "eventwrap.h" #include "link_list.h" #include "msg_queue.h" #include "xpdatetime.h" @@ -209,7 +210,7 @@ public: uchar telnet_local_option[0x100]; uchar telnet_remote_option[0x100]; void send_telnet_cmd(uchar cmd, uchar opt); - void request_telnet_opt(uchar cmd, uchar opt); + bool request_telnet_opt(uchar cmd, uchar opt, unsigned waitforack=0); uchar telnet_cmd[64]; uint telnet_cmdlen; @@ -217,6 +218,7 @@ public: uchar telnet_last_rxch; char telnet_location[128]; char terminal[TELNET_TERM_MAXLEN+1]; + xpevent_t telnet_ack_event; time_t event_time; // Time of next exclusive event char* event_code; // Internal code of next exclusive event diff --git a/src/sbbs3/telgate.cpp b/src/sbbs3/telgate.cpp index 09d7f1a758..e427ae57d6 100644 --- a/src/sbbs3/telgate.cpp +++ b/src/sbbs3/telgate.cpp @@ -8,7 +8,7 @@ * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 Rob Swindell - http://www.synchro.net/copyright.html * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * @@ -115,9 +115,6 @@ void sbbs_t::telnet_gate(char* destaddr, ulong mode) ,mode&TG_RLOGIN ? "RLogin" : "Telnet" ,destaddr,port,remote_socket); - if(mode&(TG_PASSTHRU|TG_RLOGIN)) - telnet_mode|=TELNET_MODE_GATE; // Pass-through telnet commands - if(!(mode&TG_CTRLKEYS)) console|=CON_RAW_IN; @@ -136,10 +133,13 @@ void sbbs_t::telnet_gate(char* destaddr, ulong mode) /* This is required for gating to Unix telnetd */ if(mode&TG_NOTERMTYPE) - request_telnet_opt(TELNET_DONT,TELNET_TERM_TYPE); // Re-negotiation of terminal type + request_telnet_opt(TELNET_DONT,TELNET_TERM_TYPE, 3000); // Re-negotiation of terminal type /* Text/NVT mode by default */ - request_telnet_opt(TELNET_DONT,TELNET_BINARY_TX); + request_telnet_opt(TELNET_DONT,TELNET_BINARY_TX, 3000); + + if(mode&(TG_PASSTHRU|TG_RLOGIN)) + telnet_mode|=TELNET_MODE_GATE; // Pass-through telnet commands while(online) { if(!(mode&TG_NOCHKTIME)) @@ -250,7 +250,7 @@ void sbbs_t::telnet_gate(char* destaddr, ulong mode) p=dump; for(int i=0;i<rd;i++) p+=sprintf(p,"%u ",buf[i]); - lprintf(LOG_DEBUG,"Node %d Telnet cmd from remote: %s", cfg.node_num, dump); + lprintf(LOG_DEBUG,"Node %d Telnet cmd from server: %s", cfg.node_num, dump); } #endif RingBufWrite(&outbuf,buf,rd); -- GitLab