📄 ccontrolthread.cpp
字号:
void
CControlThread::ConfigComplete()
{
uchar *p, *e;
short sl, inx;
char s[128];
long codec;
// Configuration complete, start call
mStatusPane->AddStatus(0, "Configuration complete.");
mControlState = _con_Phone;
mSoundInput->Record(FALSE);
mPFWindow->SetDecoderList((uchar *)mVoiceDecoders,
mNumDecoders);
mPFWindow->SetEncoderList((uchar *)mVoiceEncoders,
mNumEncoders);
BUFFER_TO_LONG(mEncryptor, codec);
mPFWindow->SetEncryption(codec, 0);
mPFWindow->ShowStatus();
mTransport->BindMediaStreams();
SetSpeaker(mOriginator || mFullDuplex);
BUFFER_TO_LONG(mVoiceEncoders, codec);
mPFWindow->SetEncoder(codec);
mSoundInput->SetCodec(codec);
mSoundInput->SetOutput(mOutHPP, mSoundOutQ);
mSoundInput->Pause(TRUE);
if(mHaveChannel)
mSoundInput->Record(TRUE);
mChangingEnc = TRUE;
if(gPacketWatch)
gPacketWatch->SetHPPQueue(mSoundOutQ);
p = e = (uchar *)pgp_malloc(5);
*e++ = _ctp_OpenVoice;
LONG_TO_BUFFER(codec, e); e+=4;
mControlOutQ->Send(_mt_controlPacket, p, e-p);
if(mUseWordList)
{
for(sl=0,inx=0;inx<mAuthBytes;inx++)
{
sprintf(&s[sl], "%s\r", (inx==1 || inx==3) ?
hashWordListOdd[mAuthInfo[inx]] :
hashWordListEven[mAuthInfo[inx]]);
sl = strlen(s);
}
}
else
{
for(sl=0,inx=0;inx<mAuthBytes;inx++)
{
sprintf(&s[sl], "%02x\r", mAuthInfo[inx]);
sl = strlen(s);
}
}
if(mPrime)
mPFWindow->ShowAuthParams(s);
#ifdef PGPXFER
if(mSupportsFileXfer)
{
mXferResult = 0;
mXferQueue = new CMessageQueue(16);
(mXfer = new CXferThread(mPFWindow, mXferWindow, mOutHPP, mXferQueue,
mControlOutQ, (void **)&mXferResult))->Resume();
mPFWindow->AllowXfers(TRUE);
mInHPP->SetXferQueue(mXferQueue);
mOutHPP->SetXferThread(mXfer);
mXferWindow->SetXferThread(mXfer);
}
#endif
}
void
CControlThread::SetupTransport(enum ContactMethods method)
{
short result=0;
if(!mTransport)
{
switch(method)
{
case _cme_Serial:
mTransport = new CPFTSerial(&gPGFOpts.sopt, mPFWindow, &result);
break;
case _cme_Internet:
mTransport = new CPFTInternet(mPFWindow, this, &result);
break;
case _cme_AppleTalk:
#ifndef PGP_WIN32
mTransport = new CPFTAppleTalk(mPFWindow, this, &result);
#endif
break;
}
if(result)
{
delete mTransport;
mTransport = NULL;
}
}
}
void
CControlThread::StartPhone()
{
mControlState = _con_Configuring;
mConfigState = _cts_Hello;
mRemotePublicName[0]=0;
mRemoteSystemType = _pst_Generic;
pgp_memcpy(mEncryptor, sCryptorHash[_enc_none], 4);
mNumPrimes = 0;
mPrime = NIL;
if(mDHPublic)
pgp_free(mDHPublic);
if(mDHPrivate)
pgp_free(mDHPrivate);
mDHPublic = mDHPrivate = NIL;
mAuthenticated = mUseWordList = mFullDuplex = mAllowNone =
mFlipInProgress = mChangingEnc = mChangingDec =
mSupportsFileXfer = FALSE;
mRemoteWindow = 1;
mAuthBytes = 4;
bnInit();
byteFifoInit(&mSharedSecret);
byteFifoInit(&mOAuthentication);
byteFifoInit(&mAAuthentication);
gPacketWatch->InitCall(); // reset packet watch
mControlOutQ = new CMessageQueue(4);
mSoundOutQ = new CMessageQueue(10);
mInHPPResult = mOutHPPResult = 0;
(mInHPP = new CPFPacketsIn(gPGFOpts.popt.connection != _cme_Serial,
mPFWindow, mSoundOutput, mTransport, mMsgQueue,
mControlOutQ, mSoundOutput->GetPlayQueue(),
(void **)&mInHPPResult))->Resume();
(mOutHPP = new CPFPacketsOut(gPGFOpts.popt.connection != _cme_Serial,
mPFWindow, mTransport, mSoundInput, mControlOutQ, mSoundOutQ,
(void **)&mOutHPPResult))->Resume();
mSoundInput->SetPacketThread(mOutHPP);
#ifdef CONFIGCALL
// record sound until the call is configured
mSoundInput->SetCodec('rand');
mSoundInput->SetOutput(NIL, NIL);
mSoundInput->Record(TRUE);
SendHello(); //begin configuration
#else
// this code exists to test calls without configuration packets
// and without encryption
mControlState = _con_Phone;
mFullDuplex = TRUE;
mPFWindow->ShowStatus();
mSoundInput->SetCodec('GS5L'); // hardcoded default configuration
mSoundInput->SetOutput(mOutHPP, mControlOutQ);
mSoundInput->Record(TRUE);
mSoundOutput->SetCodec('GS5L');
mSoundOutput->Play(TRUE);
#endif
}
// CSoundOutput calls DropCoder when its underflow algorithm
// has determined that the coder currently in use is not
// adequately low CPU or low bandwidth for the connection.
// This tries not to but does partially assume the list of
// coders we got back intersected is listed in an estimate of
// decreasing order of coder complexity
void
CControlThread::DropCoder(ulong curCoder)
{
short i;
ulong curTime, codTime;
long curcps, codcps;
return;
//This feature has been temporarily disabled.
GetCoderReqs(curCoder, &curTime, &curcps);
for(i=0;i<mNumDecoders;i++)
{
if(curCoder != mVoiceDecoders[i])
{
GetCoderReqs(mVoiceDecoders[i], &codTime, &codcps);
if(codcps < curcps)
{
mMsgQueue->SendUnique(_mt_changeDecoder,
(void *)mVoiceDecoders[i]);
return;
}
}
}
mStatusPane->AddStatus(0,"Alternate coders exhausted, "
"connection is hopeless.");
}
// This function sets the "speaker" or the talking party in a half duplex
// conversation. It also passes the current information up to the window
// so that the appropriate information can be displayed to the user
void
CControlThread::SetSpeaker(Boolean speaker)
{
mHaveChannel = speaker;
mSoundOutput->Play(!speaker || mFullDuplex);
mPFWindow->SetSpeaker(speaker, mFullDuplex);
}
// Other threads can call this function to abort a call
// or cause the thread to exit
void
CControlThread::AbortSync(Boolean exit, Boolean remote)
{
mControlState = _con_Disconnecting;
if(mTransport)
mTransport->AbortSync();
if(exit)
{
mDone = TRUE;
mMsgQueue->SendUnique(_mt_quit);
}
else if(remote)
mMsgQueue->SendUnique(_mt_remoteAbort);
else
mMsgQueue->SendUnique(_mt_abort);
}
// The following function is called when the user switches port information
// or switches from Modem <-> Internet while the program is running.
void
CControlThread::ResetTransport()
{
if(mTransport)
mTransport->AbortSync();
mMsgQueue->SendUnique(_mt_resetTransport);
}
#define GSM7INDEX 7
#define GSM7LINDEX 2
void
CControlThread::SetCoderList(CoderEntry *coders, short numCoders)
{
mCoders = coders;
mNumCoders = numCoders;
if(gPacketWatch)
gPacketWatch->SetGSMTimes(
coders[GSM7INDEX].encTime, coders[GSM7LINDEX].encTime,
coders[GSM7INDEX].decTime, coders[GSM7LINDEX].decTime); //##### hardcoded GSM 7350/Lite
if(coders[GSM7INDEX].encTime > 750) // 1 second GSM encode took >70% of processor!
PGFAlert("PGPfone has determined that this computer is probably too slow.", 0);
}
char *
CControlThread::GetCoderName(ulong coder)
{
if(mCoders)
{
for(short inx = 0;inx<mNumCoders;inx++)
if(coder == (ulong)mCoders[inx].code)
return mCoders[inx].name;
}
return NIL;
}
void
CControlThread::GetCoderReqs(ulong coder, ulong *reqTime, long *reqcps)
{
if(mCoders)
{
for(short inx = 0;inx<mNumCoders;inx++)
if(coder == (ulong)mCoders[inx].code)
{
*reqTime = mCoders[inx].encTime;
*reqcps = mCoders[inx].reqcps;
return;
}
}
}
void
CControlThread::SendInfo()
{
uchar *p, *e;
short dInx, eInx, inx;
#ifdef DEBUGCONFIG
mStatusPane->AddStatus(0,"SendInfo");
#endif
// the following block of code sends the _ctp_Info packet
// which is the first packet sent under cloak. It
// negotiates various parameters such as voice encoders,
// duplex, sync, wordlist/hex, and # of authentication bytes
p = e = (uchar *)pgp_malloc(512);
pgpAssert(p);
*e++ = _ctp_Info;
if(!gPGFOpts.popt.idUnencrypted &&
((mOriginator && gPGFOpts.popt.idOutgoing) ||
(!mOriginator && gPGFOpts.popt.idIncoming)) &&
gPGFOpts.popt.identity[0])
{
*e++ = _cti_PublicName;
*e++ = strlen(gPGFOpts.popt.identity);
strcpy((char *)e, gPGFOpts.popt.identity);
e+= strlen((char *)e);
}
*e++ = _cti_SystemType;
*e++ = 1;
#ifdef PGP_MACINTOSH
*e++ = _pst_Macintosh;
#else
*e++ = _pst_Generic;
#endif
*e++ = _cti_Duplex;
*e++ = 1;
*e++ = (gPGFOpts.popt.fullDuplex);
*e++ = _cti_WordList; // We want the word list by default
*e++ = 1;
*e++ = 1;
*e++ = _cti_AuthenticationBytes;// Number of Authentication Bytes
*e++ = 1;
*e++ = mAuthBytes;
// Setup list of voice encoders and decoders
LONG_TO_BUFFER(gPGFOpts.popt.prefCoder, mVoiceDecoders);
dInx = 4;
mNumDecoders = 1;
if(gPGFOpts.popt.prefCoder != gPGFOpts.popt.altCoder)
{
LONG_TO_BUFFER(gPGFOpts.popt.altCoder, mVoiceDecoders+dInx);
dInx+=4;
mNumDecoders++;
}
mNumEncoders = 0;
eInx = 0;
pgpAssert(mCoders);
for(inx = mNumCoders-1;inx>=0;inx--)
{
if((mCoders[inx].code != gPGFOpts.popt.prefCoder) &&
(mCoders[inx].code != gPGFOpts.popt.altCoder) &&
((mCoders[inx].reqSpeed <= gPGFOpts.sopt.maxBaud) ||
(gPGFOpts.popt.connection != _cme_Serial)))
{
LONG_TO_BUFFER(mCoders[inx].code, mVoiceDecoders+dInx);
dInx+=4;
mNumDecoders++;
}
if((mCoders[inx].encTime < MAXCODERTIMETHRESHOLD) &&
((mCoders[inx].reqSpeed <= gPGFOpts.sopt.maxBaud) ||
(gPGFOpts.popt.connection != _cme_Serial)))
{
LONG_TO_BUFFER(mCoders[inx].code, mVoiceEncoders+eInx);
eInx+=4;
mNumEncoders++;
}
}
*e++ = _cti_VoiceEncoders; // Send our list of encoders
*e++ = eInx;
pgp_memcpy(e, mVoiceEncoders, eInx);
e+=eInx;
*e++ = _cti_VoiceDecoders; // Send our list of decoders
*e++ = dInx;
pgp_memcpy(e, mVoiceDecoders, dInx);
e+=dInx;
#ifdef PGPXFER
*e++ = _cti_FileTransfer;
*e++ = 2;
SHORT_TO_BUFFER((short)MAXSAVEDOOPACKETS, e); e+=2;
#endif
mControlOutQ->Send(_mt_controlPacket, p, e-p);
}
Boolean
CControlThread::ReceiveInfo(uchar *data, short length)
{
uchar *p, *e;
ulong *cd;
short len, num, inx, inx2, nd;
Boolean good = TRUE;
#ifdef DEBUGCONFIG
mStatusPane->AddStatus(0,"ReceiveInfo");
#endif
len = 0;
for(p=data,e=data+length;p<e;p+=len)
{
num = *p++;
if(p == e)
{
good = FALSE;
break;
}
len = *p++;
if(e-p < len)
{
good = FALSE;
break;
}
switch(num)
{
case _cti_PublicName:
if(len>0)
{
if(len>63)
len=63;
pgp_memcpy(mRemotePublicName,p,len);
mRemotePublicName[len]=0;
}
break;
case _cti_SystemType:
mRemoteSystemType = (enum SystType)*p;
break;
case _cti_Duplex:
if(gPGFOpts.popt.fullDuplex && *p)
mFullDuplex = TRUE;
break;
case _cti_Sync:
//we dont support it, so it wont be negotiated
break;
case _cti_VoiceEncoders:
num = len / 4;
cd = (ulong *)p;
for(inx=0;inx<mNumDecoders;inx++)
{
for(inx2=0;inx2<num;inx2++)
{
if(!memcmp(&mVoiceDecoders[inx*4],&cd[inx2],4))
break;
}
if(inx2>=num)
{
if(inx<mNumDecoders-1)
pgp_memcpy(&mVoiceDecoders[inx*4],
&mVoiceDecoders[(inx+1)*4],
(mNumDecoders-1-inx) * 4);
mNumDecoders--;
inx--;
}
}
if(!mNumDecoders)
{
mStatusPane->AddStatus(0,
"Could not negotiate a voice decoder.");
good = FALSE;
}
break;
case _cti_VoiceDecoders:
nd = num = len / 4;
cd = (ulong *)p;
for(inx=0;inx<nd;inx++)
{
for(inx2=0;inx2<mNumEncoders;inx2++)
{
if(!memcmp(&mVoiceEncoders[inx2*4],&cd[inx],4))
break;
}
if(inx2>=mNumEncoders)
{
if(inx<nd-1)
pgp_memcpy(&cd[inx], &cd[inx+1], (nd-1-inx) * 4);
num--;
}
}
if(num > 32)
num = 32;
mNumEncoders = num;
pgp_memcpy(mVoiceEncoders, p, num * 4);
if(!mNumEncoders)
{
mStatusPane->AddStatus(0,
"Could not negotiate a voice encoder.");
good = FALSE;
}
break;
case _cti_AuthenticationBytes:
if(*p < mAuthBytes && *p >= 2)
mAuthBytes = *p;
break;
case _cti_WordList:
if(*p)
mUseWordList = TRUE;
break;
case _cti_FileTransfer:
mSupportsFileXfer = TRUE;
BUFFER_TO_SHORT(p, mRemoteWindow);
break;
default:
// unknown data, so ignore it
break;
}
}
return good;
}
Boolean
CControlThread::ReceiveDHHash(uchar *data, short length)
{
Boolean good = TRUE;
#ifdef DEBUGCONFIG
mStatusPane->AddStatus(0,"ReceiveDHHash");
#endif
if(length >= SHS_DIGESTSIZE)
pgp_memcpy(mDHHash, data, SHS_DIGESTSIZE);
else
good = FALSE;
return good;
}
void
CControlThread::SendDHHash()
{
uchar *p, *e, alen[4];
long authwrit;
SHA hash;
#ifdef DEBUGCONFIG
mStatusPane->AddStatus(0,"SendDHHash");
#endif
// The following block of code sends the _ctp_DHHash packet
// which sends a hash of the public Diffie-Hellman calculation
// This is integral to the security by making sure that both
// parties commit to a value before revealing the public
// calculation
p = e = (uchar *)pgp_malloc(512);
pgpAssert(p);
*e++ = _ctp_DHHash;
// Calculate first half of the Diffie-Hellman
mDHPublic = (uchar *)pgp_malloc(mPrime->length);
mDHPrivate = (uchar *)pgp_malloc(mPrime->length);
if(dhFirstHalf(mPrime->prime, mPrime->length, mPrime->expSize,
dhGenerator, sizeof(dhGenerator),
mDHPrivate, mPrime->length,
mDHPublic) < 0)
pgp_errstring("Diffie-Hellman error.");
// Hash the Public field and commit to it by sending it to
// the other side
hash.Init();
hash.Update(mDHPublic, mPrime->length);
hash.Final(e);
e+=SHS_DIGESTSIZE;
SHORT_TO_BUFFER((short)(e-p), alen);
authwrit = byteFifoWrite(mOriginator? &mOAuthentication : &mAAuthentication, alen, 2);
pgpAssert(authwrit == 2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -