📄 cxferthread.cpp
字号:
c2pstr(s);
pstrcpy(fs->name, (uchar *)s);
hpb.ioParam.ioCompletion = NIL;
hpb.ioParam.ioNamePtr = NIL;
hpb.ioParam.ioVRefNum = fs->vRefNum;
hpb.volumeParam.ioVolIndex = 0;
if(!PBHGetVInfoSync(&hpb))
{
if(hpb.volumeParam.ioVFrBlk * hpb.volumeParam.ioVAlBlkSiz
<= xrf->xi.bytesTotal)
{
CStatusPane::GetStatusPane()->AddStatus(0,
"Not enough disk space to receive file!");
return FALSE;
}
return TRUE;
}
return FALSE;
#elif PGP_WIN32
char savePath[MAX_PATH + 1] = {0x00};
//char tempPath[MAX_PATH + 1] = {0x00};
// get the default save directory
if(gPGFOpts.fopt.recvDir[0])
{
strcpy(savePath, gPGFOpts.fopt.recvDir);
if(!SetCurrentDirectory(savePath) )
{
// need to create it...
}
}
else
{
char root[MAX_PATH];
GetCurrentDirectory(sizeof(root), root);
root[3] = 0x00;
strcpy(savePath,root);
}
// parse the platform independant directory
char* cp = (char*)pathname;
while(len > 0)
{
char* check = NULL;
char thisDir[256];
int dirLength;
int i;
len -= *cp + 1;
check = cp + 1;
// make sure the directory name is win-friendly
// chars not allowed in win filenames -> \ / : * ? " < > |
for(i = 0; i < *cp ; i++, check++)
{
if( *check == '\\' ||
*check == '/' ||
*check == ':' ||
*check == '*' ||
*check == '?' ||
*check == '\"' ||
*check == '<' ||
*check == '>' ||
*check == '|' )
{
*check = '-'; // no colons in dirnames
}
}
dirLength = *cp;
memcpy(thisDir, cp + 1, dirLength);
*(thisDir + dirLength) = 0x00;
strcat(savePath, "\\");
strcat(savePath, thisDir);
if( !SetCurrentDirectory(savePath) )
{
// doesn't exist, so create it
CreateDirectory(savePath, NULL);
}
cp += *cp + 1;
}
// tuck away path
strcpy((char*)xrf->path, savePath);
// parse the platform independant filename
char filename[256];
len = strlen((char *)p);
strncpy(filename, (char *)p, 255);
cp = filename;
for(;*cp;cp++)
{
if( *cp == '\\' ||
*cp == '/' ||
*cp == ':' ||
*cp == '*' ||
*cp == '?' ||
*cp == '\"' ||
*cp == '<' ||
*cp == '>' ||
*cp == '|' )
{
*cp = '-'; // no colons in filenames
}
}
if(filename[0] == '.')
{
filename[0] = '-'; // no periods in first letter on windows
}
strcat(savePath, "\\");
strcat(savePath, filename);
// tuck away path and filename
strcpy((char*)xrf->xi.filepath, savePath);
xrf->xi.filename = strrchr((char*)xrf->xi.filepath, '\\') + 1;
// check the current disk for space
DWORD sectorsPerCluster;
DWORD bytesPerSector;
DWORD numberOfFreeClusters;
DWORD totalNumberOfClusters;
GetDiskFreeSpace( NULL, // use current working root
§orsPerCluster,
&bytesPerSector,
&numberOfFreeClusters,
&totalNumberOfClusters);
DWORD freespace = sectorsPerCluster * bytesPerSector * numberOfFreeClusters;
if(freespace <= xrf->xi.bytesTotal)
{
/*CStatusPane::GetStatusPane()->AddStatus(0,
"Not enough disk space to receive file!");*/
MessageBox( NULL,
"Not enough disk space to receive file!",
filename,
MB_OK|MB_ICONERROR);
return FALSE;
}
return TRUE;
#endif
}
void
CXferThread::GetFileSize(XSendFile *xsf, void *file)
{
#ifdef PGP_MACINTOSH
XferFileSpec *xspec = (XferFileSpec *)file;
Str255 rootPath, filePath;
uchar *p;
short pathlen, dirlen;
if((xspec->rootDir != xspec->fs.parID) || (xspec->rootVol != xspec->fs.vRefNum))
{
rootPath[0] = filePath[0] = 0;
pgp_GetFullPathname(xspec->rootVol, xspec->rootDir, rootPath);
pgp_GetFullPathname(xspec->fs.vRefNum, xspec->fs.parID, filePath);
// cut off the root part of the directory and record the partial pathname
pstrcpy(xsf->path, "\p:"); // add leading colon which will be replaced by sublen
dirlen = pstrlen(rootPath);
pathlen = pstrlen(filePath) - dirlen;
memcpy(&xsf->path[2], &filePath[dirlen+1], pstrlen(filePath) - dirlen);
xsf->path[0] = pathlen+1;
pathlen = --xsf->path[0]; // cut off the trailing colon
for(p=&xsf->path[pathlen],dirlen=0;p>xsf->path;--p)
{
if(*p == ':')
{
*p = dirlen;
dirlen = 0;
}
else
dirlen++;
}
}
pgp_memcpy(&xsf->xi.file, &xspec->fs, sizeof(FSSpec));
xsf->xi.sendAs = SendFileAs(&xsf->xi.file, mPFWindow->GetControlThread()->GetRemoteSystemType());
CheckSendMethod(this, &xsf->xi);
#elif PGP_WIN32
XferFileSpec *xspec = (XferFileSpec *)file;
//char* path = NULL;
int dirlen = 0;
int pathlen = 0;
char* cp = NULL;
strcpy(xsf->xi.filepath, xspec->path);
xsf->xi.filename = strrchr(xsf->xi.filepath, '\\') + 1;
*(xsf->path) = 0x00;
if(xspec->root)
{
//placeholders for length bytes
strcpy((char*)xsf->path,".\\");
strcat((char*) (xsf->path + 2), xspec->root);
*(strrchr((char*)xsf->path, '\\')) = 0x00;
// remember total length of path...
// add one for the extra 'total length byte'
pathlen = strlen((char*) (xsf->path + 2)) + 1;
// record the length byte
*(xsf->path) = pathlen;
for(cp = (char*)(xsf->path + pathlen), dirlen = 0;cp > (char*)xsf->path; --cp)
{
if(*cp == '\\')
{
*cp = dirlen;
dirlen = 0;
}
else
{
dirlen++;
}
}
}
xsf->xi.sendAs = 1; // BINARY
HANDLE handle;
WIN32_FIND_DATA wfd;
handle = FindFirstFile( xspec->path, &wfd);
if( INVALID_HANDLE_VALUE != handle)
{
xsf->xi.bytesTotal = wfd.nFileSizeLow;
FindClose(handle);
}
else
{
xsf->xi.bytesTotal = 0;
}
#endif
}
void
CXferThread::AbortSend(uchar localStreamID, ulong *salt)
{
uchar *p, *e;
// Send an _xst_AbortStream to abort the receiver for this stream
e = p = (uchar *)safe_malloc(10); pgpAssert(p);
*e++ = _xst_AbortStream;
*e++ = localStreamID;
pgp_memcpy( e, salt, XFERSALTCHECKSIZE ); e += XFERSALTCHECKSIZE;
mOutQueue->Send(_mt_filePacket, p, e-p, 1);
}
void
CXferThread::AbortReceive(uchar remoteStreamID, ulong *salt)
{
uchar *p, *e;
// Send an _xst_RemoteAbortStream to abort the sender for this stream
e = p = (uchar *)safe_malloc(10); pgpAssert(p);
*e++ = _xst_RemoteAbortStream;
*e++ = remoteStreamID;
pgp_memcpy( e, salt, XFERSALTCHECKSIZE ); e += XFERSALTCHECKSIZE;
mOutQueue->Send(_mt_filePacket, p, e-p, 1);
}
CMessageQueue *
CXferThread::GetQueue()
{
return mInQueue;
}
Boolean
CXferThread::HashPartialFile(XferInfo *xi, SHA *hash, uchar *hashfinal)
{
LThread *fileThread;
SHA *cloneHash;
long fileThreadResult, pull, pullSize, bDone=0;
Boolean done=FALSE, aborted=FALSE;
uchar *data;
// Given a file, this function loads it in through the normal pipe
// mechanism and hashes it to a certain position in order to match
// the contents on each side. It is used by the sender to confirm
// the hash received from the receiver, and by the receiver when it
// believes it is receiving the completion of a previous partial file.
#ifdef PGP_MACINTOSH
xi->sendAs = SendFileAs(&xi->file, mPFWindow->GetControlThread()->GetRemoteSystemType());
#endif
xi->pipe = new CPipe(STDPIPESIZE, STDPIPEEXTRA);
fileThread = new CFileSendPipe(xi, TRUE, (void **)&fileThreadResult);
xi->pipe->SetPusher(fileThread);
xi->pipe->SetPuller(this);
fileThread->Resume();
while(!done && !aborted)
{
pullSize = pull = 1024;
if(xi->bytesDone)
if(pull+bDone>xi->bytesDone)
{
pull = xi->bytesDone-bDone;
done = TRUE;
}
xi->pipe->DoStartPipePull(&pull, (void **)&data, 0);
if(pull<pullSize)
done = TRUE;
if(pull)
{
bDone += pull;
hash->Update(data, pull);
}
xi->pipe->DoEndPipePull(-1);
(Yield)();
aborted = xi->pipe->DoPipeAborted();
}
if(!aborted)
xi->pipe->DoAckEndPipe();
delete xi->pipe;
xi->pipe = NIL;
if(!xi->bytesDone)
xi->bytesDone = bDone;
if(!aborted)
{
cloneHash = hash->Clone();
cloneHash->Final(hashfinal);
delete cloneHash;
return TRUE;
}
else
xi->fatalErr = 0;
return FALSE;
}
long
CXferThread::GetNextSendPacket(long maxSize)
{
Boolean done = FALSE, aborted = FALSE;
long pullSize, pull, sentBytes=0;
uchar *data, *p, *e, str[80];
// Activating the following mutex causes a deadlock that is
// difficult to eliminate. Using these mutexes is probably
// desirable however in the long run. The deadlock scenario:
// CPFPacketsOut: mOutQueue->mFreeSpace is full
// calls this func which grabs mSendMutex
// CXferThread: already has mSendMutex
// Has called OpenStream to send a packet
//
// This scenario also occurs with a number of the abort
// packets.
// Eliminating the mutex eliminates the deadlock and
// I don't believe it will result in actual problems.
//mSendMutex->Wait();
if(mSending && mSending->openAckd && mSending->xi.pipe)
{
pullSize = pull = minl(maxSize, MAXXFERPACKETSIZE);
mSending->xi.pipe->DoStartPipePull(&pull, (void **)&data, 0);
if(pull<pullSize)
done=TRUE;
if(pull)
{
mSending->xi.bytesDone += pull;
mSending->hash->Update(data, pull);
mSending->xi.lastTime=pgp_getticks();
p=e=(uchar *)safe_malloc(pull+2);
*e++ = _xst_DataStream;
*e++ = mSending->localStreamID;
pgp_memcpy(e, data, pull); e+=pull;
mPacketThread->Send(_mt_filePacket, p, e-p);
sentBytes += e-p;
#ifdef DEBUGXFERLOG
DebugLog("Send: _xst_DataStream: len %ld", (long)(e-p-2));
#endif
safe_free(p);
}
mSending->xi.pipe->DoEndPipePull(-1);
aborted = mSending->xi.pipe->DoPipeAborted();
if(done && !aborted)
{
p=e=(uchar *)safe_malloc(6 + SHS_DIGESTSIZE);
*e++ = _xst_EndStream;
*e++ = mSending->localStreamID;
pgp_memcpy( e, &mSending->salt[0], XFERSALTCHECKSIZE );
e += XFERSALTCHECKSIZE;
mSending->hash->Final(e); e+=SHS_DIGESTSIZE;
mPacketThread->Send(_mt_filePacket, p, e-p);
sentBytes += e-p;
safe_free(p);
#ifdef DEBUGXFERLOG
DebugLog("Send: _xst_EndStream");
#endif
mSending->xi.pipe->DoAckEndPipe();
GetFileName(&mSending->xi, str);
CStatusPane::GetStatusPane()->AddStatus(0,
"Sent: %s (%ld K).", str, maxl(mSending->xi.bytesTotal / 1024,1L));
EndSend();
if(!mOpeningStream)
CheckForNewStreams();
}
if(aborted)
mInQueue->Send(_mt_abortSend);
}
//mSendMutex->Signal();
return sentBytes;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -