2011-01-20 15:56:30 +00:00
/**
* Feathery FTP - Server < https : //sourceforge.net/projects/feathery>
* Copyright ( C ) 2005 - 2010 Andreas Martin ( andreas . martin @ linuxmail . org )
*
* ftpRuntime . c - ftp - server runtime environment
*
* This is the central module of feathery . It defines all runtime functions
* of feathery . That is startup , state , main - thread an shutdown .
*
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <stdio.h>
# include "ftpTypes.h"
# include "ftpConfig.h"
# include "ftp.h"
# include "ftpMessages.h"
/**
* @ brief server - sockets that listens for incoming connections
*/
2011-01-06 00:52:00 +00:00
LOCAL socket_t server ;
LOCAL int serverListenPort ;
LOCAL int serverPassiveListenPort ;
2011-01-20 15:56:30 +00:00
//LOCAL socket_t serverPassivePort;
2011-11-29 05:07:18 +00:00
void ftpInit ( ftpFindExternalFTPServerIpType cb1 , ftpAddUPNPPortForwardType cb2 ,
ftpRemoveUPNPPortForwardType cb3 , ftpIsValidClientType cb4 ,
ftpIsClientAllowedToGetFileType cb5 ) {
2010-12-31 21:00:25 +00:00
ftpFindExternalFTPServerIp = cb1 ;
ftpAddUPNPPortForward = cb2 ;
2011-01-07 06:21:23 +00:00
ftpRemoveUPNPPortForward = cb3 ;
2011-01-20 15:56:30 +00:00
ftpIsValidClient = cb4 ;
2011-11-29 05:07:18 +00:00
ftpIsClientAllowedToGetFile = cb5 ;
2011-01-20 15:56:30 +00:00
}
2011-01-06 00:52:00 +00:00
int ftpGetListenPort ( )
{
return serverListenPort ;
}
int ftpGetPassivePort ( )
{
return serverPassiveListenPort ;
}
//socket_t ftpGetServerPassivePortListenSocket()
//{
// return serverPassivePort;
//}
2011-01-20 15:56:30 +00:00
/**
* @ brief Initializes and starts the server
*
*
* @ return - 0 : server started successfully
* - - 1 : could not create server socket
*/
int ftpStart ( int portNumber )
2011-01-06 00:52:00 +00:00
{
serverListenPort = portNumber ;
2011-01-20 15:56:30 +00:00
serverPassiveListenPort = portNumber + 1 ;
2011-01-06 00:52:00 +00:00
server = - 1 ; // set server socket to invalid value
2011-01-20 15:56:30 +00:00
//serverPassivePort = -1;
if ( VERBOSE_MODE_ENABLED ) printf ( " Feathery FTP-Server \n " ) ;
ftpArchInit ( ) ;
if ( VERBOSE_MODE_ENABLED ) printf ( " Creating server socket " ) ;
server = ftpCreateServerSocket ( serverListenPort ) ; // create main listener socket
if ( server < 0 )
{
if ( VERBOSE_MODE_ENABLED ) printf ( " \t \t error \n " ) ;
return - 1 ;
}
if ( VERBOSE_MODE_ENABLED ) printf ( " \t \t ok \n " ) ;
if ( VERBOSE_MODE_ENABLED ) printf ( " Server successfully started \n " ) ;
2011-01-06 00:52:00 +00:00
ftpTrackSocket ( server ) ; // add socket to "watchlist"
/*
2011-01-20 15:56:30 +00:00
if ( VERBOSE_MODE_ENABLED ) printf ( " Creating server PASSIVE socket " ) ;
serverPassivePort = ftpCreateServerSocket ( serverPassiveListenPort ) ; // create main listener socket
if ( serverPassivePort < 0 )
{
if ( VERBOSE_MODE_ENABLED ) printf ( " \t \t passive port error \n " ) ;
return - 1 ;
}
if ( VERBOSE_MODE_ENABLED ) printf ( " \t \t ok \n " ) ;
if ( VERBOSE_MODE_ENABLED ) printf ( " Server passive port successfully started \n " ) ;
2011-01-06 00:52:00 +00:00
*/
2011-01-20 15:56:30 +00:00
return 0 ;
}
/**
* @ brief Checks if the server has something to do
*
* In order of avoid blocking of ftpExecute this function can be used to
* determine if the server has something to do . You can call this function in
* a loop and everytime it returns nonezero its time to call ftpExecute ( ) .
*
* @ return 0 noting to do ; else server has received some data
*/
int ftpState ( void )
{
return 0 ;
}
/**
* @ brief Main server - thread
*
* Manages all client connections and active transmitions . In addtition
* all received control - strings are dispatched to the command - module .
* Note , the function blocks if there is nothing to do .
*/
int ftpExecute ( void )
2011-01-09 04:49:21 +00:00
{
2011-01-20 15:56:30 +00:00
int processedWork = 0 ;
int n = 0 ;
int socksRdy = 0 ;
ftpSession_S * pSession = NULL ;
int sessionId = 0 ;
2012-10-20 07:15:13 +00:00
//int activeJobs=0;
2011-01-20 15:56:30 +00:00
int len ;
int bufLen ;
2012-10-20 07:15:13 +00:00
int activeJobs = ftpGetActiveTransCnt ( ) ; // are there any active transmitions?
2011-01-20 15:56:30 +00:00
//for(n = 0; (activeJobs > 0) && (n < MAX_CONNECTIONS); n++)
for ( n = 0 ; n < MAX_CONNECTIONS ; n + + )
{
pSession = ftpGetSession ( n ) ;
if ( pSession - > activeTrans . op ) // has this session an active transmition?
{
processedWork = 1 ;
ftpExecTransmission ( n ) ; // do the job
activeJobs - - ;
}
}
if ( ftpGetActiveTransCnt ( ) ) // don't block if there's still something to do
{
socksRdy = ftpSelect ( TRUE ) ;
}
else
{
//if(VERBOSE_MODE_ENABLED) printf("ftpExecute calling blocking select\n");
socksRdy = ftpSelect ( FALSE ) ;
}
if ( socksRdy > 0 )
{
if ( VERBOSE_MODE_ENABLED ) printf ( " ftpExecute socksRdy = %d \n " , socksRdy ) ;
processedWork = 1 ;
if ( ftpTestSocket ( server ) ) // server listner-socket signaled?
{
socket_t clientSocket ;
ip_t remoteIP ;
port_t remotePort ;
socksRdy - - ;
clientSocket = ftpAcceptServerConnection ( server , & remoteIP , & remotePort ) ;
if ( clientSocket > = 0 )
{
if ( VERBOSE_MODE_ENABLED ) printf ( " ftpExecute ftpAcceptServerConnection = %d \n " , clientSocket ) ;
sessionId = ftpOpenSession ( clientSocket , remoteIP , remotePort ) ;
if ( sessionId > = 0 )
{
ftpTrackSocket ( clientSocket ) ;
ftpSendMsg ( MSG_NORMAL , sessionId , 220 , ftpMsg037 ) ;
}
else
{
if ( VERBOSE_MODE_ENABLED ) printf ( " ERROR: Connection refused; Session limit reached, about to close socket = %d \n " , clientSocket ) ;
ftpUntrackSocket ( clientSocket ) ;
ftpCloseSocket ( & clientSocket ) ;
}
}
}
//socksRdy = ftpSelect(TRUE);
for ( n = 0 ; ( socksRdy > 0 ) & & ( n < MAX_CONNECTIONS ) ; n + + )
{
pSession = ftpGetSession ( n ) ;
if ( pSession - > open )
{
socket_t ctrlSocket = pSession - > ctrlSocket ;
if ( ftpTestSocket ( ctrlSocket ) )
{
if ( VERBOSE_MODE_ENABLED ) printf ( " ftpExecute signaled socket = %d, session = %d \n " , ctrlSocket , n ) ;
socksRdy - - ;
bufLen = ( LEN_RXBUF - pSession - > rxBufWriteIdx ) ;
len = ftpReceive ( ctrlSocket ,
& pSession - > rxBuf [ pSession - > rxBufWriteIdx ] ,
bufLen ) ;
if ( len < = 0 ) // has client shutdown the connection?
{
int errorNumber = getLastSocketError ( ) ;
const char * errText = getLastSocketErrorText ( & errorNumber ) ;
if ( VERBOSE_MODE_ENABLED ) printf ( " In ftpExecute ERROR ON RECEIVE session = %d for socket = %d, data len = %d index = %d, len = %d, error = %d [%s] \n " , n , ctrlSocket , bufLen , pSession - > rxBufWriteIdx , len , errorNumber , errText ) ;
ftpUntrackSocket ( ctrlSocket ) ;
ftpCloseSession ( n ) ;
}
else
{
pSession - > rxBufWriteIdx + = len ;
ftpParseCmd ( n ) ;
}
}
/// @bug Session-Timeout-Management doesn't work
if ( ( ftpGetUnixTime ( ) - pSession - > timeLastCmd ) > SESSION_TIMEOUT )
{
if ( VERBOSE_MODE_ENABLED ) printf ( " \n In ftpExecute ERROR: SESSION TIMED OUT for socket = %d \n " , ctrlSocket ) ;
ftpSendMsg ( MSG_NORMAL , n , 421 , ftpMsg036 ) ;
ftpUntrackSocket ( ctrlSocket ) ;
ftpCloseSession ( n ) ;
}
}
}
2011-01-09 04:49:21 +00:00
}
2011-01-20 15:56:30 +00:00
return processedWork ;
}
/**
* @ brief Shut down the server
*
* Cuts all tcp - connections and frees all used resources .
* @ return 0
*/
int ftpShutdown ( void )
{
int n ;
if ( VERBOSE_MODE_ENABLED ) printf ( " About to Shutdown Feathery FTP-Server server [%d] \n " , server ) ;
ftpUntrackSocket ( server ) ;
2011-01-15 21:53:00 +00:00
ftpCloseSocket ( & server ) ;
2011-01-20 15:56:30 +00:00
//ftpCloseSocket(serverPassivePort);
if ( VERBOSE_MODE_ENABLED ) printf ( " About to Shutdown clients \n " ) ;
for ( n = 0 ; n < MAX_CONNECTIONS ; n + + )
{
if ( ftpGetSession ( n ) - > open )
{
2011-01-06 00:52:00 +00:00
ftpUntrackSocket ( ftpGetSession ( n ) - > ctrlSocket ) ;
2011-01-02 09:33:37 +00:00
}
2011-01-20 15:56:30 +00:00
ftpCloseSession ( n ) ;
}
if ( VERBOSE_MODE_ENABLED ) printf ( " About to Shutdown stack \n " ) ;
ftpArchCleanup ( ) ;
return 0 ;
}