Fix PASV reply for Firefox.
[dftpd.git] / Server.cpp
blob7dbf74eb9964d546b5915d6e65465434ed2bec3e
1 #ifdef _WIN32
2 #include <winsock.h>
3 #undef min
4 #undef max
5 #else
6 #include <sys/select.h>
7 #endif
9 #include <iostream>
10 #include <string.h>
11 #include <errno.h>
12 #include "Server.hpp"
13 #include "Auth.hpp"
14 #include "Log.hpp"
15 #include "Exceptions.hpp"
17 Server::Server( const AuthPtr& auth )
18 : m_listener( new Listener )
19 , m_sessionController( new SessionController )
20 , m_auth( auth )
22 g_log->Print( "Dumb FTP server" );
23 g_log->Print( std::string("IP: ") + m_listener->GetIPAddr() );
25 LoadWelcomeMessage();
27 m_listener->Listen();
30 Server::Server( const AuthPtr& auth, const std::string& ip )
31 : m_listener( new Listener( ip ) )
32 , m_sessionController( new SessionController )
33 , m_auth( auth )
35 g_log->Print( "Dumb FTP server" );
36 g_log->Print( std::string("IP: ") + m_listener->GetIPAddr() );
38 LoadWelcomeMessage();
40 m_listener->Listen();
43 Server::~Server()
45 g_log->Print( "[Server] Shutting down" );
48 ServerPtr Server::Create( const AuthPtr& auth )
50 ServerPtr ret( new Server( auth ) );
51 ret->m_this = ret;
53 ret->InitListener();
55 return ret;
58 ServerPtr Server::Create( const AuthPtr& auth, const std::string& ip )
60 ServerPtr ret( new Server( auth, ip ) );
61 ret->m_this = ret;
63 ret->InitListener();
65 return ret;
68 void Server::Tick()
70 fd_set read, write;
71 std::list<int> fds = m_sessionController->GetFds();
72 int maxfd = m_listener->GetSock();
74 FD_ZERO( &read );
75 FD_ZERO( &write );
77 FD_SET( maxfd, &read );
79 for( std::list<int>::const_iterator it = fds.begin(); it != fds.end(); ++it )
81 maxfd = std::max( maxfd, abs( *it ) );
83 if( *it < 0 )
85 // Hack
86 FD_SET( -(*it), &write );
88 else
90 FD_SET( *it, &read );
94 timeval tv;
95 tv.tv_sec = 0;
96 tv.tv_usec = 50000;
98 int ret = select( maxfd + 1, &read, &write, NULL, &tv );
100 if( ret == -1 )
102 g_log->Print( strerror( errno ) );
103 throw ServerCrashException;
105 else if( ret == 0 )
107 // Descriptors not ready
108 return;
111 std::list<int> activeFds;
112 for( std::list<int>::const_iterator it = fds.begin(); it != fds.end(); ++it )
114 if( ( *it > 0 && FD_ISSET( *it, &read ) ) ||
115 ( *it < 0 && FD_ISSET( -(*it), &write ) ) )
117 activeFds.push_back( abs( *it ) );
121 if( activeFds.size() != 0 )
123 m_sessionController->Tick( activeFds );
126 if( FD_ISSET( m_listener->GetSock(), &read ) )
128 m_listener->Tick();
132 void Server::IncomingConnection( int sock )
134 m_sessionController->Add( Session::Create( sock, m_sessionController, m_auth, m_listener->GetIPAddr(), m_this ) );
137 void Server::InitListener()
139 m_listener->SetServer( m_this );
142 void Server::LoadWelcomeMessage()
144 FILE *f = fopen( "welcome", "r" );
145 if( !f )
147 return;
150 char buf[256];
151 while( fgets( buf, 256, f ) )
153 if( buf[strlen( buf ) - 1] == '\n' )
155 buf[strlen( buf ) - 1] = 0;
158 m_welcome.push_back( buf );
161 fclose( f );