Stupid winsock needs special way to close sockets.
[dftpd.git] / Telnet.cpp
blob67bece5991f11d88be5cc2dbddbee8ee896c6343
1 #ifdef _WIN32
2 #include <winsock.h>
3 #else
4 #include <sys/socket.h>
5 #include <sys/select.h>
6 #endif
8 #include <iostream>
9 #include <sys/types.h>
10 #include <string.h>
11 #include <errno.h>
12 #include "Telnet.hpp"
13 #include "Exceptions.hpp"
14 #include "Log.hpp"
16 static const char CRLF[] = { 13, 10, 0 };
17 static const char IAC[] = { 255, 0 };
19 Telnet::Telnet( int sock )
20 : m_sock( sock )
24 Telnet::~Telnet()
28 TelnetPtr Telnet::Create( int sock )
30 TelnetPtr ret( new Telnet( sock ) );
31 ret->m_this = ret;
32 ret->m_cmd.reset( new TelnetCommand( ret ) );
34 return ret;
37 bool Telnet::Read()
39 std::string buf;
41 // Read all that's waiting on the socket
42 for(;;)
44 char tmpBuf[BufSize];
46 fd_set fd;
47 FD_ZERO( &fd );
48 FD_SET( m_sock, &fd );
49 timeval tv;
50 tv.tv_sec = 0;
51 tv.tv_usec = 0;
52 select( m_sock + 1, &fd, NULL, NULL, &tv );
53 if( !FD_ISSET( m_sock, &fd ) )
55 break;
58 int size = recv( m_sock, tmpBuf, BufSize, 0 );
60 if( size == -1 )
62 throw SessionErrorException;
64 else if( size == 0 )
66 throw ConnectionTerminatedException;
69 buf.append( tmpBuf, size );
72 // Parse telnet commands
73 for( unsigned int i=0; i<buf.size(); i++ )
75 if( m_cmd->ParsingCommand() || (unsigned char)buf[i] == 255 )
77 if( !m_cmd->Parse( buf[i] ) )
79 throw SessionErrorException;
82 else
84 m_readBuf += buf[i];
88 return m_readBuf.find( CRLF ) != std::string::npos;
91 void Telnet::Write( const std::string& msg )
93 #ifdef DEBUG
94 g_log->Print( "> " + msg );
95 #endif
97 std::string buf;
98 for( unsigned int i=0; i<msg.size(); i++ )
100 buf += msg[i];
102 if( (unsigned char)msg[i] == 255 )
104 buf.append( IAC );
107 buf.append( CRLF );
109 unsigned int pos = 0;
110 char *ptr = (char*)buf.c_str();
112 while( pos != buf.size() )
114 int size = send( m_sock, ptr, buf.size() - pos, 0 );
116 if( size == -1 )
118 throw SessionErrorException;
120 else if( size == 0 )
122 throw ConnectionTerminatedException;
125 pos += size;
126 ptr += size;
130 std::string Telnet::GetBuf()
132 std::string ret;
134 unsigned int pos = m_readBuf.find( CRLF );
135 if( pos == std::string::npos )
137 throw SessionErrorException;
140 ret = m_readBuf.substr( 0, pos );
142 m_readBuf.erase( 0, pos + 2 );
144 #ifdef DEBUG
145 g_log->Print( "< " + ret );
146 #endif
148 return ret;
151 void Telnet::EraseCharacter()
153 if( m_readBuf.size() > 0 )
155 m_readBuf.erase( m_readBuf.end() - 1 );
159 void Telnet::EraseLine()
161 throw SessionErrorException;