home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.muug.mb.ca
/
2014.06.ftp.muug.mb.ca.tar
/
ftp.muug.mb.ca
/
pub
/
openh323.tar.gz
/
openh323.tar
/
openh323
/
src
/
rfc2833.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
2003-06-03
|
7KB
|
274 lines
/*
* rfc2833.cxx
*
* Open Phone Abstraction Library (OPAL)
* Formally known as the Open H323 project.
*
* Copyright (c) 2001 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Open Phone Abstraction Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Contributor(s): ______________________________________.
*
* $Log: rfc2833.cxx,v $
* Revision 1.4 2003/06/03 05:02:18 rjongbloed
* Added comment and test for NULL pointer parameter.
*
* Revision 1.3 2002/05/08 04:39:57 robertj
* Fixed problem with receiving RFC2833 data, was still trying to process it as
* codec and upsettign the channel receiver code.
*
* Revision 1.2 2002/02/19 06:32:38 robertj
* Allowed for RTP filter functions to force output of packet, or prevent it
* from being sent overriding the n frames per packet algorithm.
* Added more tracing.
*
* Revision 1.1 2002/01/23 05:06:23 robertj
* Added RFC2833 support as separate class
*
*/
#include <ptlib.h>
#ifdef __GNUC__
#pragma implementation "rfc2833.h"
#endif
#include "rfc2833.h"
static const char RFC2833Table1Events[] = "0123456789*#ABCD!";
#define new PNEW
///////////////////////////////////////////////////////////////////////////////
OpalRFC2833Info::OpalRFC2833Info(char t, unsigned d, unsigned ts)
{
tone = t;
duration = d;
timestamp = ts;
}
///////////////////////////////////////////////////////////////////////////////
OpalRFC2833::OpalRFC2833(const PNotifier & rx)
: receiveNotifier(rx),
#ifdef _MSC_VER
#pragma warning(disable:4355)
#endif
receiveHandler(PCREATE_NOTIFIER(ReceivedPacket)),
transmitHandler(PCREATE_NOTIFIER(TransmitPacket))
#ifdef _MSC_VER
#pragma warning(default:4355)
#endif
{
PTRACE(3, "RFC2833\tHandler created");
payloadType = RTP_DataFrame::IllegalPayloadType;
receiveComplete = TRUE;
receiveTimestamp = 0;
receiveTimer.SetNotifier(PCREATE_NOTIFIER(ReceiveTimeout));
transmitState = TransmitIdle;
transmitTimestamp = 0;
transmitTimer.SetNotifier(PCREATE_NOTIFIER(TransmitEnded));
}
BOOL OpalRFC2833::SendTone(char tone, unsigned duration)
{
if (!BeginTransmit(tone))
return FALSE;
transmitTimer = duration;
return TRUE;
}
BOOL OpalRFC2833::BeginTransmit(char tone)
{
PWaitAndSignal m(mutex);
const char * theChar = strchr(RFC2833Table1Events, tone);
if (theChar == NULL) {
PTRACE(1, "RFC2833\tInvalid tone character.");
return FALSE;
}
if (transmitState != TransmitIdle) {
PTRACE(1, "RFC2833\tAttempt to send tone while currently sending.");
return FALSE;
}
transmitCode = (BYTE)(theChar-RFC2833Table1Events);
transmitState = TransmitActive;
transmitTimestamp = 0;
PTRACE(3, "RFC2833\tBegin transmit tone='" << tone << '\'');
return TRUE;
}
BOOL OpalRFC2833::EndTransmit()
{
PWaitAndSignal m(mutex);
if (transmitState != TransmitActive) {
PTRACE(1, "RFC2833\tAttempt to stop send tone while not sending.");
return FALSE;
}
transmitState = TransmitEnding;
PTRACE(3, "RFC2833\tEnd transmit tone='" << RFC2833Table1Events[transmitCode] << '\'');
return TRUE;
}
void OpalRFC2833::OnStartReceive(char tone)
{
OpalRFC2833Info info(tone);
receiveNotifier(info, 0);
}
void OpalRFC2833::OnEndReceive(char tone, unsigned duration, unsigned timestamp)
{
OpalRFC2833Info info(tone, duration, timestamp);
receiveNotifier(info, 0);
}
void OpalRFC2833::ReceivedPacket(RTP_DataFrame & frame, INT)
{
if (frame.GetPayloadType() != payloadType)
return;
PINDEX payloadSize = frame.GetPayloadSize();
// Zero the payload size so the channel processing ignores this packet
frame.SetPayloadSize(0);
if (payloadSize < 4) {
PTRACE_IF(1, payloadSize > 0,
"RFC2833\tIgnoring packet, too small: " << frame.GetPayloadSize());
return;
}
const BYTE * payload = frame.GetPayloadPtr();
if (payload[0] >= sizeof(RFC2833Table1Events)-1) {
PTRACE(2, "RFC2833\tIgnoring packet, unsupported event.");
return;
}
PWaitAndSignal m(mutex);
receivedTone = RFC2833Table1Events[payload[0]];
receivedDuration = (payload[2]<<8) + payload[3];
unsigned timestamp = frame.GetTimestamp();
if (receiveTimestamp != timestamp) {
PTRACE(3, "RFC2833\tReceived start tone=" << receivedTone);
OnStartReceive(receivedTone);
// Starting a new event.
receiveTimestamp = timestamp;
receiveComplete = FALSE;
receiveTimer = 150;
}
else {
receiveTimer = 150;
if (receiveComplete) {
PTRACE(3, "RFC2833\tIgnoring duplicate packet.");
return;
}
}
if ((payload[1]&0x80) == 0) {
PTRACE(1, "RFC2833\tIgnoring packet, not end of event.");
return;
}
receiveComplete = TRUE;
receiveTimer.Stop();
PTRACE(3, "RFC2833\tReceived end tone=" << receivedTone << " duration=" << receivedDuration);
OnEndReceive(receivedTone, receivedDuration, receiveTimestamp);
}
void OpalRFC2833::ReceiveTimeout(PTimer &, INT)
{
PWaitAndSignal m(mutex);
if (receiveComplete)
return;
receiveComplete = TRUE;
PTRACE(3, "RFC2833\tTimeout tone=" << receivedTone << " duration=" << receivedDuration);
OnEndReceive(receivedTone, receivedDuration, receiveTimestamp);
}
void OpalRFC2833::TransmitPacket(RTP_DataFrame & frame, INT param)
{
if (transmitState == TransmitIdle)
return;
// Set flag to force a packet to be sent.
if (param != 0)
*(BOOL *)param = TRUE;
PWaitAndSignal m(mutex);
//frame.SetMarker(transmitTimestamp == 0);
unsigned actualTimestamp = frame.GetTimestamp();
if (transmitTimestamp == 0)
transmitTimestamp = actualTimestamp;
frame.SetTimestamp(transmitTimestamp);
frame.SetPayloadType(payloadType);
frame.SetPayloadSize(4);
BYTE * payload = frame.GetPayloadPtr();
payload[0] = transmitCode;
payload[1] = 7; // Volume
if (transmitState == TransmitEnding) {
payload[1] |= 0x80;
transmitState = TransmitIdle;
}
unsigned duration = actualTimestamp - transmitTimestamp;
payload[2] = (BYTE)(duration>>8);
payload[3] = (BYTE) duration ;
PTRACE(4, "RFC2833\tInserting packet: ts=" << transmitTimestamp
<< " code='" << RFC2833Table1Events[transmitCode] << "'"
" duration=" << duration << ' '
<< (transmitState == TransmitIdle ? "ending" : "continuing"));
}
void OpalRFC2833::TransmitEnded(PTimer &, INT)
{
EndTransmit();
}
/////////////////////////////////////////////////////////////////////////////