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

📄 cxferthread.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				default:
					pgp_errstring("Unknown XferThread command.");
					break;
			}
			mInQueue->Free(msg);
		}
	}
	mPacketThread->SetXferThread(NULL);
	while(mSending)
	{
		if(mSending->xi.pipe)
		{
			mSending->xi.pipe->DoAbortPipe();
			if(!mSending->xi.fatalErr)
				mSending->xi.fatalErr=_pge_InternalAbort;
			mSending->xi.pipe->DoAckEndPipe();
			mXferWindow->EndSend();
		}
		DisposeSend(mSending);
	}
	while(mOverflowSends)
	{
		xsf = mOverflowSends;
		delete xsf->hash;
		mOverflowSends = xsf->next;
		pgp_free(xsf);
	}
	while(mReceiving)
	{
		if(mReceiving->xi.pipe)
		{
			mReceiving->xi.pipe->DoAbortPipe();
			mXferWindow->EndReceive();
		}
		DisposeRecv(mReceiving);
	}
	return (void *)1L;
}

void
CXferThread::CheckForNewStreams()
{
	XSendFile *xsf;
	
	if(mOverflowSends)
	{
		xsf = mOverflowSends;
		mOverflowSends = xsf->next;
		xsf->next = NIL;
		OpenStream(xsf);
#ifdef	DEBUGXFERLOG
		uchar str[128];
		GetFileName(&xsf->xi, str);
		DebugLog("Send: OpenStream: %s", str);
#endif
	}
}

XRcvFile *
CXferThread::InitRecv(uchar *p, uchar streamID, short len)
{
	StMutex mutex(*this);
	XRcvFile *nxr=NIL, *walk;
	uchar filename[MAXFILENAMELEN+1], *e, *dirspec;
	short nlen, subtype, slen, dirlen;

	// Format:
	// 8 byte salt
	// data type: 0 for files
	// 4 byte total file length
	// filename [max 256 chars], null terminated
	// subpackets*		(0 or more, in any order)
	//		subpacket type byte
	//		subpacket length byte
	//		subpacket [length]
	if(mNumReceiving >= MAXRCVFILES)
		goto error;
	if(len<XFERSALTCHECKSIZE+5)	//verify minimum length
		goto error;
	for(walk=mReceiving;walk;walk=walk->next)
		if(walk->remoteStreamID == streamID)
			goto error;
	nxr = (XRcvFile *)pgp_malloc(sizeof(XRcvFile));	pgpAssert(nxr);
	memset(nxr, 0, sizeof(XRcvFile));
	nxr->remoteStreamID = streamID;
	nxr->fileThreadResult = 1;
	e=p+len;
	pgp_memcpy( &nxr->salt[0], p, XFERSALTCHECKSIZE );
	p += XFERSALTCHECKSIZE;
	if(*p++ != 0)	// check data type specifier, we only handle files
		goto error;
	BUFFER_TO_LONG(p, nxr->xi.bytesTotal);	
	p+=sizeof(nxr->xi.bytesTotal);
	nlen = strlen((char *)p);
	if((len<nlen+14) || (nlen > MAXFILENAMELEN))	//verify name length is correct
		goto error;
	strcpy((char *)filename, (char *)p);	
	p+=nlen+1;
	dirlen = 0;	dirspec = NIL;
	// subtype interpreter
	slen = 0;
	for(;p<e;p+=slen)
	{
		subtype = *p++;
		if(p == e)
			goto error;
		slen = *p++;
		if(e-p < slen)
			goto error;
		switch(subtype)
		{
			case _ost_CanonDirectory:
				// cross platform canonical directory specifier
				dirspec = p;
				dirlen = slen;
				break;
			case _ost_CanonInfo:
				// cross platform canonical file info (creation/mod/etc..)
				break;
		}
	}
	
	if(PrepIncomingFile(nxr, filename, dirspec, dirlen))// platform dependent processing
	{
		if(mReceiving)
		{
			for(walk=mReceiving;walk->next;walk=walk->next);
			walk->next = nxr;
		}
		else
			mReceiving = nxr;
		mNumReceiving++;
		nxr->hash = new SHA();
		nxr->hash->Update((uchar *)&nxr->salt[0], XFERSALTCHECKSIZE);
		mXferWindow->QueueReceive(nxr);
		return nxr;
	}
error:
	if(nxr)
		pgp_free(nxr);
	return NIL;
}

void
CXferThread::AckOpenStream(XRcvFile *xrf)
{
	uchar *p, *e, hashfinal[SHS_DIGESTSIZE];
	short hashLen;

	if(HashPartialFile(&xrf->xi, xrf->hash, hashfinal))
	{
		hashLen = SHS_DIGESTSIZE;
		xrf->xi.resurrect = 1;
	}
	else
		hashLen = 0;
	e = p = (uchar *)safe_malloc(6 + hashLen);	pgpAssert(p);
	*e++ = _xst_AckOpenStream;
	*e++ = xrf->remoteStreamID;
	LONG_TO_BUFFER(xrf->xi.bytesDone, e);	e+=sizeof(xrf->xi.bytesDone);
	if(hashLen)
	{
		pgp_memcpy(e, hashfinal, SHS_DIGESTSIZE);
		e+=SHS_DIGESTSIZE;
	}
	mOutQueue->Send(_mt_filePacket, p, e-p, 1);
}

XSendFile *
CXferThread::OpenStream(XSendFile *xsf)
{
	XSendFile *walk;
	uchar name[128], *p, *e;
	short nlen;
	
	if(xsf)
	{
		if(!mSending)
			mSending = xsf;
		else
		{
			for(walk=mSending;walk->next;walk=walk->next);	
			walk->next = xsf;
		}
		mNumSending++;
		mOpeningStream=TRUE;
		mXferWindow->QueueSend(xsf);
		xsf->localStreamID = mNextStreamID++;
		nlen = GetFileName(&xsf->xi, name);
		e = p = (uchar *)safe_malloc(16+nlen);	pgpAssert(p);
		*e++ = _xst_OpenStream;
		*e++ = xsf->localStreamID;
		pgp_memcpy( e, &xsf->salt[0], XFERSALTCHECKSIZE );	e += XFERSALTCHECKSIZE;
		*e++ = 0;	// Data type specifier - 0 is file, hardcoded for now
		LONG_TO_BUFFER(xsf->xi.bytesTotal, e);	e+=sizeof(xsf->xi.bytesTotal);
		strcpy((char *)e, (char *)name);	e+=nlen+1;
		if(xsf->path[0])
		{
			*e++ = _ost_CanonDirectory;
			
#ifdef PGP_MACINTOSH
			pstrcpy(e, xsf->path);
			e+=*e+1;
#elif PGP_WIN32
			nlen = strlen((char*)xsf->path);
			//*e++ = nlen;
			strcpy((char*)e, (char*)xsf->path);
			e+=nlen;
#endif
			
		}
		
		mOutQueue->Send(_mt_filePacket, p, e-p, 1);
	}
	return xsf;
}

XSendFile *
CXferThread::InitSend(void *file)
{
	StMutex mutex(*this);
	XSendFile *nxs=NIL;

	if(nxs = (XSendFile *)pgp_malloc(sizeof(XSendFile)))
	{
		memset(nxs, 0, sizeof(XSendFile));
		GetFileSize(nxs, file);
		randPoolGetBytes((uchar *)&nxs->salt[0], XFERSALTCHECKSIZE);
		nxs->hash = new SHA();
		nxs->hash->Update((uchar *)&nxs->salt[0], XFERSALTCHECKSIZE);
		
		nxs->fileThreadResult = 1;
	}
#ifdef	DEBUGXFERLOG
	else
		DebugLog("_mt_sendFile: memory error!");
#endif
	return nxs;
}

void
CXferThread::StartSend()
{
	XSendFile *xsf;
	
	// First, create the file data pipe, we create it now
	// so that it is not allocated when the stream has only
	// been setup.
	pgpAssert(mSending);
	xsf = mSending;
	xsf->xi.startTime=xsf->xi.lastTime=pgp_getticks();
	xsf->xi.pipe = new CPipe(STDPIPESIZE, STDPIPEEXTRA);
	xsf->fileThread = new CFileSendPipe(&xsf->xi, FALSE,
						(void **)&xsf->fileThreadResult);
	// Create the send thread
	xsf->xi.pipe->SetPusher(xsf->fileThread);
	xsf->xi.pipe->SetPuller(mPacketThread);
	if(xsf->xi.bytesDone)	// If so, this is a resumed file transfer
		xsf->xi.pipe->DoSetPipePos(xsf->xi.bytesDone);
	xsf->fileThread->Resume();
	mXferWindow->StartSend(&xsf->xi);
}

void
CXferThread::EndSend()
{
	// The file transfer at the front of the queue is completed
	// so move onto the next file.
	mXferWindow->EndSend();
	if(mSending)
	{
		DisposeSend(mSending);
		if(mSending && mSending->openAckd && !mSending->xi.pipe)
			StartSend();
	}
}

void
CXferThread::DisposeSend(XSendFile *xsf)
{
	XSendFile *walk;
	
	while(!xsf->fileThreadResult)
		(Yield)();
	mXferWindow->DequeueSend(xsf);
	if(xsf == mSending)
		mSending = xsf->next;
	else
	{
		for(walk=mSending;walk->next!=xsf;walk=walk->next);
		if(walk->next == xsf)
			walk->next = xsf->next;
	}
	delete xsf->hash;
	if(xsf->xi.pipe)
		delete xsf->xi.pipe;
	mNumSending--;
	pgp_free(xsf);
}

void
CXferThread::DisposeRecv(XRcvFile *xrf)
{
	XRcvFile *lxrf, *wxrf;
	
	while(!xrf->fileThreadResult)
		(Yield)();
	mXferWindow->DequeueReceive(xrf);
	for(lxrf=NIL,wxrf=mReceiving;wxrf!=xrf;wxrf=wxrf->next)
		lxrf=wxrf;
	if(wxrf==xrf)
	{
		if(lxrf)
			lxrf->next = xrf->next;
		else
			mReceiving = xrf->next;
		delete xrf->hash;
		if(xrf->xi.pipe)
			delete xrf->xi.pipe;
		pgp_free(xrf);
	}
	mNumReceiving--;
}

short
CXferThread::GetFileName(XferInfo *xi, uchar *name)
{
#ifdef	PGP_MACINTOSH
	short len;
	FSSpec *fs;
	
	fs = (FSSpec *)&xi->file;
	len = fs->name[0];
	pstrcpy(name, fs->name);
	p2cstr(name);
	return len;
#elif	PGP_WIN32
	short len = 0;
	char* cp = NULL;
	
	cp = strrchr(xi->filepath, '\\');
	
	if(cp)
	{
		strcpy((char*)name, cp + 1);
		len = strlen((char*)name);
	}
	else
	{
		*name = 0x00;
	}
	
	return len;

#endif
}

Boolean
CXferThread::PrepIncomingFile(	XRcvFile *xrf, 		// new receive file struct
								uchar *p, 			// platform independant filename
								uchar *pathname, 	// platform independant directory
								short len)			// directory length
{
	// Copy name into platform dependent file structure
#ifdef	PGP_MACINTOSH
	HParamBlockRec hpb;
	CInfoPBRec cpb;
	Str255 path, thisDir;
	FSSpec *fs;
	uchar *e=pathname, *u;
	char s[128];
	short vRefNum, inx;
	OSErr err;
	long dirID;
	
	fs = &xrf->xi.file;
	// first parse the pathname
	if(gPGFOpts.fopt.volName[0])
	{
		vRefNum = pgp_GetVolRefNum(gPGFOpts.fopt.volName);
		dirID = gPGFOpts.fopt.dirID;
	}
	else
	{
		vRefNum = -1;	//default root directory
		dirID = 0;
	}
	path[0]=0;
	while(len>0)
	{
		len-=*e+1;
		pstrcpy(thisDir, e);
		// make sure the directory name is mac-friendly
		for(inx = 0,u=e+1;inx<*e;inx++,u++)
			if(*u == ':')
				*u = '-';	// no colons in dirnames
		if(*(e+1)=='.')
			*(e+1)='-';		// no periods in first letter on the mac
		e+=*e+1;
		pstrcat(path, "\p:");
		pstrcat(path, thisDir);
		cpb.dirInfo.ioCompletion = NIL;
		cpb.dirInfo.ioNamePtr = thisDir;
		cpb.dirInfo.ioVRefNum = vRefNum;
		cpb.dirInfo.ioFDirIndex = 0;
		cpb.dirInfo.ioDrDirID = dirID;
		err = PBGetCatInfoSync(&cpb);
		if(err)
		{
			// doesn't exist, so create it
			hpb.fileParam.ioCompletion = NIL;
			hpb.fileParam.ioNamePtr = thisDir;
			hpb.fileParam.ioVRefNum = vRefNum;
			hpb.fileParam.ioDirID = dirID;
			err = PBDirCreateSync(&hpb);
			dirID = hpb.fileParam.ioDirID;
		}
		else
			dirID = cpb.dirInfo.ioDrDirID;
	}
	
	pstrcpy(xrf->path, path);
	fs->vRefNum = vRefNum;
	fs->parID = dirID;

	len = strlen((char *)p);
	strncpy(s, (char *)p, 32);
	if(len > 31)
		s[31] = 0;
	p=(uchar *)s;
	for(;*p;p++)
		if(*p == ':')
			*p = '-';	// no colons in filenames
	if(s[0]=='.')
		s[0]='-';		// no periods in first letter on the mac

⌨️ 快捷键说明

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