📄 cxferthread.cpp
字号:
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 + -