Handle IAC during sending data.
[dftpd.git] / Telnet.cpp
blob15c7370f8a7c35d79986ec78de451bd75dad6af9
1 #include <iostream>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <string.h>
5 #include <errno.h>
6 #include "Telnet.hpp"
7 #include "Exceptions.hpp"
9 static const char CRLF[] = { 13, 10, 0 };
10 static const char IAC[] = { 255, 0 };
12 Telnet::Telnet( int sock )
13 : m_sock( sock )
17 Telnet::~Telnet()
21 TelnetPtr Telnet::Create( int sock )
23 TelnetPtr ret( new Telnet( sock ) );
24 ret->m_this = ret;
25 ret->m_cmd.reset( new TelnetCommand( ret ) );
27 return ret;
30 bool Telnet::Read()
32 std::string buf;
34 // Read all that's waiting on the socket
35 for(;;)
37 char tmpBuf[BufSize];
38 int size = recv( m_sock, tmpBuf, BufSize, 0 );
40 if( size == -1 )
42 if( errno == EAGAIN )
44 // No error, just nothing to be read from socket
45 break;
48 throw strerror( errno );
50 else if( size == 0 )
52 throw ConnectionTerminatedException;
55 buf.append( tmpBuf, size );
58 // Parse telnet commands
59 for( unsigned int i=0; i<buf.size(); i++ )
61 if( m_cmd->ParsingCommand() || (unsigned char)buf[i] == 255 )
63 if( !m_cmd->Parse( buf[i] ) )
65 throw "Telnet parse error";
68 else
70 m_readBuf += buf[i];
74 return m_readBuf.find( CRLF ) != std::string::npos;
77 void Telnet::Write( const std::string& msg )
79 std::string buf;
80 for( unsigned int i=0; i<msg.size(); i++ )
82 buf += msg[i];
84 if( (unsigned char)msg[i] == 255 )
86 buf.append( IAC );
89 buf.append( CRLF );
91 unsigned int pos = 0;
92 char *ptr = (char*)buf.c_str();
94 while( pos != buf.size() )
96 int size = send( m_sock, ptr, buf.size() - pos, 0 );
98 if( size == -1 )
100 throw strerror( errno );
102 else if( size == 0 )
104 throw ConnectionTerminatedException;
107 pos += size;
108 ptr += size;
112 std::string Telnet::GetBuf()
114 std::string ret;
116 unsigned int pos = m_readBuf.find( CRLF );
117 if( pos == std::string::npos )
119 throw "Trying to get telnet buffer when buffer not ready";
122 ret = m_readBuf.substr( 0, pos );
124 m_readBuf.erase( 0, pos + 2 );
126 return ret;
129 void Telnet::EraseCharacter()
131 if( m_readBuf.size() > 0 )
133 m_readBuf.erase( m_readBuf.end() - 1 );
137 void Telnet::EraseLine()
139 throw "Unimplemented";