/****************************************************************/
/*																*/
/*  CONNECTTHREAD.CPP											*/
/*																*/
/*  Implementation of the Connect Thread.						*/
/*	Created when a client logs on to the server and processes	*/
/*  'Send' commando's.											*/
/*																*/
/*  Programmed by LYFZ van der Meer							    */
/*	http://www.LYFZvandermeer.nl								*/
/*																*/
/*  Last updated: 15 july 2002									*/
/*																*/
/****************************************************************/
//��ConnectThread.cpp�ļ���ʵ�������̵߳Ĵ���������߳�����������ͻ��˵����ӡ�
//��һ���ͻ���¼�����������߳̽���������������"Send"���

#include "stdafx.h"
#include "LYFZIPReceiveApp.h"
#include "LYFZIPReceive.h"
#include "ApplicationDlg.h"
#include "ConnectThread.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CLYFZIPReceive *g_pWndServer;

IMPLEMENT_DYNCREATE(CConnectThread, CWinThread)


/********************************************************************/
/*																	*/
/* Function name : CConnectThread::CConnectThread					*/
/* Description   : Constructor										*/
/*																	*/
/********************************************************************/
CConnectThread::CConnectThread()
{
	m_nReceivedBytes = 0;
	m_nSentBytes = 0;
	m_nTimerID = 0;
	m_LastDataTransferTime = CTime::GetCurrentTime();
}


/********************************************************************/
/*																	*/
/* Function name : CConnectThread::~CConnectThread					*/
/* Description   : Destructor										*/
/*																	*/
/********************************************************************/
CConnectThread::~CConnectThread()
{
}


/********************************************************************/
/*																	*/
/* Function name : InitInstance										*/		
/* Description   : Perform tasks that must be completed when the	*/
/*				   thread is first created.							*/
/*																	*/
/********************************************************************/
//��ʼ���߳�
BOOL CConnectThread::InitInstance()
{
	try
	{
		g_pWndServer->m_CriticalSection.Lock();
		g_pWndServer->m_ThreadList.AddTail(this);
		g_pWndServer->m_CriticalSection.Unlock();

 
		// ��CSocket������socket�����
		m_ConnectSocket.Attach(m_hSocket);
 
		CString strIPAddress;
		UINT nPort;
		m_ConnectSocket.GetPeerName(strIPAddress, nPort);
		m_strRemoteHost=strIPAddress;

		// ֪ͨ������һ���µ����ӵ���
		g_pWndServer->SendMessage(WM_THREADSTART, (WPARAM)this, 0);
		
		if (g_pWndServer->CheckMaxUsers())
		{
		//	m_ConnectSocket.SendResponse("421 Too many users are connected, please try again later.");
			PostThreadMessage(WM_QUIT,0,0);WriteLogin("���ӳ����������");
		}
		else
		if (!g_pWndServer->IsIPAddressAllowed(strIPAddress))
		{
		//	m_ConnectSocket.SendResponse("421 Access denied, IP address was rejected by the server.");
			PostThreadMessage(WM_QUIT,0,0);WriteLogin("�Ƿ�IP��ַ");
		}
		else
		{
		//	AfxMessageBox(strIPAddress);
			// ���ͻ�ӭ��Ϣ���ͻ���
		//	m_ConnectSocket.SendResponse("220 %s", g_pWndServer->GetWelcomeMessage());
			m_nTimerID = ::SetTimer(NULL, 0, 1000, TimerProc); 
		}
	}
	catch(CException *e) 
	{
		e->Delete();
	}
	return TRUE;
}


/********************************************************************/
/*																	*/
/* Function name : ExitInstance										*/		
/* Description   : Perform clean-up when the thread terminates.		*/
/*																	*/
/********************************************************************/
//�߳���ֹ
int CConnectThread::ExitInstance()
{
	 
	try
	{
			 m_ConnectSocket.Close();
	}
	catch(...)
	{
	}
 
	try
	{
	
		g_pWndServer->m_CriticalSection.Lock();
		
		// ��������ɾ����ǰ�߳�
		POSITION pos = g_pWndServer->m_ThreadList.Find(this);
		if(pos != NULL)
		{
			g_pWndServer->m_ThreadList.RemoveAt(pos);
		}
		g_pWndServer->m_CriticalSection.Unlock();    		

		//֪ͨ������ѭ��
		g_pWndServer->SendMessage(WM_THREADCLOSE, (WPARAM)this, 0);
	
	}
	catch(CException *e) 
	{
		g_pWndServer->m_CriticalSection.Unlock();
		e->Delete();
	}
	return CWinThread::ExitInstance();
}


BEGIN_MESSAGE_MAP(CConnectThread, CWinThread)
	//{{AFX_MSG_MAP(CConnectThread)
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_THREADMSG, OnThreadMessage)
END_MESSAGE_MAP()



/********************************************************************/
/*																	*/
/* Function name : IncSentBytes										*/		
/* Description   : Increment number of bytes sent by the server.	*/
/*																	*/
/********************************************************************/
void CConnectThread::IncSentBytes(int nBytes)
{
	m_LastDataTransferTime = CTime::GetCurrentTime();
	m_nSentBytes += nBytes;
	// notify server class
	g_pWndServer->PostMessage(WM_THREADMSG, (WPARAM)0, (LPARAM)nBytes);
}


/********************************************************************/
/*																	*/
/* Function name : IncReceivedBytes									*/		
/* Description   : Increment number of bytes received by the server.*/
/*																	*/
/********************************************************************/
void CConnectThread::IncReceivedBytes(int nBytes)
{
	m_LastDataTransferTime = CTime::GetCurrentTime();
	m_nReceivedBytes += nBytes;
	// notify server class
	g_pWndServer->PostMessage(WM_THREADMSG, (WPARAM)1, (LPARAM)nBytes);
}


/********************************************************************/
/*																	*/
/* Function name : UpdateStatistic									*/	
/* Description   : Specific statistics has been changed.			*/
/*																	*/
/********************************************************************/
void CConnectThread::UpdateStatistic(int nType)
{
	// notify server class
	g_pWndServer->PostMessage(WM_THREADMSG, (WPARAM)2, (LPARAM)nType);
}


/********************************************************************/
/*																	*/
/* Function name : OnThreadMessage									*/		
/* Description   : Thread message received.							*/
/*																	*/
/********************************************************************/
LRESULT CConnectThread::OnThreadMessage(WPARAM wParam, LPARAM lParam)
{
	switch(wParam)
	{
		case 0: // destroy data socket
		//	AfxMessageBox("destroy conn");
			break;
		case 1: // quit !
			PostThreadMessage(WM_QUIT,0,0);
			break;
		default:
			break;
	}
	return 0L;
}


/********************************************************************/
/*																	*/
/* Function name : TimerProc										*/	
/* Description   : Callback function for timer.						*/
/*																	*/
/********************************************************************/
VOID CALLBACK CConnectThread::TimerProc(HWND hwnd, UINT uMsg, UINT uIDEvent, DWORD dwTime)
{
	CConnectThread *pThread = (CConnectThread *)AfxGetThread();

	if (uIDEvent == pThread->m_nTimerID)
	{
		int nConnectionTimeout = g_pWndServer->GetTimeout();
		// check for connection timeout
		CTime time = pThread->m_LastDataTransferTime;
		time += CTimeSpan(0, 0, 0, 60);
		if (time < CTime::GetCurrentTime())
		{
		//	pThread->m_ConnectSocket.SendResponse("426 Connection timed out, aborting transfer");
			pThread->PostThreadMessage(WM_QUIT,0,0);
		}
	}
}