void request_telnet_opt(uchar cmd, uchar opt) { 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 */ 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 */ telnet_local_option[opt]=telnet_opt_ack(cmd); } send_telnet_cmd(cmd,opt); }
char sbbs_t::getkey(long mode) { char ch,coldkey,c=0,spin=sbbs_random(5); time_t last_telnet_cmd=0; if(!online || !input_thread_running) { YIELD(); // just in case someone is looping on getkey() when they shouldn't return(0); } sys_status&=~SS_ABORT; if((sys_status&SS_USERON || action==NODE_DFLT) && !(mode&(K_GETSTR|K_NOSPIN))) mode|=(useron.misc&SPIN); lncntr=0; timeout=time(NULL); if(mode&K_SPIN) outchar(' '); do { if(sys_status&SS_ABORT) { if(mode&K_SPIN) /* back space once if on spinning cursor */ backspace(); return(0); } if(mode&K_SPIN) { if(useron.misc&NO_EXASCII) { switch(c++) { case 0: outchar(BS); outchar('|'); break; case 1: outchar(BS); outchar('/'); break; case 2: outchar(BS); outchar('-'); break; case 3: outchar(BS); outchar('\\'); c=0; break; } } else { switch(spin) { case 0: switch(c++) { case 0: outchar(BS); outchar('³'); break; case 1: outchar(BS); outchar('/'); break; case 2: outchar(BS); outchar('Ä'); break; case 3: outchar(BS); outchar('\\'); c=0; break; } break; case 1: switch(c++) { case 0: outchar(BS); outchar('°'); break; case 1: outchar(BS); outchar('±'); break; case 2: outchar(BS); outchar('²'); break; case 3: outchar(BS); outchar('Û'); break; case 4: outchar(BS); outchar('²'); break; case 5: outchar(BS); outchar('±'); c=0; break; } break; case 2: switch(c++) { case 0: outchar(BS); outchar('-'); break; case 1: outchar(BS); outchar('='); break; case 2: outchar(BS); outchar('ð'); break; case 3: outchar(BS); outchar('='); c=0; break; } break; case 3: switch(c++) { case 0: outchar(BS); outchar('Ú'); break; case 1: outchar(BS); outchar('À'); break; case 2: outchar(BS); outchar('Ù'); break; case 3: outchar(BS); outchar('¿'); c=0; break; } break; case 4: switch(c++) { case 0: outchar(BS); outchar('Ü'); break; case 1: outchar(BS); outchar('Þ'); break; case 2: outchar(BS); outchar('ß'); break; case 3: outchar(BS); outchar('Ý'); c=0; break; } break; } } } ch=inkey(mode,mode&K_SPIN ? 250:1000); if(sys_status&SS_ABORT) return(0); now=time(NULL); if(ch) { if(mode&K_NUMBER && isprint(ch) && !isdigit(ch)) continue; if(mode&K_ALPHA && isprint(ch) && !isalpha(ch)) continue; if(mode&K_NOEXASC && ch&0x80) continue; if(mode&K_SPIN) backspace(); if(mode&K_COLD && ch>' ' && useron.misc&COLDKEYS) { if(mode&K_UPPER) outchar(toupper(ch)); else outchar(ch); while((coldkey=inkey(mode,1000))==0 && online && !(sys_status&SS_ABORT)) ; backspace(); if(coldkey==BS || coldkey==DEL) continue; if(coldkey>' ') ungetkey(coldkey); } if(mode&K_UPPER) return(toupper(ch)); return(ch); } if(sys_status&SS_USERON && !(sys_status&SS_LCHAT)) gettimeleft(); else if(online && now-answertime>SEC_LOGON && !(sys_status&SS_LCHAT)) { console&=~(CON_R_ECHOX|CON_L_ECHOX); console|=(CON_R_ECHO|CON_L_ECHO); bputs(text[TakenTooLongToLogon]); hangup(); } if(sys_status&SS_USERON && online && (timeleft/60)<(5-timeleft_warn) && !SYSOP && !(sys_status&SS_LCHAT)) { timeleft_warn=5-(timeleft/60); SAVELINE; attr(LIGHTGRAY); bprintf(text[OnlyXminutesLeft] ,((ushort)timeleft/60)+1,(timeleft/60) ? "s" : nulstr); RESTORELINE; } if(!(startup->options&BBS_OPT_NO_TELNET_GA) && now!=last_telnet_cmd && now-timeout>=60 && !((now-timeout)%60)) { // Let's make sure the socket is up // Sending will trigger a socket d/c detection send_telnet_cmd(TELNET_GA,0); last_telnet_cmd=now; } if(online==ON_REMOTE && !(console&CON_NO_INACT) && now-timeout>=cfg.sec_warn) { /* warning */ if(sys_status&SS_USERON && cfg.sec_warn!=cfg.sec_hangup) { SAVELINE; bputs(text[AreYouThere]); } else bputs("\7\7"); while(!inkey(K_NONE,100) && online && now-timeout>=cfg.sec_warn) { now=time(NULL); if(now-timeout>=cfg.sec_hangup) { if(online==ON_REMOTE) { console|=CON_R_ECHO; console&=~CON_R_ECHOX; } bputs(text[CallBackWhenYoureThere]); logline(nulstr,"Inactive"); hangup(); return(0); } } if(sys_status&SS_USERON && cfg.sec_warn!=cfg.sec_hangup) { bputs("\r\1n\1>"); RESTORELINE; } timeout=now; } } while(online); return(0); }
BOOL handle_call(void) { BYTE buf[4096]; BYTE telnet_buf[sizeof(buf)]; BYTE* p; int result; int rd; int wr; fd_set socket_set; struct timeval tv = {0, 0}; bytes_sent=0; bytes_received=0; call_terminated=FALSE; /* Reset Telnet state information */ telnet_cmdlen=0; ZERO_VAR(telnet_local_option); ZERO_VAR(telnet_remote_option); if(telnet && telnet_advertise_cid && (cid_number[0] || cid_name[0])) /* advertise the ability to send our location */ send_telnet_cmd(TELNET_WILL, TELNET_SEND_LOCATION); input_thread_terminated=FALSE; _beginthread(input_thread, 0, NULL); while(!terminated) { if(!dcd_ignore && !carrier_detect(com_handle)) { lprintf(LOG_WARNING,"Loss of Carrier Detect (DCD) detected"); break; } #if 0 /* single-threaded mode: */ if(comReadByte(com_handle, &ch)) { lprintf(LOG_DEBUG,"read byte: %c", ch); send(sock, &ch, sizeof(ch), 0); } #endif FD_ZERO(&socket_set); FD_SET(sock,&socket_set); if((result = select(sock+1,&socket_set,NULL,NULL,&tv)) == 0) { YIELD(); continue; } if(result == SOCKET_ERROR) { lprintf(LOG_ERR,"SOCKET ERROR %u on select", ERROR_VALUE); break; } rd=recv(sock,buf,sizeof(buf),0); if(rd < 1) { if(rd==0) { lprintf(LOG_WARNING,"Socket Disconnected"); break; } if(ERROR_VALUE == EAGAIN) continue; else if(ERROR_VALUE == ENOTSOCK) lprintf(LOG_WARNING,"Socket closed by peer on receive"); else if(ERROR_VALUE==ECONNRESET) lprintf(LOG_WARNING,"Connection reset by peer on receive"); else if(ERROR_VALUE==ESHUTDOWN) lprintf(LOG_WARNING,"Socket shutdown on receive"); else if(ERROR_VALUE==ECONNABORTED) lprintf(LOG_WARNING,"Connection aborted by peer on receive"); else lprintf(LOG_ERR,"SOCKET RECV ERROR %d",ERROR_VALUE); break; } if(telnet) p=telnet_interpret(buf,rd,telnet_buf,&rd); else p=buf; if((wr=comWriteBuf(com_handle, p, rd)) != COM_ERROR) bytes_sent += wr; } call_terminated=TRUE; /* terminate input_thread() */ while(!input_thread_terminated) { YIELD(); } lprintf(LOG_INFO,"Bytes sent-to, received-from COM Port: %lu, %lu" ,bytes_sent, bytes_received); return TRUE; }
BYTE* telnet_interpret(BYTE* inbuf, int inlen, BYTE* outbuf, int *outlen) { BYTE command; BYTE option; BYTE* first_iac; int i; if(inlen<1) { *outlen=0; return(inbuf); /* no length? No interpretation */ } first_iac=(BYTE*)memchr(inbuf, TELNET_IAC, inlen); if(!telnet_cmdlen && first_iac==NULL) { *outlen=inlen; return(inbuf); /* no interpretation needed */ } if(first_iac!=NULL) { *outlen=first_iac-inbuf; memcpy(outbuf, inbuf, *outlen); } else *outlen=0; for(i=*outlen;i<inlen;i++) { if(inbuf[i]==TELNET_IAC && telnet_cmdlen==1) { /* escaped 255 */ telnet_cmdlen=0; outbuf[(*outlen)++]=TELNET_IAC; continue; } if(inbuf[i]==TELNET_IAC || telnet_cmdlen) { if(telnet_cmdlen<sizeof(telnet_cmd)) telnet_cmd[telnet_cmdlen++]=inbuf[i]; command = telnet_cmd[1]; option = telnet_cmd[2]; if(telnet_cmdlen>=2 && command==TELNET_SB) { if(inbuf[i]==TELNET_SE && telnet_cmd[telnet_cmdlen-2]==TELNET_IAC) { if(debug_telnet) lprintf(LOG_INFO,"RX Telnet sub-negotiation command: %s" ,telnet_opt_desc(option)); /* sub-option terminated */ if(option==TELNET_TERM_TYPE && telnet_cmd[3]==TELNET_TERM_SEND) { BYTE buf[32]; int len=sprintf(buf,"%c%c%c%c%s%c%c" ,TELNET_IAC,TELNET_SB ,TELNET_TERM_TYPE,TELNET_TERM_IS ,termtype ,TELNET_IAC,TELNET_SE); if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: Terminal Type is %s", termtype); sendsocket(sock,buf,len); /* request_telnet_opt(TELNET_WILL, TELNET_TERM_SPEED); */ } else if(option==TELNET_TERM_SPEED && telnet_cmd[3]==TELNET_TERM_SEND) { BYTE buf[32]; int len=sprintf(buf,"%c%c%c%c%s%c%c" ,TELNET_IAC,TELNET_SB ,TELNET_TERM_SPEED,TELNET_TERM_IS ,termspeed ,TELNET_IAC,TELNET_SE); if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: Terminal Speed is %s", termspeed); sendsocket(sock,buf,len); } telnet_cmdlen=0; } } else if(telnet_cmdlen==2 && inbuf[i]<TELNET_WILL) { telnet_cmdlen=0; } else if(telnet_cmdlen>=3) { /* telnet option negotiation */ if(debug_telnet) lprintf(LOG_INFO,"RX Telnet command: %s %s" ,telnet_cmd_desc(command),telnet_opt_desc(option)); if(command==TELNET_DO || command==TELNET_DONT) { /* local options */ if(telnet_local_option[option]!=command) { switch(option) { case TELNET_BINARY_TX: case TELNET_ECHO: case TELNET_TERM_TYPE: case TELNET_TERM_SPEED: case TELNET_SUP_GA: telnet_local_option[option]=command; send_telnet_cmd(telnet_opt_ack(command),option); break; case TELNET_SEND_LOCATION: if(command==TELNET_DO) { BYTE buf[128]; int len=safe_snprintf(buf,sizeof(buf),"%c%c%c%s %s%c%c" ,TELNET_IAC,TELNET_SB ,TELNET_SEND_LOCATION ,cid_number, cid_name ,TELNET_IAC,TELNET_SE); if(debug_telnet) lprintf(LOG_INFO,"TX Telnet command: Location is %s %s", cid_number, cid_name); sendsocket(sock,buf,len); } else send_telnet_cmd(telnet_opt_ack(command),option); break; default: /* unsupported local options */ if(command==TELNET_DO) /* NAK */ send_telnet_cmd(telnet_opt_nak(command),option); break; } } } else { /* WILL/WONT (remote options) */ if(telnet_remote_option[option]!=command) { switch(option) { case TELNET_BINARY_TX: case TELNET_ECHO: case TELNET_TERM_TYPE: case TELNET_SUP_GA: telnet_remote_option[option]=command; send_telnet_cmd(telnet_opt_ack(command),option); break; default: /* unsupported remote options */ if(command==TELNET_WILL) /* NAK */ send_telnet_cmd(telnet_opt_nak(command),option); break; } } } telnet_cmdlen=0; } } else outbuf[(*outlen)++]=inbuf[i]; } return(outbuf); }
int recv_byte(void* unused, unsigned timeout) { int i; long t; uchar ch; fd_set socket_set; time_t end; struct timeval tv; static uchar telnet_cmd; static int telnet_cmdlen; end=msclock()+(timeout*MSCLOCKS_PER_SEC); while(!terminate) { FD_ZERO(&socket_set); #ifdef __unix__ if(stdio) FD_SET(STDIN_FILENO,&socket_set); else #endif FD_SET(sock,&socket_set); if((t=end-msclock())<0) t=0; tv.tv_sec=t/MSCLOCKS_PER_SEC; tv.tv_usec=0; if((i=select(sock+1,&socket_set,NULL,NULL,&tv))<1) { if(i==SOCKET_ERROR) { lprintf(LOG_ERR,"ERROR %d selecting socket", ERROR_VALUE); } if(timeout) lprintf(LOG_WARNING,"Receive timeout (%u seconds)", timeout); return(NOINP); } #ifdef __unix__ if(stdio) i=read(STDIN_FILENO,&ch,sizeof(ch)); else #endif i=recv(sock,&ch,sizeof(ch),0); if(i!=sizeof(ch)) { if(i==0) { lprintf(LOG_WARNING,"Socket Disconnected"); } else lprintf(LOG_ERR,"recv error %d (%d)",i,ERROR_VALUE); return(NOINP); } if(telnet) { if(ch==TELNET_IAC) { #if DEBUG_TELNET lprintf(LOG_DEBUG,"T<%s> ",telnet_cmd_desc(ch)); #endif if(telnet_cmdlen==0) { telnet_cmdlen=1; continue; } if(telnet_cmdlen==1) { telnet_cmdlen=0; if(debug_rx) lprintf(LOG_DEBUG,"RX: %s",chr(TELNET_IAC)); return(TELNET_IAC); } } if(telnet_cmdlen) { telnet_cmdlen++; #if DEBUG_TELNET if(telnet_cmdlen==2) lprintf(LOG_DEBUG,"T<%s> ",telnet_cmd_desc(ch)); else lprintf(LOG_DEBUG,"T<%s> ",telnet_opt_desc(ch)); #endif if(debug_telnet && telnet_cmdlen==3) lprintf(LOG_DEBUG,"Received telnet command: %s %s" ,telnet_cmd_desc(telnet_cmd),telnet_opt_desc(ch)); if(telnet_cmdlen==3 && telnet_cmd==TELNET_DO) send_telnet_cmd(sock, TELNET_WILL,ch); /* else if(telnet_cmdlen==3 && telnet_cmd==TELNET_WILL) send_telnet_cmd(sock, TELNET_DO,ch); */ telnet_cmd=ch; if((telnet_cmdlen==2 && ch<TELNET_WILL) || telnet_cmdlen>2) { telnet_cmdlen=0; /* Code disabled. Why? ToDo */ /* break; */ } continue; } } if(debug_rx) lprintf(LOG_DEBUG,"RX: %s",chr(ch)); return(ch); } return(NOINP); }