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

📄 ccontrolthread.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*____________________________________________________________________________
	Copyright (C) 1996-1999 Network Associates, Inc.
	All rights reserved.

	$Id: CControlThread.cpp,v 1.4 1999/03/10 02:32:21 heller Exp $
____________________________________________________________________________*/
#include "CControlThread.h"
#include "CPFTSerial.h"
#include "CPFWindow.h"
#include "CStatusPane.h"
#include "CPFPackets.h"
#include "CMessageQueue.h"
#include "CSoundInput.h"
#include "CSoundOutput.h"
#include "CPacketWatch.h"
#include "CEncryptionStream.h"
#include "HashWordList.h"
#include "SHA.h"
#include "dh.h"
#include "bn.h"
#include "fastpool.h"
#include "CPFTInternet.h"
#ifdef	PGPXFER
#include "CXferWindow.h"
#include "CXferThread.h"
#endif
#ifdef PGP_MACINTOSH
#include "CPFTAppleTalk.h"
#endif

#include <stdio.h>
#include <string.h>


/* CONFIGCALL enables us to "turn off" configuration packets
	This can be helpful in testing for many reasons including
	trying to determine whether a problem lies in configuration
	or elsewhere	*/
#define CONFIGCALL
/* DIRECTCONNECT implements a debug mode where ControlThread
	assumes that a modem connection is already established just
	by creating a transport object and vice versa. */
#define noDIRECTCONNECT
#define noDEBUGCONFIG

const uchar pgpfMajorProtocolVersion = 0;
const uchar pgpfMinorProtocolVersion = 0;

CControlThread::CControlThread(CMessageQueue *msgQueue,
								CPFWindow *cpfWindow,
								CSoundInput *soundInput,
								CSoundOutput *soundOutput,
								void **outResult)
#ifndef PGP_WIN32
        : LThread(FALSE, thread_DefaultStack, threadOption_UsePool, outResult)
#else
        : LThread(outResult)
#endif  // PGP_WIN32
{
	mControlState = _con_None;
	mDone = FALSE;
	mMsgQueue = msgQueue;
	mPFWindow = cpfWindow;
	mSoundInput = soundInput;
	mSoundOutput = soundOutput;
	mStatusPane = CStatusPane::GetStatusPane();
	mXferWindow = NIL;
	mTransport = NIL;
	mInHPP = NIL;
	mOutHPP = NIL;
	mXfer = NIL;
	mXferQueue = NIL;
	mXferResult = mInHPPResult = mOutHPPResult = 1L;
	mSoundOutQ = mControlOutQ = NIL;
	mFullDuplex = FALSE;
	mAuthenticated = FALSE;
	mDHPublic = mDHPrivate = NIL;
	mCoders = NIL;
	mNumCoders = 0;
	mRemotePublicName[0]=0;
	SetSpeaker(TRUE);
	byteFifoInit(&mSharedSecret);
	byteFifoInit(&mOAuthentication);
	byteFifoInit(&mAAuthentication);
}

CControlThread::~CControlThread()
{
	if(mDHPublic)
		pgp_free(mDHPublic);
	if(mDHPrivate)
		pgp_free(mDHPrivate);
	if(mCoders)
		pgp_free(mCoders);
}

void *
CControlThread::Run(void)
{
	short done = 0, err;
	Boolean exit = FALSE;
	PFMessage *msg, *hACK;
	ContactEntry *contact;
	uchar *p, *e, alen[4];
	long codec, authwrit;
	short reply;
#ifdef DEBUGCONFIG
	uchar s[80];
#endif
	
	while(!exit)
	{
		err = 0;
		msg = mMsgQueue->Recv();
		if(!msg)
			continue;
		switch(msg->type)
		{
			case _mt_quit:
				exit = mDone = TRUE;
			case _mt_remoteAbort:
			case _mt_abort:
				mControlState = _con_Disconnecting;
				mPFWindow->ShowStatus();
				if(msg->type != _mt_quit)
				{
					mPFWindow->SetDecoder(0);
					mPFWindow->SetEncoder(0);
					mPFWindow->SetEncryption(0,0);
					mPFWindow->HideAuthParams();
					mPFWindow->ClearDecoderList();
					mPFWindow->ClearEncoderList();
					mPFWindow->SetKeyExchange("");
					mPFWindow->AllowXfers(FALSE);
				}
				mSoundInput->Record(FALSE);
				mSoundOutput->Play(FALSE);
				mAuthenticated = FALSE;
#ifdef	PGPXFER
				if(mXfer)
				{
					mInHPP->SetXferQueue(NIL);
					if(mXferWindow)
						mXferWindow->SetXferThread(NIL);
					mXferQueue->Send(_mt_abort);
					while(!mXferResult)
						(Yield)();
					delete mXferQueue;
					mXferQueue = NIL;
					mXfer = NIL;
				}
#endif
				if(mControlOutQ)
				{
					mSoundOutQ->FreeType(_mt_voicePacket);
					mTransport->Flush();
					if((msg->type == _mt_abort || msg->type == _mt_quit))
					{
						if((p = (uchar *)pgp_malloc(1)) != NULL)
						{
							// Send out a hangup request after clearing the queue
							// and wait 4.1 seconds for a reply
							*p = _ctp_Hangup;
							mControlOutQ->Send(_mt_controlPacket, p, 1);
							hACK = mMsgQueue->Recv(4100);
							//pgpAssert(!hACK || hACK->type == _mt_ack);
						}
					}
					mSoundInput->SetPacketThread(NIL);
					mControlOutQ->Send(_mt_abort);
					while(!mOutHPPResult)
						(Yield)();
					mInHPP->AbortSync();
					while(!mInHPPResult)
						(Yield)();
					delete mControlOutQ;
					mControlOutQ = NIL;
					if(gPacketWatch)
						gPacketWatch->SetHPPQueue(NIL);
					delete mSoundOutQ;
					mSoundOutQ = NIL;
				}
				if(mTransport)
				{
					if(mTransport->GetState() == _cs_connected)
						mTransport->Disconnect();
					if(!mDone && gPGFOpts.popt.alwaysListen)
						mMsgQueue->SendUnique(_mt_waitCall);
					else
					{
						delete mTransport;
						mTransport = NIL;
					}
				}
				byteFifoDestroy(&mSharedSecret);	//destroy all records of key
				byteFifoDestroy(&mOAuthentication);	//material for this call
				byteFifoDestroy(&mAAuthentication);
				memset(mRemotePublicName, 0, 64);	//destroy record of remote party
				mControlState = _con_None;
				break;
			case _mt_answer:
			case _mt_waitCall:
				if(mControlState != _con_None)
					break;
				SetupTransport(gPGFOpts.popt.connection);
				if(mTransport)
				{
#ifndef DIRECTCONNECT
					if(mTransport->Reset())
					{
						delete mTransport;
						mTransport = NIL;
					}
					else if(!(err = mTransport->Listen(msg->type == _mt_answer)) &&
							(mTransport->GetState() == _cs_connected))
					{
						mOriginator = FALSE;
						StartPhone();
					}
					else if(err != _pge_InternalAbort)
					{
						if(gPGFOpts.popt.alwaysListen && !mDone)
							mMsgQueue->SendUnique(_mt_waitCall);
						else
						{
							delete mTransport;
							mTransport = NIL;
						}
					}
#else
					mPFWindow->SetState(_cs_connected);
					mOriginator = FALSE;
					StartPhone();
#endif
				}
				break;
			case _mt_call:
				contact = (ContactEntry *)msg->data;
				reply = _cr_NoReply;
				SetupTransport(contact->method);
				if(mTransport)
				{
#ifndef DIRECTCONNECT
					pgpAssert(contact);
					if(mTransport->Reset())
					{
						delete mTransport;
						mTransport = NIL;
					}
					else if(mTransport->Connect(contact, &reply))
					{
						delete mTransport;
						mTransport = NIL;
					}
					else if(reply == _cr_Connect)
					{
						mOriginator = TRUE;
						StartPhone();
					}
					else if(gPGFOpts.popt.alwaysListen && !mDone)
						mMsgQueue->SendUnique(_mt_waitCall);
#else
					mPFWindow->SetState(_cs_connected);
					mOriginator = TRUE;
					StartPhone();
#endif
				}
				break;
			case _mt_talk:			// outgoing talk request initiated by us
				if(!mFlipInProgress && mControlOutQ && mTransport)
				{
					if(!mFullDuplex)
					{
						if((p = (uchar *)pgp_malloc(1)) != NULL)
						{
							*p = _ctp_Talk;
							mControlOutQ->Send(_mt_controlPacket, p, 1);
							mFlipInProgress = TRUE;
						}
					}
					else if(!mHaveChannel)
					{
						SetSpeaker(TRUE);
						mSoundInput->Record(TRUE);
					}
				}
				break;
			case _mt_listen:		// outgoing listen request initiated by us
				if(!mFlipInProgress && mControlOutQ && mTransport)
				{
					if(!mFullDuplex)
					{
						if((p = (uchar *)pgp_malloc(1)) != NULL)
						{
							*p = _ctp_Listen;
							mControlOutQ->Send(_mt_controlPacket, p, 1);
							mFlipInProgress = TRUE;
						}
					}
					else if(mHaveChannel)
					{
						mSoundInput->Record(FALSE);
						SetSpeaker(FALSE);
					}
				}
				break;
			case _mt_ack:
				switch((uchar)msg->data)
				{
					case _ctp_Talk:
						if(!mHaveChannel && mFlipInProgress)
						{
							SetSpeaker(TRUE);
							mSoundInput->Record(TRUE);
						}
						mFlipInProgress = FALSE;
						break;
					case _ctp_Listen:
						if(mHaveChannel && mFlipInProgress)
						{
							mSoundInput->Record(FALSE);
							SetSpeaker(FALSE);
						}
						mFlipInProgress = FALSE;
						break;
					case _ctp_OpenVoice:
						if(mChangingEnc)
							mSoundInput->Pause(FALSE);
						mChangingEnc = FALSE;
						break;
					case _ctp_VoiceSwitch:
						if(mChangingDec)
							mSoundOutput->Pause(FALSE);
						mChangingDec = FALSE;
						break;
				}
				msg->data = NIL;
				break;
			case _mt_resetTransport:
				if(mTransport)
				{
					delete mTransport;
					mTransport = NIL;
				}
				if(gPGFOpts.popt.alwaysListen)
					mMsgQueue->SendUnique(_mt_waitCall);
				break;
			case _mt_changeDecoder:
				codec = (long)msg->data;
				if(mChangingDec)
				{
					// The user has become overzealous about
					// changing coders.  Lets set the display back
					// to what was requested a couple seconds
					// ago.
					//+++++todo
				}
				else if(!mChangingDec && ((p = e = (uchar *)pgp_malloc(5)) != NULL))
				{
					mSoundOutput->Pause(TRUE);
					*e++ = _ctp_VoiceSwitch;
					LONG_TO_BUFFER(codec, e);	e+=4;
					mControlOutQ->Send(_mt_controlPacket, p, e-p);
					mSoundOutput->SetCodec(codec);
					mChangingDec = TRUE;
				}
				msg->data = NIL;
				break;
			case _mt_changeEncoder:
				if(mChangingEnc)
				{
					// The user has become overzealous about
					// changing coders.  Lets set the display back
					// to what was requested a couple seconds
					// ago.
					//+++++todo
				}
				else if(!mChangingEnc && ((p = e = (uchar *)pgp_malloc(5)) != NULL))
				{
					mSoundInput->Pause(TRUE);
					*e++ = _ctp_OpenVoice;
					codec = (long)msg->data;
					LONG_TO_BUFFER(codec, e);	e+=4;
					mControlOutQ->Send(_mt_controlPacket, p, e-p);
					mSoundInput->SetCodec(codec);
					mChangingEnc = TRUE;
				}
				msg->data = NIL;
				break;
			case _mt_controlPacket:
				switch(*(p=(uchar *)msg->data))
				{
					case _ctp_Hello:
						if(mControlState == _con_Configuring &&
							mConfigState == _cts_Hello)
						{
							SHORT_TO_BUFFER(msg->len, alen);
							authwrit = byteFifoWrite(mOriginator? &mAAuthentication : &mOAuthentication, alen, 2);
							pgpAssert(authwrit == 2);
							authwrit = byteFifoWrite(mOriginator? &mAAuthentication : &mOAuthentication, p, msg->len);
							pgpAssert(authwrit == msg->len);
							if(ReceiveHello(++p, msg->len - 1))
							{
								if(mPrime &&
									memcmp(mEncryptor, sCryptorHash[_enc_none], 4))
								{
									mConfigState = _cts_DHHash;
									SendDHHash();
								}
								else
								{	//non-encrypted call
									mPrime = NIL;
									mStatusPane->AddStatus(0,
										"Unencrypted connection negotiated.");
									PlayInsecureWarning();
									mInHPP->SetNoCryptoMode();
									mConfigState = _cts_Info;
									SendInfo();
								}
							}
							else
							{
								mStatusPane->AddStatus(0,
									"Bad Hello received.  Aborting call.");
								mMsgQueue->Send(_mt_abort);
							}
						}
						break;
					case _ctp_DHHash:
						if(mControlState == _con_Configuring &&
							mConfigState == _cts_DHHash)
						{
							SHORT_TO_BUFFER(msg->len, alen);
							authwrit = byteFifoWrite(mOriginator? &mAAuthentication : &mOAuthentication, alen, 2);
							pgpAssert(authwrit == 2);
							authwrit = byteFifoWrite(mOriginator? &mAAuthentication : &mOAuthentication, p, msg->len);
							pgpAssert(authwrit == msg->len);
							if(ReceiveDHHash(++p, msg->len - 1))
							{
								mConfigState = _cts_DHPublic;
								SendDHPublic();
							}
							else
							{
								mStatusPane->AddStatus(0,
									"Bad DHHash received.  Aborting call.");
								mMsgQueue->Send(_mt_abort);
							}
						}
						break;
					case _ctp_DHPublic:
						if(mControlState == _con_Configuring &&
							mConfigState == _cts_DHPublic)
						{
							SHORT_TO_BUFFER(msg->len, alen);
							authwrit = byteFifoWrite(mOriginator? &mAAuthentication : &mOAuthentication, alen, 2);
							pgpAssert(authwrit == 2);
							authwrit = byteFifoWrite(mOriginator? &mAAuthentication : &mOAuthentication, p, msg->len);
							pgpAssert(authwrit == msg->len);
							if(ReceiveDHPublic(++p, msg->len - 1))
							{
								mConfigState = _cts_Info;
								SendInfo();
							}
							else
							{
								mStatusPane->AddStatus(0,
									"Bad DHPublic received.  Aborting call.");
								mMsgQueue->Send(_mt_abort);
							}
						}
						break;
					case _ctp_Info:
						if(mControlState == _con_Configuring &&
							mConfigState == _cts_Info)
						{
							if(ReceiveInfo(++p, msg->len - 1))
								ConfigComplete();
						}
						break;
					case _ctp_Hangup:
						mControlState = _con_Disconnecting;
						mStatusPane->AddStatus(0,"Remote disconnected.");
						Sleep(1000);	// Try to allow time for the ACK to go out
						mMsgQueue->Send(_mt_remoteAbort);
						break;
					case _ctp_OpenVoice:
						p++;
						BUFFER_TO_LONG(p, codec);
						mPFWindow->SetDecoder(codec);
						mSoundOutput->Pause(TRUE);
						mSoundOutput->SetCodec(codec);
						mSoundOutput->Pause(FALSE);
#ifdef DEBUGCONFIG
						pgp_memcpy(s,p,4);
						s[4]=0;
						mStatusPane->AddStatus(0,"_ctp_OpenVoice(O): %s",s);
#endif
						break;
					case _ctp_VoiceSwitch:
						p++;
						BUFFER_TO_LONG(p, codec);
						mPFWindow->SetEncoder(codec);
						mSoundInput->Pause(TRUE);
						mSoundInput->SetCodec(codec);
						mSoundInput->Pause(FALSE);
#ifdef DEBUGCONFIG
						pgp_memcpy(s,p,4);
						s[4]=0;
						mStatusPane->AddStatus(0,"_ctp_VoiceSwitch(I): %s",s);
#endif
						break;
					case _ctp_Talk:		// other side wishes to speak
						if(!mFullDuplex && (!mFlipInProgress || !mOriginator))
						{
							mSoundInput->Record(FALSE);
							SetSpeaker(FALSE);
							mFlipInProgress = FALSE;
						}
						break;
					case _ctp_Listen:	// other side wishes to listen
						if(!mFullDuplex && (!mFlipInProgress || !mOriginator))
						{
							SetSpeaker(TRUE);	// disable further playing of
												//	incoming packets
							mSoundOutput->ChannelSwitch();
							mSoundInput->Record(TRUE);
							mFlipInProgress = FALSE;
						}
						break;
					default:
						mStatusPane->AddStatus(0,"Unknown control packet received.");
						break;
				}
				break;
		}
		mMsgQueue->Free(msg);
	}
	return (void *)1L;
}

⌨️ 快捷键说明

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