⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zmodemcore.cpp

📁 zmodemclass的经典源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
// project:		ZModem
// author:		Frank Weiler, Genshagen, Germany
// version:		0.91
// date:		October 10, 2000
// email:		frank@weilersplace.de
// copyright:	This Software is OpenSource.
// file:		ZModemCore.cpp
// description:	A class that implements a basic ZModem protocol.
//				Not all possible features are supported, especially
//				no support for buffersizes greater than 1024.
//				Sending data is done with 1024 buffersize,
//				receiving is event-driven using overlapped I/O.
//-----------------------------------------------------------------------------

#include "stdafx.h"
#include "ZModemCore.h"

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

//-----------------------------------------------------------------------------
// purpose:	construction
// params:	howner			->	handle of the Owner Window
//			hcomm			->	handle of the modem ressource, got from TAPI
//			hcancelevent	->  handle of an event signaling user-break
CZModemCore::CZModemCore(HWND howner,HANDLE hcomm,HANDLE hcancelevent)
//-----------------------------------------------------------------------------
{
	m_hOwner = howner;
	m_hcomm = hcomm;
	m_hCancelEvent = hcancelevent;
	m_ZModemComm = new CZModemComm(m_hcomm,m_hCancelEvent);
	m_ZModemFile = new CZModemFile(howner);
	maxTx = ZMCORE_MAXTX;
}

//-----------------------------------------------------------------------------
// purpose:	destruction
CZModemCore::~CZModemCore()
//-----------------------------------------------------------------------------
{
	delete m_ZModemComm;
	delete m_ZModemFile;
}

//-----------------------------------------------------------------------------
// purpose:	sending files
// params:	filelist	->	Array of filenames (full path) to send
// returns:	success
bool CZModemCore::Send(CStringArray* filelist)
//-----------------------------------------------------------------------------
{	// 
	bool fin=false,quit=false,ok=true;
	int tries=0;
	// 
	this->ResetAll();
	if(filelist == NULL)
		return false;
	if(filelist->GetSize() == 0)
		return false;
	m_Filelist = filelist;
	bufTop = mainBuf + (sizeof mainBuf);
	m_ZModemComm->ClearInbound();//clear all pending data from modem
	sendrz();//send initialization string 
	while(ALLOK && !fin && (tries < 100))
	{
		quit=false;
		sendZRQINIT();//send ZRQINIT
		getZMHeader();
		if(ALLOK)
		{
			switch(headerType)
			{
				case ZCAN://canceled from other side
				{
					TRACE("set error %s\n","ZMODEM_GOTZCAN");
					SetLastError(ZMODEM_GOTZCAN);
					::PostMessage(m_hOwner,WM_USER_ZMODEMERROR,(WPARAM)ZMODEM_GOTZCAN,0L);
					quit=true;
					fin=true;
					break;
				}
				case ZRINIT:// ok, let's communicate
				{
            		TRACE("ZRINIT erhalten");
					//validate CRC-32-property and CANFX-property
					static int Rxflags = 0377 & headerData[3];
					bcrc32 = (Rxflags & CANFC32) != 0;
					bcanfdx = Rxflags & CANFDX;
					TRACE("bcanfdx ist %s\n",bcanfdx ? "true" : "false");
					TRACE("bcrc32 ist %s\n",bcrc32 ? "true" : "false");
					// start sending all files
					ok=sendFiles();
					fin=true;
					break;
				}
				case ZCHALLENGE:
				{
					TRACE("got ZCHALLENGE");
					sendZACK();
					break;
				}
				default:
				{
					TRACE("got unexpected header");
					tries++;
					break;
				}
			}//switch
		}//if(ALLOK)
		else
		{
			DWORD err=GetLastError();
			if((err==ZMODEM_TIMEOUT) || (err==ZMODEM_CRCXM) ||
				(err==ZMODEM_CRC32) || (err==ZMODEM_BADHEX))
			{
				::PostMessage(m_hOwner,WM_USER_ZMODEMERROR,(WPARAM)err,0L);
				if(tries < 100)
				{
					SetLastError(0);
					tries++;
				}
			}
		}
	}//while(...)
	// sendig is over, finish session
	if(ALLOK)
	{
		quit=false;
		tries=0;
		sendZFIN();
		while(ALLOK && !quit)
		{
      		getZMHeader();
			if(ALLOK && (headerType == ZFIN))
         		quit=true;//other side has finish accepted
			else
			{
				if(tries < 100)
				{
					SetLastError(0);
					sendZFIN();
					tries++;
				}
			}
		}
		if(ALLOK)
			sendOO();//over and out
	}
	return(quit && fin && ok);
}

//-----------------------------------------------------------------------------
// purpose:	receiving files
// params:	filelist	->	Array of filenames received
//			receivedir	->  folder to save the received files
// returns:	success
bool CZModemCore::Receive(CStringArray* filelist,CString receivedir)
//-----------------------------------------------------------------------------
{	// 
	bool fin,quit;
	int tries;
	// 
	this->ResetAll();
	if(filelist == NULL)
		return false;
	if(filelist->GetSize() == 0)
		return false;
	m_Filelist = filelist;
	if(!receivedir.IsEmpty())
		m_ZModemFile->SetReceivingDir(receivedir);
	bufTop = mainBuf + (sizeof mainBuf);
	m_ZModemComm->ClearInbound();
	skip = false;
	fin = false;
	while(ALLOK && !fin)
	{
		sendZRINIT();
		quit = false;
		tries = 0;
		while(ALLOK && !quit)
		{
			getZMHeader();
			if(ALLOK)
			{
				if(headerType == ZFIN)//other side has finish signaled
				{
					sendZFIN();//reply
					getOO();//try to get over and out signal
					quit = true;
					fin = true;
				}
				else if(headerType == ZRQINIT)
				{
					if(tries < 100)
					{
						sendZRINIT();
						tries++;
					}
					else
					{
						TRACE("set error %s\n","ZMODEM_INIT");
						SetLastError(ZMODEM_INIT);
					}
				}
				else if(headerType == ZFILE)//file transfer signaled
				{
					skip = false;
					getFILEINFO();//extract the FILEINFO from data block
					if(ALLOK)
					{
						receiveFile();//receive current file
						if(ALLOK)
							m_Filelist->Add(m_ZModemFile->GetReceivedFileName());
						quit = true;
					}
					else if(GetLastError()==ZMODEM_CRC32)
					{
						::PostMessage(m_hOwner,WM_USER_ZMODEMERROR,(WPARAM)ZMODEM_CRC32,0L);
						if(tries < 100)
						{
							SetLastError(0);
							sendZRINIT();
							tries++;
						}
					}
				}
			}
			else
			{
				DWORD err=GetLastError();
				if((err==ZMODEM_TIMEOUT) || (err==ZMODEM_CRCXM) ||
					(err==ZMODEM_CRC32) || (err==ZMODEM_BADHEX))
				{
					::PostMessage(m_hOwner,WM_USER_ZMODEMERROR,(WPARAM)err,0L);
					if(tries < 100)
					{
						SetLastError(0);
						sendZRINIT();
						tries++;
					}
				}
			}
		}
	}
	Sleep(4000);//wait 4 seconds tu ensure that the other side really get our ZEOF 
	return(ALLOK);
}

// Layer 3 ####################################################################
//-----------------------------------------------------------------------------
void CZModemCore::ResetAll()
//-----------------------------------------------------------------------------
{
	ch = 0;
	gotSpecial =0;
	m_bWait = true;
	gotHeader =0;
	frameType =0;
	headerType =0;
	memset(headerData,0,4);
	moreData=0;
	memset(mainBuf,0,sizeof mainBuf);
	bufPos = NULL;
	bufTop = NULL;
	goodOffset=0;
	bytes=0;
	bcrc32=false,bcanfdx=false;
	skip=false;
	m_ZModemFile->ResetAll();
	m_ZModemComm->ResetAll();
}

//-----------------------------------------------------------------------------
bool CZModemCore::sendFiles()
//-----------------------------------------------------------------------------
{	// 
	bool gotfile;
	int count = 0;
	int tries;
	bool sent;
	bool rw=true;
	DWORD offset;
	int i=0;
	bool fileinfosent=false;
	// 
	int nSize=m_Filelist->GetSize();

	while(ALLOK && ( i < nSize))
	{
		gotfile = m_ZModemFile->Open(m_Filelist->GetAt(i),OPEN_EXISTING);
     	if(gotfile)
        	TRACE("SendFiles filename %s",m_Filelist->GetAt(i));
		else
      		break;
		goodOffset = 0;
		tries = 0;
		sent = false;
		while(ALLOK && (tries < 10) && !sent)
		{
			if(!fileinfosent)
			{
				sendZFILE();
				sendFILEINFO();
				fileinfosent=true;
			}	
			getZMHeader();
			if(ALLOK)
			{
				if(headerType == ZRINIT)
				{
            		TRACE("got ZRINIT");
					tries++;
				}
				else if (headerType == ZRPOS)
				{
           			TRACE("got ZRPOS");
					offset=(headerData[3] << 24) | (headerData[2] << 16) |
							 (headerData[1] << 8)  | headerData[0];
					m_ZModemFile->SetPos(offset);
					goodOffset = offset;
					rw=sendFile();
					sent = true;
				}
				else if(headerType == ZNAK)//nochmal senden
				{
            		TRACE("got ZNAK");
					fileinfosent=false;
				}
				else if(headerType == ZSKIP)//bitte n鋍hstes file
				{
					TRACE("got ZSKIP");
            		sent=true;
				}
				else if(headerType== ZCRC)
				{
					TRACE("got ZCRC, no action");
				}
			}
			else
			{
				DWORD err=GetLastError();
				if(err==ZMODEM_TIMEOUT)
				{
					SetLastError(0);
				}
				tries++;
			}
		}
		m_ZModemFile->Finish();
		i++;//next file
	}
	return rw;
}

//-----------------------------------------------------------------------------
bool CZModemCore::sendFile()
//-----------------------------------------------------------------------------
{	// 
	int tries = 0;
	DWORD lastpos = 0;
	DWORD newpos;
	int state;
	bool sentfile = false;
	bool rw=true;
	// 
	state = SM_SENDZDATA;
	while(ALLOK && !sentfile)
	{
		switch(state)
		{
			case SM_SENDZDATA:
			{
	       		moreData = 1;
				int erg=m_ZModemFile->GetData(mainBuf,maxTx,&bytes);
				if(erg==ZMODEMFILE_NOMOREDATA)
				{
					state = SM_SENDZEOF;
					moreData = 0;
				}
				else if(erg == ZMODEMFILE_OK)
				{
					sendZDATA();
					state = SM_SENDDATA;
				}
				else//ZMODEMFILE_ERROR
				{
					TRACE("set error ZMODEM_ERROR_FILE");
					SetLastError(ZMODEM_ERROR_FILE);
				}
				break;
			}
			case SM_SENDDATA:
				while (ALLOK && (state == SM_SENDDATA))
				{
					sendData();
					getZMHeaderImmediate();
					DWORD err=GetLastError();
					if(ALLOK && (headerType == ZRPOS))
					{
						state = SM_ACTIONRPOS;
					}
					else
					{
						DWORD err=GetLastError();
						if(err==ZMODEM_TIMEOUT)//got no header
							SetLastError(0);
						if(ALLOK)
						{
							if(!moreData)
							{
								state = SM_SENDZEOF;
								break;
							}
							else
								m_ZModemFile->GetData(mainBuf,maxTx,&bytes);
						}
					}
				}//while
				break;
			case SM_ACTIONRPOS:
				newpos=headerData[0] | (headerData[1] << 8) |
						 (headerData[2] << 16) | (headerData[3] << 24);
				TRACE("in SM_ACTIONRPOS\n");
#ifdef _DEBUG
				char out[1000];
				wsprintf(out,"newpos: %lu",newpos);
				TRACE(out);
#endif
				if(newpos <= lastpos)
					tries++;
				else
					 tries = 0;
				m_ZModemFile->SetPos(newpos);
				::PostMessage(m_hOwner,WM_USER_ZMODEMERROR,ZMODEM_POS,0L);
				::PostMessage(m_hOwner,WM_USER_ZMODEMRPOS,newpos,0L);
				goodOffset = newpos;
				state = SM_SENDZDATA;
				break;
			case SM_SENDZEOF:
				TRACE("in SM_SENDZEOF\n");
				sendZEOF();
				tries = 0;
				state = SM_WAITZRINIT;
				break;
			case SM_WAITZRINIT:
				TRACE("in SM_WAITZRINIT\n");
				getZMHeader();
				if(ALLOK && (headerType == ZRINIT))
					sentfile = true;
				else if (ALLOK && (headerType == ZRPOS))
				{
					state = SM_ACTIONRPOS;
				}
				//erweitert ...
				else if(ALLOK && (headerType == ZFERR))
				{
					TRACE("got ZFERR, finish sending");
					sentfile = true;
					rw=false;
				}
				else if(ALLOK && (headerType == ZFIN))
				{
					TRACE("got ZFIN, finish sending");
					sentfile = true;
				}
				else
				{
					tries++;
					if(tries < 100)
						SetLastError(0);
				}
				break;
		}//switch
	}//while
	return rw;
}

//-----------------------------------------------------------------------------
void CZModemCore::receiveFile()
//-----------------------------------------------------------------------------
{	// 
	bool quit;
	int tries;
	// 
	goodOffset = 0;
	m_ZModemFile->OpenReceivingFile(&goodOffset,&skip);
	if(skip)
		sendZSKIP();
	else
	{
		sendZRPOS();
		quit = false;
		tries = 0;
		while(ALLOK && !quit)
		{
			getZMHeader();
			if(ALLOK)
			{
				if(headerType == ZFILE)
				{
					if(tries < 100)
					{
						sendZRPOS();
						tries++;
					}
					else
					{
						TRACE("set error %s\n","ZMODEM_POS");
						SetLastError(ZMODEM_POS);
						::PostMessage(m_hOwner,WM_USER_ZMODEMERROR,ZMODEM_POS,0L);
					}
				}
				else if(headerType == ZDATA)
				{
					receiveData();
					quit = true;
				}
			}
			else
			{
				DWORD err=GetLastError();
				if((err==ZMODEM_TIMEOUT) || (err==ZMODEM_CRCXM) ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -