📄 filesend.cpp
字号:
// FileSend.cpp : implementation file
//
#include "stdafx.h"
#include "Netmsg.h"
#include "FileSend.h"
#include "ContactView.h"
#include "FXFileSend.h"
#include "TransferStatus.h"
#include "ConversationThread.h"
#include "Conversation.h"
#include "StatusThread.h"
#include "NetSocket.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
char *FormatBytes(unsigned long bytes);
//The file send engine
BEGIN_MESSAGE_MAP(CFileSocketThread, CWinThread)
//{{AFX_MSG_MAP(CPopWndThread)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CFileSocketThread::CFileSocketThread(CContact *pContact, bool bSend, char *szFileName, int nPort, unsigned long lFileLen)
{
Sending = bSend;
Finished = false;
hFile = NULL;
Sock = NULL;
FileName = szFileName;
RemotePort = nPort;
FileLen = lFileLen;
SendSock = NULL;
RecvSock = NULL;
Contact = pContact;
Transfered = 0L;
LastTransfered = 0L;
StatusDlg = NULL;
StatusConv = NULL;
}
CFileSocketThread::~CFileSocketThread()
{
}
BOOL CFileSocketThread::InitInstance()
{
HWND ParentWnd;
if (Contact->IsConvWindowOpen()) //file transfer can be displayed in either a seperate dialog or
{ //in the conversation window depending if it is active or not.
ParentWnd = Contact->pThread->Conv->GetSafeHwnd();
StatusConv = Contact->pThread->Conv;
DlgMode = 0;
}
else
{
CStatusThread *StatusThread = new CStatusThread();
StatusThread->CreateThread();
while (!StatusThread->Init)
{
Sleep(1); //synchronise threads
}
StatusDlg = StatusThread->Dialog;
ParentWnd = StatusDlg->GetSafeHwnd();
DlgMode = 1;
}
if (Sending)
strcpy(szFile, "*.*");
else
strcpy(szFile, FileName);
if (DlgMode)
{
StatusDlg->SetStatus("Choosing local file...");
}
else
{
//nothing
}
if ((!Sending) || (Sending && !FileName))
{
if (!GetFileName(Sending, ParentWnd, szFile))
{
::SendMessage(GetApp()->View->GetSafeHwnd(), WM_CANCELXFER, 0, (LPARAM) Contact);
if (DlgMode)
{
StatusDlg->Remove();
}
else
{
StatusConv->Remove();
}
PostThreadMessage(WM_QUIT, 0, 0);
return TRUE;
}
}
else
{
strcpy(szFile, FileName);
}
if (Sending)
{
XFER *Xfer = new XFER; //remember to delete
unsigned long dwUpper, dwLower;
hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (!hFile)
{
MessageBox(ParentWnd, "A problem occured when attempting to open this file", "Send error", MB_OK|MB_ICONSTOP);
if (DlgMode)
{
StatusDlg->Remove();
}
else
{
StatusConv->Remove();
}
delete Xfer;
PostThreadMessage(WM_QUIT, 0, 0);
return TRUE;
}
dwLower = GetFileSize(hFile, &dwUpper);
if (dwUpper || !dwLower)
{
MessageBox(ParentWnd, "A problem with the file size is preventing this program from sending the file", "Send error", MB_OK|MB_ICONSTOP);
if (DlgMode)
{
StatusDlg->Remove();
}
else
{
StatusConv->Remove();
}
delete Xfer;
PostThreadMessage(WM_QUIT, 0, 0);
return TRUE;
}
Xfer->Contact = Contact;
Xfer->filelen = dwLower;
Xfer->port = GetFreePort();
nopath(Xfer->filename, szFile);
FileLen = dwLower;
RemotePort = Xfer->port;
if (DlgMode)
{
StatusDlg->InitStatus(this, Contact, Sending, szFile);
}
else
{
if (!StatusConv->InitStatus(this, NULL, Sending, szFile))
MessageBox(NULL, "An internal error has occurred (CConversation::InitStatus() Failed)", "Error", MB_ICONSTOP | MB_OK);
}
::SendMessage(GetApp()->View->GetSafeHwnd(), WM_REQUESTXFER, 0, (LPARAM) Xfer);
if (DlgMode)
{
StatusDlg->SetStatus("Waiting for remote user to accept...");
}
else
{
StatusConv->SetStatus("Waiting for remote user to accept...");
}
Sock = new CFXListen(this);
if (!Sock->Create(RemotePort))
{
char buf[512];
sprintf(buf, "Unable to port %d. transfer will not take place.", RemotePort);
MessageBox(ParentWnd, buf, "File transfer", MB_OK|MB_ICONSTOP);
if (DlgMode)
{
StatusDlg->Remove();
}
else
{
StatusConv->Remove();
}
PostThreadMessage(WM_QUIT, 0, 0);
return TRUE;
}
else
Sock->Listen();
}
else
{
hFile = CreateFile(szFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
if (!hFile)
{
MessageBox(ParentWnd, "A problem occured when attempting to save this file", "Send error", MB_OK|MB_ICONSTOP);
if (DlgMode)
{
StatusDlg->Remove();
}
else
{
StatusConv->Remove();
}
PostThreadMessage(WM_QUIT, 0, 0);
return TRUE;
}
RecvSock = new CFXFileRecv(this, hFile, FileLen);
RecvSock->Create();
if (!RecvSock->Connect(Contact->GetHostName().Get(), RemotePort))
{
MessageBox(ParentWnd, "Unable to connect to remote machine. transfer will not take place", "File transfer", MB_OK|MB_ICONSTOP);
if (DlgMode)
{
StatusDlg->Remove();
}
else
{
StatusConv->Remove();
}
PostThreadMessage(WM_QUIT, 0, 0);
return TRUE;
}
else
{
if (DlgMode)
StatusDlg->InitStatus(this, Contact, Sending, szFile);
else
StatusConv->InitStatus(this, NULL, Sending, szFile);
TransferStarted();
}
}
return TRUE;
}
int CFileSocketThread::GetFreePort()
{
int Baseport = 8401, port;
for (port = Baseport; port < 9000; port++)
{
POSITION pos;
pos = GetApp()->View->List.GetHeadPosition();
while (pos)
{
CContact *pContact = GetApp()->View->List.GetNext(pos);
if (pContact->IsTransfering() && pContact != Contact)
{
port++;
continue;
}
}
break;
}
return port;
}
void CFileSocketThread::TransferAccepted()
{
if (DlgMode)
{
if (!::IsWindow(StatusDlg->m_hWnd)) return;
StatusDlg->SetStatus("Remote user is choosing save file path...");
}
else
{
StatusConv->SetStatus("Remote user is choosing save file path...");
}
}
void CFileSocketThread::TransferStarted()
{
LastUpdated = 0;
LastUpdated2 = 0;
if (RecvSock)
if (RecvSock->Stop)
return;
if (SendSock)
if (SendSock->Stop)
return;
if (DlgMode)
{
StatusDlg->SetStatus("Transfer in progress");
}
else
{
char buf[512], buf2[512];;
nopath(buf2, szFile);
sprintf(buf, "%s: %s", Sending ? "Sending" : "Receiving", buf2);
StatusConv->SetStatus(buf);
}
}
void CFileSocketThread::TransferComplete()
{
Finished = true;
if (hFile)
{
CloseHandle(hFile);
hFile = NULL;
}
if (RecvSock)
if (RecvSock->Stop)
return;
if (SendSock)
if (SendSock->Stop)
return;
if (DlgMode)
{
StatusDlg->SetStatus("Transfer complete!");
StatusDlg->SetPercent(100);
StatusDlg->Ended();
}
else
{
StatusConv->SetStatus("Transfer complete!");
StatusConv->SetPercent(100);
StatusConv->Ended();
}
}
void CFileSocketThread::TransferFailed()
{
Finished = true;
if (hFile)
{
CloseHandle(hFile);
hFile = NULL;
}
if (RecvSock)
if (RecvSock->Stop)
return;
if (SendSock)
if (SendSock->Stop)
return;
if (DlgMode)
{
if (!::IsWindow(StatusDlg->m_hWnd)) return;
StatusDlg->SetStatus("Transfer failed");
StatusDlg->Ended();
}
else
{
StatusConv->SetStatus("Transfer failed");
StatusConv->Ended();
}
}
void CFileSocketThread::UpdateTransfered(int nBytes)
{
if (RecvSock)
if (RecvSock->Stop)
return;
if (SendSock)
if (SendSock->Stop)
return;
Transfered += nBytes;
if ((GetTickCount() - LastUpdated) > 1000)
{
if (DlgMode)
{
StatusDlg->SetStats(Transfered, Transfered - LastTransfered);
}
else
{
StatusConv->SetStats(Transfered, Transfered - LastTransfered);
}
LastUpdated = GetTickCount();
LastTransfered = Transfered;
}
if (GetTickCount() - LastUpdated2 > 50)
{
float fldone = ((float)Transfered / (float)FileLen) * 100;
if (DlgMode)
{
StatusDlg->SetPercent((int) fldone);
}
else
{
StatusConv->SetPercent((int) fldone);
}
LastUpdated2 = GetTickCount();
}
}
bool CFileSocketThread::GetFileName(bool bSending, HWND hWndOwner, char *FileName)
{
char file[1024];
bool bResult;
strncpy(file, FileName, sizeof(file));
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWndOwner;
ofn.lpstrFile = file;
ofn.nMaxFile = sizeof(file);
ofn.lpstrFilter = "All Files (*.*)\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = bSending ? OFN_FILEMUSTEXIST : OFN_OVERWRITEPROMPT;
if (Sending)
bResult = GetOpenFileName(&ofn) ? true : false;
else
bResult = GetSaveFileName(&ofn) ? true : false;
if (bResult)
{
strcpy(FileName, ofn.lpstrFile);
return true;
}
else
return false;
}
void CFileSocketThread::Kill()
{
if (Sending)
{
if (SendSock)
{ //since sock threads are going hard nut the only way to stop them is to
//set a boolean that it checks every cycle to false from another thread
SendSock->Stop = true;
}
}
else
{
if (RecvSock)
{
RecvSock->Stop = true;
}
}
if (!Finished) GetApp()->View->SendMessage(WM_CANCELXFER, 0, (LPARAM) Contact);
PostThreadMessage(WM_QUIT, 0, 0);
return;
}
int CFileSocketThread::ExitInstance()
{
if (hFile)
{
CloseHandle(hFile);
hFile = NULL;
}
if (Sending)
{
delete SendSock;
if (Sock)
delete Sock;
}
else
{
delete RecvSock;
}
Contact->Flags &= ~CFL_TRANSFER;
return CWinThread::ExitInstance();
}
/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -