Add Visual Studio project.
[dftpd.git] / Data.cpp
blob3ca926d0f15c8efd645ee8cde954ccb09da76832
1 #ifdef _WIN32
2 #include <winsock.h>
3 typedef int socklen_t;
4 #else
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
8 #include <arpa/inet.h>
9 #include <sys/select.h>
10 #endif
12 #include <unistd.h>
13 #include <string.h>
14 #include <errno.h>
15 #include "Data.hpp"
16 #include "Session.hpp"
17 #include "Exceptions.hpp"
18 #include "DataBufferFile.hpp"
19 #include "DataBufferListing.hpp"
21 #ifdef SYMBIAN
23 #include "DataBufferFileSymbian.hpp"
25 Data::Data( const SessionWPtr& session, RFile* file, Mode mode )
26 : m_sock( 0 )
27 , m_mode( mode )
28 , m_session( session )
29 , m_buf( new char[BufSize] )
31 if( mode == M_UPLOAD )
33 m_data.reset( new DataBufferFileSymbian( file, BufSize ) );
35 else
37 m_data.reset( new DataBufferFileSymbian( file, BufSize ) );
40 #endif
42 Data::Data( const SessionWPtr& session, FILE* file, Mode mode )
43 : m_sock( 0 )
44 , m_mode( mode )
45 , m_session( session )
46 , m_buf( new char[BufSize] )
48 if( mode == M_UPLOAD )
50 m_data.reset( new DataBufferFile( file, BufSize ) );
52 else
54 m_data.reset( new DataBufferFile( file, BufSize ) );
58 Data::Data( const SessionWPtr& session, const std::list<std::string>& list )
59 : m_sock( 0 )
60 , m_mode( M_UPLOAD )
61 , m_session( session )
62 , m_buf( new char[BufSize] )
63 , m_data( new DataBufferListing( list ) )
67 Data::~Data()
69 delete[] m_buf;
71 if( m_sock != 0 )
73 #ifdef _WIN32
74 closesocket( m_sock );
75 #else
76 close( m_sock );
77 #endif
81 bool Data::Connect( const std::string& addr, int port )
83 if( ( m_sock = socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 )
85 throw SessionErrorException;
88 sockaddr_in sa;
90 sa.sin_family = AF_INET;
91 sa.sin_port = htons( port );
92 sa.sin_addr.s_addr = inet_addr( addr.c_str() );
93 memset( sa.sin_zero, 0, sizeof( sa.sin_zero ) );
95 return connect( m_sock, (sockaddr*)&sa, sizeof( sockaddr ) ) != -1;
98 bool Data::Accept( int sock )
100 sockaddr_in addr;
101 socklen_t size = sizeof( addr );
103 int incoming = accept( sock, (sockaddr*)&addr, &size );
105 if( incoming == -1 )
107 return false;
110 m_sock = incoming;
112 return true;
115 void Data::Tick()
117 if( m_mode == M_UPLOAD )
119 Send();
121 else
123 Receive();
127 void Data::Send()
129 int len = m_data->Read( m_buf, BufSize );
131 if( len == 0 )
133 m_session.lock()->DataConnectionFinished();
135 else
137 int pos = 0;
138 char *ptr = m_buf;
140 while( pos != len && CanSend() )
142 int size = send( m_sock, ptr, len - pos, 0 );
144 if( size == -1 )
146 throw SessionErrorException;
148 else if( size == 0 )
150 m_session.lock()->DataConnectionError();
151 return;
154 pos += size;
155 ptr += size;
158 if( pos != len )
160 m_data->Store( ptr, len - pos );
165 void Data::Receive()
167 int total = 0;
169 while( total < BufSize && CanReceive() )
171 int size = recv( m_sock, m_buf, BufSize - total, 0 );
172 if( size == -1 )
174 throw SessionErrorException;
176 else if( size == 0 )
178 m_session.lock()->DataConnectionFinished();
179 return;
181 else
183 int writeSize = m_data->Write( m_buf, size );
185 if( writeSize != size )
187 m_session.lock()->OutOfSpace();
188 return;
192 total += size;
196 bool Data::CanSend()
198 fd_set fd;
199 FD_ZERO( &fd );
200 FD_SET( m_sock, &fd );
201 timeval tv;
202 tv.tv_sec = 0;
203 tv.tv_usec = 0;
204 select( m_sock + 1, NULL, &fd, NULL, &tv );
206 return FD_ISSET( m_sock, &fd );
209 bool Data::CanReceive()
211 fd_set fd;
212 FD_ZERO( &fd );
213 FD_SET( m_sock, &fd );
214 timeval tv;
215 tv.tv_sec = 0;
216 tv.tv_usec = 0;
217 select( m_sock + 1, &fd, NULL, NULL, &tv );
219 return FD_ISSET( m_sock, &fd );