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

📄 cpfpackets.cpp

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

	$Id: CPFPackets.cpp,v 1.6 1999/03/10 02:35:19 heller Exp $
____________________________________________________________________________*/

//////////////////////////////////////////////////////////////////////
//	This module implements an asynchronous reliable and unreliable
//	datagram service that routes packets among the various threads
//	above it and the transport layer below it.
//////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "CPFPackets.h"

#include "CControlThread.h"
#include "CCounterEncryptor.h"
#include "CPriorityQueue.h"
#include "CPacketWatch.h"
#include "CPFTransport.h"
#include "CPFWindow.h"
#include "CSoundInput.h"
#include "CSoundOutput.h"
#include "CRC.h"
#include "CStatusPane.h"
#include "PGPFoneUtils.h"
#ifdef PGPXFER
#include "CXferThread.h"
#endif
#ifdef PGP_MACINTOSH
#include "CPFTAppleTalk.h"
#include <UEnvironment.h>
#endif

#define BANDWIDTHIP				150000	// default bandwidth estimates
#define BANDWIDTHSERIAL9600		960
#define BANDWIDTHSERIAL14400	1370
#define BANDWIDTHSERIAL28800	2700

#define RELIABLESTART		_hpt_Control
#define LASTPACKETTYPE		_hpt_File

#define HPPPACKETDELIM		0x7E	// At start and end of each packet
#define HPPPACKETESCAPE		0x7D	// Prefix for escaped characters
#define HPPNEEDSESCAPE(c) ((((c) - HPPPACKETESCAPE) & 0xff) < 2)
#define HPPESCAPE(c)		((c) ^ 0x20)// transforms an escaped character
#define HPPUNESCAPE(c)		HPPESCAPE(c)// transform is self-inverse

HPPReliablePacket	*sControlReliables, *sFileReliables;
LMutexSemaphore		*sInOutMutex;

ulong sRTTSequence, sRTTBase, sIntervalms,		// milliseconds btwn snd sound pkts
		sRFileSequence, sSFileSequence, sRControlSequence, sSControlSequence,
		sLastRRR,								// last rcvd reception report time
		sLastSRR;								// last sent reception report time
long sBandwidthcps, sBandwidthpp, sACKWaitAverage, sACKWaitTime,
		sJitter,								// jitter for rcvd packets
		sJVariance,								// arrival variance
		sSkew,									// clock skew
		sMTU;									// Maximum Transfer Unit

#ifdef	PGP_MACINTOSH
#include <OpenTransport.h>
// On Macs with OT installed, we use a more precise measurement
// which gives us accurate milliseconds
OTTimeStamp sOTRTTBase;
#endif

CPFPacketsIn::CPFPacketsIn(Boolean packetMode,
				CPFWindow *window,
				CSoundOutput *soundOutput,
				CPFTransport *transport,
				CMessageQueue *controlQueue,
				CMessageQueue *outQueue,
				CMessageQueue *soundOut,
				void **outResult)
#ifndef PGP_WIN32
        : LThread(0, thread_DefaultStack, threadOption_UsePool, outResult)
#else
        : LThread(outResult)
#endif  // PGP_WIN32
{
	sInOutMutex				= new LMutexSemaphore;
	mPFWindow				= window;
	mTransport				= transport;
	mSoundOutput			= soundOutput;
	mControlQueue			= controlQueue;
	mSoundOutQueue			= soundOut;
	mXferQueue				= NIL;
	mOutQueue				= outQueue;
	mPacketMode				= packetMode;
	mDecryptor				= NIL;
	mNoCrypto				= FALSE;
	mInputHead		=
		mInputTail			= mInputBuffer;
	mAbort					= FALSE;
	mSequence		=
		sSControlSequence	=
		sRControlSequence	=
		sSFileSequence		=
		sRFileSequence		= 0;
	sBandwidthcps			= BANDWIDTHIP;
	sMTU					= 1040;
	if(gPGFOpts.popt.connection == _cme_Serial)
	{
		switch(gPGFOpts.sopt.maxBaud)
		{
			case 0:
				sBandwidthcps = BANDWIDTHSERIAL9600;
				sMTU = 256;
				break;
			case 1:
				sBandwidthcps = BANDWIDTHSERIAL14400;
				sMTU = 256;
				break;
			case 2:
				sBandwidthcps = BANDWIDTHSERIAL28800;
				sMTU = 512;
				break;
		}
	}
#ifdef PGP_MACINTOSH
	else if(gPGFOpts.popt.connection == _cme_AppleTalk)
	{
		sMTU = MAXPGPFDDPSIZE;
	}
#endif
	sIntervalms = 200;
	sJitter = 0;
	sJVariance = 0;
	sSkew = 0;
	
	mJitterCount = 0;
	sLastSRR = sLastRRR = 0;
	mLateTrack = 0;
	mSavedOOPkts = NIL;
	mNumSavedOOPkts = 0;
	sACKWaitTime = sACKWaitAverage = DEFAULTACKWAITTIME;
#ifdef PGP_WIN32
	//windows 95 bug so we do this all the time
	mAbortEvent_foo = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (mAbortEvent_foo == INVALID_HANDLE_VALUE)
		pgp_errstring("error creating abort event");
	mAbortEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (mAbortEvent == INVALID_HANDLE_VALUE)
		pgp_errstring("error creating abort event");
#endif	// PGP_WIN32
}

CPFPacketsIn::~CPFPacketsIn()
{
	SavedOOPacket *soop, *lsoop;
	HPPReliablePacket *hppr;
		
	if(mDecryptor)
		delete mDecryptor;
	for(soop=mSavedOOPkts;soop;)
	{
		// Delete any remaining reliable out of order packets
		lsoop=soop;
		soop=soop->next;
		safe_free(lsoop->data);
		safe_free(lsoop);
	}
#ifdef PGP_WIN32
	if(mAbortEvent != INVALID_HANDLE_VALUE)
		CloseHandle(mAbortEvent);
	if(mAbortEvent_foo != INVALID_HANDLE_VALUE)
		CloseHandle(mAbortEvent_foo);
#endif	// PGP_WIN32
	for(hppr = sControlReliables;hppr;)
	{
		sControlReliables = sControlReliables->next;
		if(hppr->data)
			safe_free(hppr->data);
		safe_free(hppr);
		hppr = sControlReliables;
	}
	for(hppr = sFileReliables;hppr;)
	{
		sFileReliables = sFileReliables->next;
		if(hppr->data)
			safe_free(hppr->data);
		safe_free(hppr);
		hppr = sFileReliables;
	}
	delete sInOutMutex;
}

CPFPacketsOut::CPFPacketsOut(Boolean packetMode,
								CPFWindow *window,
								CPFTransport *transport,
								CSoundInput *soundIn,
								CMessageQueue *controlQueue,
								CMessageQueue *soundQueue,
								void **outResult)
#ifndef PGP_WIN32
        : LThread(0, thread_DefaultStack, threadOption_UsePool, outResult)
#else
        : LThread(outResult)
#endif  // PGP_WIN32
{
	short inx;
	
	mPFWindow = window;
	mTransport = transport;
	mSoundQueue = soundQueue;
	mControlQueue = controlQueue;
	mXferThread = NIL;
	mSoundInput = soundIn;
	mPacketMode = packetMode;
	mEncryptor = NIL;
	mAbort = FALSE;
	mSendingSound = FALSE;
	for(inx = 0;inx<NUMHPPASYNCS;inx++)
		mTransport->NewAsync(&mAsyncs[inx]);
	mNextAsync = 0;
	sControlReliables = sFileReliables = NIL;
	mSequence = 0;
	mReceiverWindow = MAXSAVEDOOPACKETS;
	sRTTSequence = 0;
	sRTTBase = pgp_getticks();
#ifdef PGP_WIN32
	mAbortEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if (mAbortEvent == INVALID_HANDLE_VALUE)
		pgp_errstring("error creating abort event");
#endif	// PGP_WIN32
}

CPFPacketsOut::~CPFPacketsOut()
{
	for(short inx = 0;inx<NUMHPPASYNCS;inx++)
		mTransport->DeleteAsync(&mAsyncs[inx]);
	if(mEncryptor)
		delete mEncryptor;
#ifdef PGP_WIN32
	if (mAbortEvent != INVALID_HANDLE_VALUE)
		CloseHandle(mAbortEvent);
#endif	// PGP_WIN32
}

// Package and send a packet.
// A packet is surrounded by HPPPACKETDELIM characters, and contains the
// following:
// Packet type (1 byte)
// Sequence Number (1 byte)
// Packet data (variable length)
// CRC (2 bytes, 4 bytes if reliable packet)
//
// If either of the bytes HPPPACKETDELIM or HPPPACKETESCAPE appear
// anywhere in the packet, they are escaped by replacing them
// with HPPPACKETESCAPE followed by an escaped form of the character.
// The escaping is done by XORing 0x20 with the character.

void
CPFPacketsOut::StreamSendPacket(enum HPPPacketType type, ulong seq, long len,
						uchar *data, Boolean lastPacket)
{
	HPPReliablePacket *hppr, *walk;
	uchar *buffer, *p, c, *r, fb;
	uchar iv[6], crcs[4];
	ushort crc = 0xffff;
	ulong crc32 = 0xffffffff;
	short inx;
	Boolean reliable;

	pgpAssert(len <= HPPMAXPKTLEN);
	r=data;
	fb = *data;
	if((type != _hpt_Control) && (type != _hpt_ACK))
	{
		mTXKeyChangeMutex.Wait();
		
		// Setup the counter for counter mode
		// Counter format:
		// Byte 1		Packet Type
		// Byte 2		Packet Counter, mod 2^40
		// Bytes 7-8	Cipher block counter
		
		iv[0] = (uchar)type;
		iv[1] = 0;
		LONG_TO_BUFFER(seq, &iv[2]);

		if(mEncryptor)
			mEncryptor->Encrypt(data, len, iv);
		mTXKeyChangeMutex.Signal();
	}
	mTransport->WaitAsync(&mAsyncs[mNextAsync]);
	mAsyncs[mNextAsync].buffer = p = buffer = (uchar *)safe_malloc(HPPBUFFERSIZE);
	if(type >= RELIABLESTART)
		reliable = TRUE;
	else
		reliable = FALSE;
	*p++ = HPPPACKETDELIM;	// Ensure packet starts with a delimiter
	// escape and CRC the type byte
	c = type;
	if(reliable)
		crc32 = updatecrc32(c, crc32);
	else
		crc = updatecrc16(c, crc);
	if(HPPNEEDSESCAPE(c))
	{
		*p++ = HPPPACKETESCAPE;
		c = HPPESCAPE(c);
	}
	*p++ = c;
	// escape and CRC the sequence number
	c = (uchar)seq;
	if(reliable)
		crc32 = updatecrc32(c, crc32);
	else
		crc = updatecrc16(c, crc);
	if(HPPNEEDSESCAPE(c))
	{
		*p++ = HPPPACKETESCAPE;
		c = HPPESCAPE(c);
	}
	*p++ = c;
	// escape and CRC the packet data
	for(;;)
	{
		c = *r++;
		len--;
		if(reliable)
			crc32 = updatecrc32(c, crc32);
		else
			crc = updatecrc16(c, crc);
		if(HPPNEEDSESCAPE(c))
		{
			*p++ = HPPPACKETESCAPE;
			c = HPPESCAPE(c);
		}
		*p++ = c;
		if(!len)
			break;
	}
	// Now escape the CRC
	if(reliable)
	{
		crc32 = ~crc32;
		for(inx=0;inx<4;inx++)
		{
			// CRC-32 is implemented as little-endian, so we have to make
			// sure that the bytes get inserted in little endian order
			// here.
			
			crcs[inx] = (unsigned char) crc32 & 0xff;
			crc32>>=8;
		}
		for(inx=0;inx<4;inx++)
		{
			c = crcs[inx];
			if(HPPNEEDSESCAPE(c))
			{
				*p++ = HPPPACKETESCAPE;
				c = HPPESCAPE(c);
			}
			*p++ = c;
		}
	}
	else
	{
		c = (crc >> 8) & 0xff;
		if(HPPNEEDSESCAPE(c))
		{
			*p++ = HPPPACKETESCAPE;
			c = HPPESCAPE(c);
		}
		*p++ = c;
		c = crc & 0xff;
		if(HPPNEEDSESCAPE(c))
		{
			*p++ = HPPPACKETESCAPE;
			c = HPPESCAPE(c);
		}
		*p++ = c;
	}

	// If no more packets are expected for a while, add a delimiter
	if(lastPacket)
		*p++ = HPPPACKETDELIM;

	// We're finished.  Send it.
	len = p-buffer;
	if(type >= RELIABLESTART)
	{
		hppr = (HPPReliablePacket *)safe_malloc(sizeof(HPPReliablePacket));
		memset(hppr, 0, sizeof(HPPReliablePacket));
		sInOutMutex->Wait();
		if(type == _hpt_File)
		{
			if(sFileReliables)
			{
				for(walk = sFileReliables;walk->next;walk=walk->next)
					;
				walk->next = hppr;
			}
			else
				sFileReliables = hppr;
		}
		else
		{
			if(sControlReliables)
			{
				for(walk = sControlReliables;walk->next;walk=walk->next)
					;
				walk->next = hppr;
			}
			else
				sControlReliables = hppr;
		}
		hppr->type = type;
		hppr->seq = seq;
		hppr->subType=fb;
		hppr->firstXmitTime = hppr->lastXmitTime = pgp_getticks();
		hppr->data = buffer;
		safe_increaseCount(buffer);
		hppr->len = (short) len;
		sInOutMutex->Signal();
	}
	// send the data to be encrypted or to the modem
	mTransport->WriteAsync(len, _pfc_Control, &mAsyncs[mNextAsync++]);
	mNextAsync %= NUMHPPASYNCS;
	if(gPacketWatch)
		gPacketWatch->SentPacket();
}

// This is organized as a state machine, with GOTOs between states.
// If the mAbort flag is set, anything will jump to the abort state,
// which returns failure.  (Checked before each I/O and before returning.)
// Otherwise, all jumps are backwards, with the expected flow being
// downwards through the code to the bottom.  The states are:
//
// packetfind: Search for a packet delimiter in the input stream
// packetstart: Just past a packet delimiter, expecting a packet type
//		followed by a packet body.  If a packet delimiter is found in an
//		unexpected place, jump straight back to packetstart.
//		When an ending delimiter is found, check the length and CRC.
//		If they're good, return the packet.  Since the ending delimiter
//		can also be the starting delimiter of the next packet, the input
//		is backed up one character to make the next invocation work.
//		If the CRC is not valid, go to packetstart.

Boolean
CPFPacketsIn::StreamGetPacket(enum HPPPacketType *type, uchar **buffer, short *len,
								ulong *seq)
{
	ushort inlen, outlen, crc;
	uchar iv[6];
	uchar c, seqbyte, *p;
	ulong sequence, crc32;
	Boolean crypted=FALSE, reliable;

	*buffer = (uchar *)safe_malloc(HPPMAXPKTLEN+2);
	if(!*buffer)
	{
		*len = 0;
		return crypted;
	}
	// Skip bytes until the next packet header
packetfind:
	// Ensure that we have some data to examine
	if(mInputHead >= mInputTail && GetData() < 0)
		goto abort;
	// Scan for the start of a packet
	for (;;)
	{
		inlen = mInputTail - mInputHead;
		mInputHead = (uchar*)memchr(mInputHead, HPPPACKETDELIM, inlen);
		if(mInputHead)
			break;
		if(GetData() < 0)
			goto abort;
	}
	mInputHead++;	// Skip packet start delimiter
packetstart:
	// We have a valid packet start - get type
	if(mInputHead >= mInputTail && GetData() < 0)
		goto abort;
	c = *mInputHead++;
	if(HPPNEEDSESCAPE(c))
	{
		if(c == HPPPACKETDELIM)
			goto packetstart;	// Zero-length "packet" - totally ignore
		// Okay, so it starts with an escaped byte
		if(mInputHead >= mInputTail && GetData() < 0)
			goto abort;
		c = *mInputHead++;
		if(c == HPPPACKETDELIM)
		{
			if(gPacketWatch)
				gPacketWatch->GotPacket(FALSE);	// Bad packet
			goto packetstart;
		}
		c = HPPUNESCAPE(c);
	}
	*type = (enum HPPPacketType)c;
	if(*type >= RELIABLESTART)
		reliable = TRUE;
	else
		reliable = FALSE;
	// Start CRC computation
	if(reliable)
		crc32 = updatecrc32(c, 0xffffffff);
	else
		crc = updatecrc16(c, 0xffff);
	
	// Get Sequence number
	if(mInputHead >= mInputTail && GetData() < 0)
		goto abort;
	c = *mInputHead++;
	if(HPPNEEDSESCAPE(c))
	{
		if(c == HPPPACKETDELIM)
		{
			if(gPacketWatch)
				gPacketWatch->GotPacket(FALSE); // Bad packet
			goto packetstart;
		}
		// Okay, so it starts with an escaped byte
		if(mInputHead >= mInputTail && GetData() < 0)
			goto abort;
		c = *mInputHead++;
		if(c == HPPPACKETDELIM)
		{
			if(gPacketWatch)
				gPacketWatch->GotPacket(FALSE); // Bad packet
			goto packetstart;
		}

⌨️ 快捷键说明

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