Polling socket for read/write.
[dftpd.git] / Data.cpp
blob77e14f1d1fc0d0749b37cd488216367dfac5eff4
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 Data::Data( const SessionWPtr& session, FILE* file, Mode mode )
16 : m_sock( 0 )
17 , m_mode( mode )
18 , m_session( session )
19 , m_buf( new char[BufSize] )
20 , m_data( new DataBufferFile( file ) )
24 Data::Data( const SessionWPtr& session, const std::list<std::string>& list )
25 : m_sock( 0 )
26 , m_mode( M_UPLOAD )
27 , m_session( session )
28 , m_buf( new char[BufSize] )
29 , m_data( new DataBufferListing( list ) )
33 Data::~Data()
35 delete[] m_buf;
37 if( m_sock != 0 )
39 close( m_sock );
43 bool Data::Connect( const std::string& addr, int port )
45 if( ( m_sock = socket( PF_INET, SOCK_STREAM, 0 ) ) == -1 )
47 throw SessionErrorException;
50 sockaddr_in sa;
52 sa.sin_family = AF_INET;
53 sa.sin_port = htons( port );
54 sa.sin_addr.s_addr = inet_addr( addr.c_str() );
55 memset( sa.sin_zero, 0, sizeof( sa.sin_zero ) );
57 return connect( m_sock, (sockaddr*)&sa, sizeof( sockaddr ) ) != -1;
60 bool Data::Accept( int sock )
62 sockaddr_in addr;
63 socklen_t size = sizeof( addr );
65 int incoming = accept( sock, (sockaddr*)&addr, &size );
67 if( incoming == -1 )
69 return false;
72 m_sock = incoming;
74 return true;
77 void Data::Tick()
79 if( m_mode == M_UPLOAD )
81 Send();
83 else
85 Receive();
89 void Data::Send()
91 int len = m_data->Read( m_buf, BufSize );
93 if( len == 0 )
95 SessionPtr sptr = m_session.lock();
96 if( !sptr )
98 throw "Data lost its Session";
100 sptr->DataConnectionFinished();
102 else
104 int pos = 0;
105 char *ptr = m_buf;
107 while( pos != len )
109 int size = send( m_sock, ptr, len - pos, 0 );
111 if( size == -1 )
113 throw SessionErrorException;
115 else if( size == 0 )
117 SessionPtr sptr = m_session.lock();
118 if( !sptr )
120 throw "Data lost its Session";
122 sptr->DataConnectionError();
124 return;
127 pos += size;
128 ptr += size;
133 void Data::Receive()
135 int size = recv( m_sock, m_buf, BufSize, 0 );
137 if( size == -1 )
139 throw SessionErrorException;
141 else if( size == 0 )
143 SessionPtr sptr = m_session.lock();
144 if( !sptr )
146 throw "Data lost its Session";
148 sptr->DataConnectionFinished();
150 else
152 int writeSize = m_data->Write( m_buf, size );
154 if( writeSize != size )
156 SessionPtr sptr = m_session.lock();
157 if( !sptr )
159 throw "Data lost its Session";
161 sptr->OutOfSpace();
166 bool Data::CanSend()
168 fd_set fd;
169 FD_ZERO( &fd );
170 FD_SET( m_sock, &fd );
171 timeval tv;
172 tv.tv_sec = 0;
173 tv.tv_usec = 0;
174 select( m_sock + 1, NULL, &fd, NULL, &tv );
176 return FD_ISSET( m_sock, &fd );
179 bool Data::CanReceive()
181 fd_set fd;
182 FD_ZERO( &fd );
183 FD_SET( m_sock, &fd );
184 timeval tv;
185 tv.tv_sec = 0;
186 tv.tv_usec = 0;
187 select( m_sock + 1, &fd, NULL, NULL, &tv );
189 return FD_ISSET( m_sock, &fd );