Viewing file: ExternalIpCheck.cpp (7.82 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
// FileZilla Server - a Windows ftp server
// Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
// 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 2
// 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "stdafx.h"
#include "ExternalIpCheck.h"
#include "ServerThread.h"
#include "Options.h"
//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////
#define TIMERINTERVAL 30
CExternalIpCheck::CExternalIpCheck(CServerThread *pOwner)
{
ASSERT(pOwner);
m_pOwner = pOwner;
m_bActive = FALSE;
m_nRetryCount = 0;
m_nTimerID = SetTimer(0, 0, TIMERINTERVAL * 1000, 0);
m_bTriggerUpdateCalled = FALSE;
m_nFailedConnections = 0;
m_nElapsedSeconds = 0;
if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
return;
if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 2)
Start();
else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1)
{
CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP);
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
#ifdef _UNICODE
sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname));
#else
sockAddr.sin_addr.s_addr = inet_addr(hostname);
#endif
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
#ifdef _UNICODE
lphost = gethostbyname(ConvToLocal(hostname));
#else
lphost = gethostbyname(hostname);
#endif
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
Close();
m_nRetryCount++;
m_bActive = FALSE;
return;
}
}
const char *ip = inet_ntoa(sockAddr.sin_addr);
if (!ip)
return;
#ifdef _UNICODE
m_IP = ConvFromLocal(ip);
#else
m_IP = ip;
#endif
}
}
CExternalIpCheck::~CExternalIpCheck()
{
Close();
}
void CExternalIpCheck::OnReceive(int nErrorCode)
{
if (!m_bActive)
return;
if (nErrorCode)
{
m_bActive = FALSE;
Close();
m_nRetryCount++;
return;
}
char buffer[1000];
int len = Receive(buffer, 999);
if (len == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
return;
Close();
m_nRetryCount++;
m_bActive = FALSE;
return;
}
buffer[len] = 0;
char *p = strstr(buffer, "\r\n\r\n");
if (!p)
p = strstr(buffer, "\n\n");
if (!p)
{
Close();
m_nRetryCount++;
m_bActive = FALSE;
return;
}
while (*p && (*p == '\n' || *p == '\r'))
p++;
if (!*p)
{
Close();
m_nRetryCount++;
m_bActive = FALSE;
return;
}
char * ip = p;
while (*p && *p != '\n' && *p != '\r')
p++;
*p = 0;
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = inet_addr(ip);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(ip);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
Close();
m_nRetryCount++;
m_bActive = FALSE;
return;
}
}
ip = inet_ntoa(sockAddr.sin_addr);
if (!ip)
{
Close();
m_nRetryCount++;
m_bActive = FALSE;
return;
}
#ifdef _UNICODE
m_IP = ConvFromLocal(ip);
#else
m_IP = ip;
#endif
m_nFailedConnections = 0;
Close();
m_nRetryCount = 0;
m_bActive = FALSE;
}
void CExternalIpCheck::OnConnect(int nErrorCode)
{
if (!m_bActive)
return;
if (nErrorCode)
{
m_bActive = FALSE;
Close();
m_nRetryCount++;
return;
}
CStdStringA address = "GET " + m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIPSERVER) + " HTTP/1.0\r\nUser-Agent: FileZilla Server\r\n\r\n";
const char *buffer = address;
int len = strlen(buffer);
if (Send(buffer, len) != len)
{
m_bActive = FALSE;
Close();
m_nRetryCount++;
}
OnReceive(0);
}
void CExternalIpCheck::OnTimer()
{
if (m_nElapsedSeconds <= 1000000)
m_nElapsedSeconds += TIMERINTERVAL;
if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
{
m_nRetryCount = 0;
Close();
m_bActive = FALSE;
return;
}
else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1)
{
m_nRetryCount = 0;
Close();
m_bActive = FALSE;
CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP);
SOCKADDR_IN sockAddr;
memset(&sockAddr,0,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
#ifdef _UNICODE
sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname));
#else
sockAddr.sin_addr.s_addr = inet_addr(hostname);
#endif
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
#ifdef _UNICODE
lphost = gethostbyname(ConvToLocal(hostname));
#else
lphost = gethostbyname(hostname);
#endif
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
Close();
m_nRetryCount++;
m_bActive = FALSE;
return;
}
}
const char *ip = inet_ntoa(sockAddr.sin_addr);
if (!ip)
return;
#ifdef _UNICODE
m_IP = ConvFromLocal(ip);
#else
m_IP = ip;
#endif
m_nFailedConnections = 0;
return;
}
if (!m_bActive && m_nRetryCount)
{
if (m_nElapsedSeconds > 60 && m_nRetryCount < 5)
{
Start();
return;
}
else if (m_nElapsedSeconds > 300 && m_nRetryCount < 10)
{
Start();
return;
}
else if (m_nElapsedSeconds > 900 && m_nRetryCount < 20)
{
Start();
return;
}
else if (m_nElapsedSeconds > 3600)
{
Start();
return;
}
}
else if (m_bActive)
{
if (m_nElapsedSeconds > 30)
{
m_bActive = FALSE;
Close();
m_nRetryCount++;
m_nElapsedSeconds = 0;
}
}
else
{
if (m_nElapsedSeconds > 300 && m_bTriggerUpdateCalled)
Start();
else if (m_nElapsedSeconds > 3600)
Start();
}
}
void CExternalIpCheck::OnClose(int nErrorCode)
{
if (m_bActive)
{
m_bActive = FALSE;
Close();
m_nRetryCount++;
}
}
void CExternalIpCheck::Start()
{
if (m_bActive)
return;
CStdString address = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIPSERVER);
if (address.Left(7) == _T("http://"))
address = address.Mid(7);
int pos = address.Find('/');
if (pos != -1)
address = address.Left(pos);
if (address == _T(""))
return;
m_bTriggerUpdateCalled = FALSE;
m_nElapsedSeconds = 0;
Create();
BOOL res = Connect(address, 80);
if (res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK)
m_nRetryCount++;
else
m_bActive = TRUE;
}
void CExternalIpCheck::TriggerUpdate()
{
if (m_bActive)
return;
m_bTriggerUpdateCalled = TRUE;
if (m_nFailedConnections < 100000)
m_nFailedConnections++;
}
CStdString CExternalIpCheck::GetIP(const CStdString& localIP)
{
if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
return _T("");
CStdString ip;
switch (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
{
case 0:
return _T("");
case 2:
if (!m_bActive && !m_nRetryCount && localIP != _T(""))
{
if (localIP == m_IP)
m_nElapsedSeconds = 0;
}
case 1:
ip = m_IP;
break;
}
return ip;
}
|