📄 telnet.cpp
字号:
/******************************************************************************** telnet.cpp:*-------------------------------------------------------------------------------* (c)1999-2001 VideoLAN* $Id: telnet.cpp,v 1.7 2002/08/14 11:13:27 tooney Exp $** Authors: Benoit Steiner <benny@via.ecp.fr>* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.**-------------------------------------------------------------------------------* Informations on the Telnet protocol can be found in RFC 854 to 861 and also* RFC 1184 for linemodes********************************************************************************///------------------------------------------------------------------------------// Preamble//------------------------------------------------------------------------------#include "../core/defs.h"#include <ctype.h>#include "config.h"#include "../core/core.h"#include "../core/network.h"#include "request.h"#include "admin.h"#include "telnet.h"#include "../core/network.cpp"//------------------------------------------------------------------------------// Telnet interface//------------------------------------------------------------------------------#define WELCOME "Videolan Server Administration System"#define LOGIN "Login: "#define PASSWD "Password: "#define PROMPT "vls> "//------------------------------------------------------------------------------// Telnet protocol constants//------------------------------------------------------------------------------#define IAC 255 // Interpret as command#define DONT 254 // You are not to use option#define DO 253 // Please use option#define WONT 252 // I won't use option#define WILL 251 // I will use option#define EL 248 // Erase the current line#define TELOPT_ECHO 1 // Echo#define TELOPT_SGA 3 // Suppress go ahead#define TELOPT_OUTMRK 27 // Output marking#define TELOPT_LINEMODE 34 // Linemode option#define KEY_UP 65 // #define KEY_DOWN 66 // #define KEY_LEFT 67 // #define KEY_RIGHT 68 ////------------------------------------------------------------------------------// Telnet module definitions//------------------------------------------------------------------------------#define CONFIG_MODE 1#define CONTROL_MODE 2#define INTERACTIVE_MODE 3#define INIT_PHASE 1#define LOGIN_PHASE 2#define PASSWD_PHASE 3#define COMMAND_PHASE 4#define HISTORY_SIZE 20/******************************************************************************** E_Telnet exception****************************************************************************************************************************************************************/E_Telnet::E_Telnet(const C_String& strMsg) : E_Exception(GEN_ERR, strMsg){}E_Telnet::E_Telnet(const C_String& strMsg, const E_Exception& e) : E_Exception(GEN_ERR, strMsg, e){}/******************************************************************************** C_TelnetOptions class********************************************************************************* Manage the configuration of the 2 NVT through telnet negociation* Very basic at that time, is to be completly rewritten*******************************************************************************///------------------------------------------------------------------------------////------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Buffer<byte> C_TelnetOptions::Request(byte bAction, byte bOption){ C_Buffer<byte> cAnswer(3); cAnswer.SetSize(3); cAnswer[0] = IAC; cAnswer[1] = bAction; cAnswer[2] = bOption; //m_cPendingRequests.PushEnd(new C_Buffer<byte>(cAnswer)); return cAnswer;}//------------------------------------------------------------------------------////------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Buffer<byte> C_TelnetOptions::Answer(const C_Buffer<byte>& cRequest){ ASSERT(cRequest.GetSize() == 3); C_Buffer<byte> cAnswer(3); cAnswer.SetSize(0); // cAnswer.SetSize(3); // cAnswer[0] = IAC; // cAnswer[2] = cRequest[3]; return cAnswer;}//------------------------------------------------------------------------------////------------------------------------------------------------------------------// //------------------------------------------------------------------------------int C_TelnetOptions::GetOptionStatus(){ return YES;}/******************************************************************************** C_TelnetCmdLine class********************************************************************************* Manage a telnet command line*******************************************************************************///------------------------------------------------------------------------------// Constructor//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_TelnetCmdLine::C_TelnetCmdLine() : m_cCurrent(m_cHistory.CreateIterator()){ m_iPosInLine = 0;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_String C_TelnetCmdLine::Append(byte bByte){ C_String cResult; switch(bByte) { case 0x7F: { if(m_strLine.Length() > 0) { m_strLine = m_strLine.SubString(0, m_strLine.Length()-1); cResult += "\b\e[P"; } break; } default: { if(bByte != '\n' && bByte != '\0') { m_strLine += (char)bByte; cResult += (char)bByte; } } } return cResult;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_Buffer<byte> C_TelnetCmdLine::Edit(const C_Buffer<byte>& cCmd){ ASSERT(cCmd.GetSize() == 3); ASSERT(cCmd[0] = TELOPT_OUTMRK); C_String strResult; switch(cCmd[2]) { case KEY_UP: { if(m_cCurrent.HasNext()) { strResult = *m_cCurrent.GetNext(); } break; } case KEY_DOWN: { if(m_cCurrent.HasPrevious()) { strResult = *m_cCurrent.GetPrevious(); } break; } } if(strResult != "") { StartNewLine(); m_strLine = strResult; } return /*EL + strResult*/C_Buffer<byte>(0);}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_String C_TelnetCmdLine::GetCmdLine(){ // Strip line C_String strResult = m_strLine.Strip(" \t"); return strResult;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_TelnetCmdLine::StartNewLine(){ // Store current line if not empty C_String strLine = GetCmdLine(); if(strLine.Length() > 0) { m_cHistory.PushStart(new C_String(strLine)); // To do: removal of old commands } // Reset command history m_cCurrent.Reset(); // Empty current line m_strLine = "";}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_TelnetCmdLine::DropLine(){ m_strLine = "";}/******************************************************************************** C_TelnetSession class********************************************************************************* * *******************************************************************************///------------------------------------------------------------------------------// Constructor//------------------------------------------------------------------------------// //------------------------------------------------------------------------------C_TelnetSession::C_TelnetSession(C_Socket* pConnection, void* pAdmin) : C_AdminSession((C_Admin*)pAdmin), m_strPeerName("[Unknown]"), m_cStream(pConnection), m_cBuffer(3){ ASSERT(pConnection); m_pConnection = pConnection; // Starting mode m_iPhase = INIT_PHASE; m_iMode = INTERACTIVE_MODE;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_TelnetSession::OnInit(){ // Actual initialisation is done internally in small pieces cause it could // block the entire server if done in one single step. For now just send // the welcome message m_cStream << "\r\n" << WELCOME << "\r\n\r\n"; // Transmission parameters: to be able to deal with all clients, editing is // done on the server m_cStream << m_cOptions.Request(WILL, TELOPT_ECHO); m_cStream << m_cOptions.Request(WILL, TELOPT_SGA); m_cStream << m_cOptions.Request(DONT, TELOPT_LINEMODE); m_cStream << LOGIN; m_iPhase = LOGIN_PHASE;}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_TelnetSession::OnClose(){ try { // Send a goodby message if possible if(m_cStream.GetState() == STREAM_READY) m_cStream << "\r\nClosing connection" << "\r\n"; // Close the connection m_pConnection->Close(); } catch(E_Exception e) { throw E_Telnet("Unable to close connection with "+m_strPeerName, e); }}//------------------------------------------------------------------------------// //------------------------------------------------------------------------------// //------------------------------------------------------------------------------void C_TelnetSession::ProcessData(){ try { // First get the data from the network C_Buffer<byte> cData(256); m_cStream >> cData; // There must be some data because the select told us else the client // closed his session. if(cData.GetSize() <= 0) throw E_Telnet("Connection reset by peer"); unsigned int iPos = 0; unsigned int iSize = cData.GetSize(); while(iPos < iSize) { switch(cData[iPos]) { case IAC: { // Telnet negociation or special char// printf("negociation: %x %x\n", cData[iPos+1], cData[iPos+2]); m_cBuffer[0] = IAC; m_cBuffer.SetSize(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -