Add FTP protocol debugging facilities.
[dftpd.git] / Telnet.cpp
blobbe4861852eb7f8fcbe0a5747d7f8ee1f31cd250a
1 #include <iostream>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <sys/select.h>
7 #include "Telnet.hpp"
8 #include "Exceptions.hpp"
9 #include "Log.hpp"
11 static const char CRLF[] = { 13, 10, 0 };
12 static const char IAC[] = { 255, 0 };
14 Telnet::Telnet( int sock )
15 : m_sock( sock )
19 Telnet::~Telnet()
23 TelnetPtr Telnet::Create( int sock )
25 TelnetPtr ret( new Telnet( sock ) );
26 ret->m_this = ret;
27 ret->m_cmd.reset( new TelnetCommand( ret ) );
29 return ret;
32 bool Telnet::Read()
34 std::string buf;
36 // Read all that's waiting on the socket
37 for(;;)
39 char tmpBuf[BufSize];
41 fd_set fd;
42 FD_ZERO( &fd );
43 FD_SET( m_sock, &fd );
44 timeval tv;
45 tv.tv_sec = 0;
46 tv.tv_usec = 0;
47 select( m_sock + 1, &fd, NULL, NULL, &tv );
48 if( !FD_ISSET( m_sock, &fd ) )
50 break;
53 int size = recv( m_sock, tmpBuf, BufSize, 0 );
55 if( size == -1 )
57 throw SessionErrorException;
59 else if( size == 0 )
61 throw ConnectionTerminatedException;
64 buf.append( tmpBuf, size );
67 // Parse telnet commands
68 for( unsigned int i=0; i<buf.size(); i++ )
70 if( m_cmd->ParsingCommand() || (unsigned char)buf[i] == 255 )
72 if( !m_cmd->Parse( buf[i] ) )
74 throw SessionErrorException;
77 else
79 m_readBuf += buf[i];
83 return m_readBuf.find( CRLF ) != std::string::npos;
86 void Telnet::Write( const std::string& msg )
88 #ifdef DEBUG
89 g_log->Print( "> " + msg );
90 #endif
92 std::string buf;
93 for( unsigned int i=0; i<msg.size(); i++ )
95 buf += msg[i];
97 if( (unsigned char)msg[i] == 255 )
99 buf.append( IAC );
102 buf.append( CRLF );
104 unsigned int pos = 0;
105 char *ptr = (char*)buf.c_str();
107 while( pos != buf.size() )
109 int size = send( m_sock, ptr, buf.size() - pos, 0 );
111 if( size == -1 )
113 throw SessionErrorException;
115 else if( size == 0 )
117 throw ConnectionTerminatedException;
120 pos += size;
121 ptr += size;
125 std::string Telnet::GetBuf()
127 std::string ret;
129 unsigned int pos = m_readBuf.find( CRLF );
130 if( pos == std::string::npos )
132 throw SessionErrorException;
135 ret = m_readBuf.substr( 0, pos );
137 m_readBuf.erase( 0, pos + 2 );
139 #ifdef DEBUG
140 g_log->Print( "< " + ret );
141 #endif
143 return ret;
146 void Telnet::EraseCharacter()
148 if( m_readBuf.size() > 0 )
150 m_readBuf.erase( m_readBuf.end() - 1 );
154 void Telnet::EraseLine()
156 throw SessionErrorException;