MegaGlest/source/shared_lib/sources/feathery_ftp/ftpRuntime.c
2012-11-12 04:50:34 +00:00

289 lines
7.6 KiB
C

/**
* 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
*/
LOCAL socket_t server;
LOCAL int serverListenPort;
LOCAL int serverPassiveListenPort;
//LOCAL socket_t serverPassivePort;
void ftpInit(ftpFindExternalFTPServerIpType cb1, ftpAddUPNPPortForwardType cb2,
ftpRemoveUPNPPortForwardType cb3, ftpIsValidClientType cb4,
ftpIsClientAllowedToGetFileType cb5) {
ftpFindExternalFTPServerIp = cb1;
ftpAddUPNPPortForward = cb2;
ftpRemoveUPNPPortForward = cb3;
ftpIsValidClient = cb4;
ftpIsClientAllowedToGetFile = cb5;
}
int ftpGetListenPort()
{
return serverListenPort;
}
int ftpGetPassivePort()
{
return serverPassiveListenPort;
}
//socket_t ftpGetServerPassivePortListenSocket()
//{
// return serverPassivePort;
//}
/**
* @brief Initializes and starts the server
*
*
* @return - 0: server started successfully
* - -1: could not create server socket
*/
int ftpStart(int portNumber)
{
serverListenPort = portNumber;
serverPassiveListenPort = portNumber + 1;
server = -1; // set server socket to invalid value
//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\terror\n");
return -1;
}
if(VERBOSE_MODE_ENABLED) printf("\t\tok\n");
if(VERBOSE_MODE_ENABLED) printf("Server successfully started\n");
ftpTrackSocket(server); // add socket to "watchlist"
/*
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\tpassive port error\n");
return -1;
}
if(VERBOSE_MODE_ENABLED) printf("\t\tok\n");
if(VERBOSE_MODE_ENABLED) printf("Server passive port successfully started\n");
*/
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)
{
int processedWork=0;
int n=0;
int socksRdy=0;
ftpSession_S *pSession=NULL;
int sessionId=0;
//int activeJobs=0;
int len;
int bufLen;
int activeJobs = ftpGetActiveTransCnt(); // are there any active transmitions?
//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("\nIn ftpExecute ERROR: SESSION TIMED OUT for socket = %d\n",ctrlSocket);
ftpSendMsg(MSG_NORMAL, n, 421, ftpMsg036);
ftpUntrackSocket(ctrlSocket);
ftpCloseSession(n);
}
}
}
}
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);
ftpCloseSocket(&server);
//ftpCloseSocket(serverPassivePort);
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown clients\n");
for(n = 0; n < MAX_CONNECTIONS; n++)
{
if(ftpGetSession(n)->open)
{
ftpUntrackSocket(ftpGetSession(n)->ctrlSocket);
}
ftpCloseSession(n);
}
if(VERBOSE_MODE_ENABLED) printf("About to Shutdown stack\n");
ftpArchCleanup();
return 0;
}