📄 cpfpackets.cpp
字号:
c = HPPUNESCAPE(c);
}
if(reliable)
crc32 = updatecrc32(c, crc32);
else
crc = updatecrc16(c, crc);
seqbyte = c;
// Get body of packet
p = *buffer;
outlen = 0;
inlen = mInputTail-mInputHead;
for (;;)
{
if(!inlen--)
{
if(GetData() < 0)
goto abort;
inlen = mInputTail-mInputHead-1;
}
c = *mInputHead++;
if(HPPNEEDSESCAPE(c))
{
if(c == HPPPACKETDELIM)
break; // End of packet!
if(!inlen--)
{
if(GetData() < 0)
goto abort;
inlen = mInputTail-mInputHead-1;
}
c = *mInputHead++;
if(c == HPPPACKETDELIM)
{
if(gPacketWatch)
gPacketWatch->GotPacket(FALSE); // Bad packet
goto packetstart;
}
c = HPPUNESCAPE(c);
}
if(++outlen > HPPMAXPKTLEN + 2) // Packet too long - skip
goto packetfind;
*p++ = c;
if(reliable)
crc32 = updatecrc32(c, crc32);
else
crc = updatecrc16(c, crc);
}
// We now have a complete packet
if(mAbort)
goto abort;
if((reliable && ((crc32 != 0xDEBB20E3) || (outlen < 4))) ||
(!reliable && ((crc != 0) || (outlen < 2)))) // Bad CRC?
{
if(gPacketWatch)
gPacketWatch->GotPacket(FALSE); // Bad packet
goto packetstart;
}
mInputHead--; // Back up so next invocation can find packet delim
*len = outlen - (reliable ? 4 : 2); // Chop off CRC, leaving only user data
// Find the last encountered sequence number
if(*type >= RELIABLESTART)
{
if(*type == _hpt_File)
sequence = sRFileSequence;
else
sequence = sRControlSequence;
}
else
sequence = mSequence;
// Find the full sequence number of the current packet
sequence += (long)(signed char)(seqbyte-sequence);
*seq = sequence;
// Okay, now decrypt the thing
if((*type != _hpt_ACK) && (*type != _hpt_Control))
{
// Create counter mode iv
iv[0] = (uchar)*type;
iv[1] = 0;
LONG_TO_BUFFER(sequence, &iv[2]);
mRXKeyChangeMutex.Wait();
if(mDecryptor)
{
mDecryptor->Decrypt(*buffer, *len, iv);
crypted = TRUE;
}
mRXKeyChangeMutex.Signal();
}
return crypted;
abort:
safe_free(*buffer);
*buffer = NIL;
*len = 0;
*type = (enum HPPPacketType)0;
return crypted;
}
short
CPFPacketsIn::GetData(void)
{
long read;
short channel;
do {
if(mAbort)
return -1;
#ifdef PGP_WIN32
// sleeps until a character arrives or our abort event is triggered
if (!ResetEvent(mAbortEvent))
{
DWORD error = GetLastError();
char str[100];
sprintf(str, "Abort event error %ld", (error));
pgp_errstring(str);
}
short result = mTransport->SleepForData(&mAbortEvent);
if (result != 0)
{
ResetEvent(mAbortEvent);
return -1; // error (< 0) or aborted (> 0)
}
ResetEvent(mAbortEvent);
#else
(Yield)();
#endif // PGP_WIN32
read = mTransport->Read(mInputBuffer, HPPBUFFERSIZE, &channel);
} while (!read);
mInputHead = mInputBuffer;
mInputTail = mInputBuffer + read;
return 0;
}
// Datagram style packet format
//
// Type : 1 byte
// Sequence : 2 bytes
// Data : <= HPPMAXPKTLEN(1024)
// CRC : 4 bytes (reliable packets only)
//
// SendPacket is designed to skip bit stuffing in favor of the
// above format for use over networks and other channels where
// bit stuffing is pointless or redundant.
void
CPFPacketsOut::SendPacket(enum HPPPacketType type, ulong seq, long len, uchar *data)
{
HPPReliablePacket *hppr, *walk;
uchar *sendbuf, *p, fb;
ulong crc32, timestamp;
uchar iv[6];
ushort seqshort;
pgpAssert(len <= HPPMAXPKTLEN);
mTransport->WaitAsync(&mAsyncs[mNextAsync]);
mAsyncs[mNextAsync].buffer = sendbuf = (uchar *)safe_malloc(1024+7);
p = sendbuf;
*p++ = type;
seqshort = (ushort)seq;
SHORT_TO_BUFFER(seqshort, p); p+= 2;
fb = *data;
if(type == _hpt_Voice)
{
timestamp = pgp_milliseconds();
LONG_TO_BUFFER(timestamp, p); p+=4;
pgp_memcpy(p, data, len); p+=len;
len += 4;
}
else
{
pgp_memcpy(p, data, len); p+=len;
}
if((type != _hpt_ACK) && (type != _hpt_Control))
{
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(sendbuf+3, len, iv);
mTXKeyChangeMutex.Signal();
}
len+=3;
if(type >= RELIABLESTART)
{
crc32 = CalcCRC32(sendbuf, len);
LONG_TO_BUFFER(crc32, p); p+=4;
len+=4;
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 = sendbuf;
safe_increaseCount(sendbuf);
hppr->len = (short) len;
sInOutMutex->Signal();
}
mTransport->WriteAsync(len, (type==_hpt_Voice)? _pfc_Media : _pfc_Control, &mAsyncs[mNextAsync++]);
mNextAsync %= NUMHPPASYNCS;
if(gPacketWatch)
gPacketWatch->SentPacket();
}
// The GetPacket routine assumes that all Read calls return an HPP
// packet. A lower layer is expected to be doing the packetization.
// This is the case under Internet UDP and AppleTalk DDP.
Boolean
CPFPacketsIn::GetPacket(enum HPPPacketType *type, uchar **buffer, short *len, ulong *seq)
{
long read, dlen, baavg, baskew;
ulong crc32, pkcrc32, sequence, timestamp, timestampnow;
uchar iv[6];
ushort seqshort;
short channel;
Boolean goodcrc, crypted=FALSE;
*buffer = NIL;
while(!mAbort)
{
read = mTransport->Read(mInputBuffer, HPPBUFFERSIZE, &channel);
if(read)
{
goodcrc = FALSE;
if(mInputBuffer[0] >= RELIABLESTART)
{
// we only CRC control packets in packet mode
if(read >= 6)
{
crc32 = CalcCRC32(mInputBuffer, read - 4);
BUFFER_TO_LONG(mInputBuffer + read - 4, pkcrc32);
if(crc32 == pkcrc32)
goodcrc = TRUE;
read -=4;
}
}
else
goodcrc = TRUE;
dlen = read - 3; // Allow for type and sequence bytes
if(goodcrc && (mInputBuffer[0] <= LASTPACKETTYPE) &&
(dlen <= HPPMAXPKTLEN))
{
*type = (enum HPPPacketType)mInputBuffer[0];
if((*buffer = (uchar*)safe_malloc(dlen)) != NULL)
{
BUFFER_TO_SHORT(&mInputBuffer[1], seqshort);
// Find the last encountered sequence number
if(*type >= RELIABLESTART)
{
if(*type == _hpt_File)
sequence = sRFileSequence;
else
sequence = sRControlSequence;
}
else
sequence = mSequence;
// Find the full sequence number of the current packet
sequence += (long)(signed short)(seqshort - sequence);
*seq = sequence;
if((*type != _hpt_ACK) && (*type != _hpt_Control))
{
iv[0] = (uchar)*type;
iv[1] = 0; // +++++ should be overflow bits
LONG_TO_BUFFER(sequence, &iv[2]);
mRXKeyChangeMutex.Wait();
if(mDecryptor)
{
mDecryptor->Decrypt(mInputBuffer + 3, dlen, iv);
crypted = TRUE;
}
mRXKeyChangeMutex.Signal();
}
if((*type == _hpt_Voice) && (dlen > 5))
{
dlen-=4;
*len = (short) dlen;
pgp_memcpy(*buffer, mInputBuffer + 7, dlen);
BUFFER_TO_LONG(mInputBuffer + 3, timestamp);
timestampnow = pgp_milliseconds();
baskew = timestampnow-timestamp;
if(mJitterCount > 3)
sSkew += (baskew-sSkew)/8;
else
sSkew = baskew;
baavg = labs(baskew-sSkew);
sJVariance += (baavg-sJVariance)/16;
sJitter = sJVariance * 2; // old: sJVariance * 2;
// max = sJitter + sSkew;
// if baskew > max, it's late!
if(baskew > sJitter + sSkew)
{
if(++mLateTrack > 2)
{
//if(sLastSRR + 5000 < pgp_getticks())
// SendRR();
mLateTrack = 0;
}
}
else
mLateTrack = 0;
if(mJitterCount<10)
mJitterCount++;
else
{
mSoundOutput->SetJitter(sJitter);
gPacketWatch->SetJitter(sJitter);
}
}
else
{
*len = (short) dlen;
pgp_memcpy(*buffer, mInputBuffer + 3, dlen);
}
return crypted;
}
}
else
gPacketWatch->GotPacket(FALSE); // Log bad packet
}
(Yield)();
}
return crypted;
}
void
CPFPacketsIn::DeliverPacket(enum HPPPacketType packetType, uchar *packet, short packetLen)
{
HPPReliablePacket *hppr, *lhpr;
enum HPPPacketType ackType;
ulong sq, rttVal;
ushort seqshort;
uchar seqbyte;
switch(packetType)
{
case _hpt_ACK:
ackType = (enum HPPPacketType)((ulong)*packet);
sInOutMutex->Wait();
if(ackType == _hpt_File)
{
hppr = sFileReliables;
sq = sSFileSequence;
}
else
{
hppr = sControlReliables;
sq = sSControlSequence;
}
if(mPacketMode)
{
BUFFER_TO_SHORT(packet+1, seqshort);
//DebugLog("ACK at %ld, on %d", sq, seqshort);
//CStatusPane::GetStatusPane()->AddStatus(0, "Rcvd ACK at %ld, on %ld", sq, seqshort);
sq += (long)(signed short)(seqshort - sq);
}
else
{
seqbyte = *(packet+1);
sq += (long)(signed char)(seqbyte-sq);
}
for(lhpr=NIL;hppr;hppr=hppr->next)
{
if((hppr->type == ackType) && (hppr->seq == sq))
{
// send ack notification back to control,
// and include the first byte of the
// packet so control can identify it.
if(ackType != _hpt_File)
mControlQueue->Send(_mt_ack, (void *)hppr->subType);
if(lhpr)
lhpr->next = hppr->next;
else
{
if(ackType == _hpt_File)
sFileReliables = hppr->next;
else
sControlReliables = hppr->next;
}
if(!hppr->retransmits)
{
// Update ACK timeout low-pass filter
sInOutMutex->Wait();
sACKWaitAverage = (ulong)((0.9 * (float)sACKWaitAverage) +
(0.1 * (float)(pgp_getticks() - hppr->firstXmitTime)));
sACKWaitTime = sACKWaitAverage * 2;
sInOutMutex->Signal();
}
else
{
}
safe_free(hppr->data);
safe_free(hppr);
}
lhpr = hppr;
}
sInOutMutex->Signal();
safe_free(packet);
break;
case _hpt_Voice:
mSoundOutQueue->Send(_mt_voicePacket, packet, packetLen, TRUE);
break;
case _hpt_Control:
if(mDecryptor)
{
safe_free(packet);
if(gPacketWatch)
gPacketWatch->GotPacket(FALSE);
break; //ignore unencrypted pkts on encrypted link
}
case _hpt_ControlEncrypt:
mControlQueue->Send(_mt_controlPacket, packet, packetLen, TRUE);
break;
case _hpt_RTT:
BUFFER_TO_LONG(&packet[1], rttVal);
if(packet[0] == mPFWindow->GetControlThread()->IsOriginator())
{
// Make sure this wasn't some RTT packet floating
// around the network we sent a long time ago
if(rttVal == sRTTSequence)
{
#ifdef PGP_MACINTOSH
if(UEnvironment::HasFeature(env_HasOpenTransport))
gPacketWatch->SetRTTime(OTElapsedMilliseconds(&sOTRTTBase));
else
gPacketWatch->SetRTTime(pgp_getticks() - sRTTBase);
#else
gPacketWatch->SetRTTime(pgp_getticks() - sRTTBase);
#endif
}
safe_free(packet);
}
else
mOutQueue->Send(_mt_rtt, packet, packetLen, TRUE);
break;
case _hpt_ReceptionReport:
#ifdef BETA
//CStatusPane::GetStatusPane()->AddStatus(0,
// "Sound is late on the remote side, adjusting bandwidth.");
#endif
/*sInOutMutex->Wait();
sBandwidthcps = sBandwidthcps / 5 * 4;
sBandwidthpp = sBandwidthcps / (1000 / sIntervalms);
gPacketWatch->SetBandwidth(sBandwidthcps);
sLastRRR = pgp_getticks();
sInOutMutex->Signal();*/
safe_free(packet);
break;
case _hpt_File:
if(mXferQueue)
mXferQueue->Send(_mt_filePacket, packet, packetLen, TRUE);
else
safe_free(packet);
break;
default:
safe_free(packet);
break;
}
}
void
CPFPacketsIn::SendRR()
{
/*
+++++
uchar *p, *e;
p = e = (uchar *)safe_malloc(1);
*e++ = 0;
mOutQueue->Send(_mt_rr, p, 1, TRUE);*/
}
void
CPFPacketsIn::AckPacket(enum HPPPacketType packetType, ulong seq)
{
uchar *p, *ackpkt, seqbyte;
ushort seqshort;
if(mPacketMode)
{
// We use 16 bit sequence numbers in packet mode (over IP and AppleTalk)
p = ackpkt = (uchar *)safe_malloc(3);
*p++ = packetType;
seqshort = (unsigned short) seq & 0xFFFF;
SHORT_TO_BUFFER(seqshort, p);
mOutQueue->Send(_mt_ack, ackpkt, 3, TRUE);
}
else
{
// We use 8 bit sequence numbers in serial mode
p = ackpkt = (uchar *)safe_malloc(2);
*p++ = packetType;
seqbyte = (unsigned char) seq & 0xFF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -