Add FTP protocol debugging facilities.
[dftpd.git] / Data.cpp
blob660d8e972978c2ea785c5cfa5fd9873a3f18df53
1 #include <unistd.h>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5 #include <arpa/inet.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <sys/select.h>
9 #include "Data.hpp"
10 #include "Session.hpp"
11 #include "Exceptions.hpp"
12 #include "DataBufferFile.hpp"
13 #include "DataBufferListing.hpp"
15 #ifdef SYMBIAN
17 #include "DataBufferFileSymbian.hpp"
19 Data::Data( const SessionWPtr& session, RFile* file, Mode mode )
20 : m_sock( 0 )
21 , m_mode( mode )
22 , m_session( session )
23 , m_buf( new char[BufSize] )
25 if( mode == M_UPLOAD )
27 m_data.reset( new DataBufferFileSymbian( file, BufSize ) );
29 else
31 m_data.reset( new DataBufferFileSymbian( file, BufSize ) );
34 #endif
36 Data::Data( const SessionWPtr& session, FILE* file, Mode mode )
37 : m_sock( 0 )
38 , m_mode( mode )
39 , m_session( session )
40 , m_buf( new char[BufSize] )
42 if( mode == M_UPLOAD )
44 m_data.reset( new DataBufferFile( file, BufSize, DataBuffer::M_READ ) );
46 else
48 m_data.reset( new DataBufferFile( file, BufSize, DataBuffer::M_WRITE ) );
52 Data::Data( const SessionWPtr& session, const std::list<std::string>& list )
53 : m_sock( 0 )
54 , m_mode( M_UPLOAD )
55 , m_session( session )
56 , m_buf( new char[BufSize] )
57 , m_data( new DataBufferListing( list ) )
61 Data::~Data()
63 delete[] m_buf;
65 if( m_sock != 0 )
67 close( m_sock );
71 bool Data::Connect( const std::string& addr, int port )
73 if( ( m_sock = socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 )
75 throw SessionErrorException;
78 sockaddr_in sa;
80 sa.sin_family = AF_INET;
81 sa.sin_port = htons( port );
82 sa.sin_addr.s_addr = inet_addr( addr.c_str() );
83 memset( sa.sin_zero, 0, sizeof( sa.sin_zero ) );
85 return connect( m_sock, (sockaddr*)&sa, sizeof( sockaddr ) ) != -1;
88 bool Data::Accept( int sock )
90 sockaddr_in addr;
91 socklen_t size = sizeof( addr );
93 int incoming = accept( sock, (sockaddr*)&addr, &size );
95 if( incoming == -1 )
97 return false;
100 m_sock = incoming;
102 return true;
105 void Data::Tick()
107 if( m_mode == M_UPLOAD )
109 Send();
111 else
113 Receive();
117 void Data::Send()
119 int len = m_data->Read( m_buf, BufSize );
121 if( len == 0 )
123 m_session.lock()->DataConnectionFinished();
125 else
127 int pos = 0;
128 char *ptr = m_buf;
130 while( pos != len && CanSend() )
132 int size = send( m_sock, ptr, len - pos, 0 );
134 if( size == -1 )
136 throw SessionErrorException;
138 else if( size == 0 )
140 m_session.lock()->DataConnectionError();
141 return;
144 pos += size;
145 ptr += size;
148 if( pos != len )
150 m_data->Store( ptr, len - pos );
155 void Data::Receive()
157 int total = 0;
159 while( total < BufSize && CanReceive() )
161 int size = recv( m_sock, m_buf, BufSize - total, 0 );
162 if( size == -1 )
164 throw SessionErrorException;
166 else if( size == 0 )
168 m_session.lock()->DataConnectionFinished();
169 return;
171 else
173 int writeSize = m_data->Write( m_buf, size );
175 if( writeSize != size )
177 m_session.lock()->OutOfSpace();
178 return;
182 total += size;
186 bool Data::CanSend()
188 fd_set fd;
189 FD_ZERO( &fd );
190 FD_SET( m_sock, &fd );
191 timeval tv;
192 tv.tv_sec = 0;
193 tv.tv_usec = 0;
194 select( m_sock + 1, NULL, &fd, NULL, &tv );
196 return FD_ISSET( m_sock, &fd );
199 bool Data::CanReceive()
201 fd_set fd;
202 FD_ZERO( &fd );
203 FD_SET( m_sock, &fd );
204 timeval tv;
205 tv.tv_sec = 0;
206 tv.tv_usec = 0;
207 select( m_sock + 1, &fd, NULL, NULL, &tv );
209 return FD_ISSET( m_sock, &fd );