/****************************************************************************
*
* Copyright (C) 2000-2001 RealNetworks, Inc. All rights reserved.
*
* This program is free software. It may be distributed under the terms
* in the file LICENSE, found in the top level of the source distribution.
*
*/
#include "dbg.h"
#include "rtspmsg.h"
#include <string.h> /* memset */
/**************************************
*
* CRtspHdr
*
**************************************/
CRtspHdr::CRtspHdr( const CString& strKey ) :
m_strKey(strKey)
{
// Empty
}
CRtspHdr::CRtspHdr( const CString& strKey, const CString& strVal ) :
m_strKey(strKey),
m_strVal(strVal)
{
// Empty
}
const CString& CRtspHdr::GetKey( void ) const
{
return m_strKey;
}
const CString& CRtspHdr::GetVal( void ) const
{
return m_strVal;
}
void CRtspHdr::SetVal( const CString& strVal )
{
m_strVal = strVal;
}
/**************************************
*
* CRtspMsg
*
**************************************/
CRtspMsg::CRtspMsg( void ) :
m_nRtspVer(0),
m_nSeq(0),
m_nBufLen(0),
m_pbuf(NULL)
{
// Empty
}
CRtspMsg::CRtspMsg( const CRtspMsg& other )
{
CRtspHdrList::ConstIterator itr( other.m_listHdrs.Begin() );
while( itr )
{
CRtspHdr* pHdr = *itr;
m_listHdrs.InsertTail( new CRtspHdr( *pHdr ) );
itr++;
}
m_nBufLen = other.m_nBufLen;
m_pbuf = NULL;
if( m_nBufLen )
{
m_pbuf = new BYTE[ m_nBufLen ];
memcpy( m_pbuf, other.m_pbuf, m_nBufLen );
}
}
CRtspMsg::~CRtspMsg( void )
{
while( !m_listHdrs.IsEmpty() )
{
CRtspHdr* pHdr = m_listHdrs.RemoveHead();
delete pHdr;
}
delete[] m_pbuf; m_pbuf = NULL;
}
const CRtspMsg& CRtspMsg::operator=( const CRtspMsg& other )
{
m_nRtspVer = other.m_nRtspVer;
m_nSeq = other.m_nSeq;
while( !m_listHdrs.IsEmpty() )
{
CRtspHdr* pHdr = m_listHdrs.RemoveHead();
delete pHdr;
}
CRtspHdrList::ConstIterator itr( other.m_listHdrs.Begin() );
while( itr )
{
CRtspHdr* pHdr = *itr;
m_listHdrs.InsertTail( new CRtspHdr( *pHdr ) );
itr++;
}
m_nBufLen = other.m_nBufLen;
delete[] m_pbuf; m_pbuf = NULL;
if( m_nBufLen )
{
m_pbuf = new BYTE[ m_nBufLen ];
memcpy( m_pbuf, other.m_pbuf, m_nBufLen );
}
return *this;
}
CRtspMsg::operator CPBYTE( void ) const
{
return m_pbuf;
}
BYTE CRtspMsg::operator[]( UINT nPos ) const
{
return GetAt( nPos );
}
RtspMsgType CRtspMsg::GetType( void ) const
{
return RTSP_TYPE_NONE;
}
size_t CRtspMsg::GetHdrLen( void ) const
{
size_t nLen = 0;
CRtspHdrList::ConstIterator itr( m_listHdrs.Begin() );
while( itr )
{
CRtspHdr* pHdr = *itr;
nLen += ( pHdr->GetKey().GetLength() + 2 + pHdr->GetVal().GetLength() + 2 );
itr++;
}
return nLen;
}
size_t CRtspMsg::GetBufLen( void ) const
{
return m_nBufLen;
}
BYTE CRtspMsg::GetAt( UINT nPos ) const
{
return m_pbuf[ nPos ];
}
void CRtspMsg::SetAt( UINT nPos, BYTE by )
{
m_pbuf[ nPos ] = by;
}
void CRtspMsg::GetRtspVer( UINT* puMajor, UINT* puMinor ) const
{
assert( puMajor && puMinor );
*puMajor = HIWORD( m_nRtspVer );
*puMinor = LOWORD( m_nRtspVer );
}
void CRtspMsg::SetRtspVer( UINT uMajor, UINT uMinor )
{
assert( uMajor < 10 && uMinor < 10 );
m_nRtspVer = MAKEDWORD( uMajor,uMinor );
}
size_t CRtspMsg::GetHdrCount( void ) const
{
return m_listHdrs.GetCount();
}
CString CRtspMsg::GetHdr( const CString& strKey ) const
{
CString strVal;
CRtspHdrList::ConstIterator itr( m_listHdrs.Begin() );
while( itr )
{
CRtspHdr* pHdr = *itr;
if( 0 == strcasecmp( strKey, pHdr->GetKey() ) )
{
strVal = pHdr->GetVal();
break;
}
itr++;
}
return strVal;
}
CRtspHdr* CRtspMsg::GetHdr( UINT nIndex ) const
{
CRtspHdrList::ConstIterator itr( m_listHdrs.Begin() );
for( UINT n = 0; n < nIndex; n++ )
{
itr++;
}
return *itr;
}
void CRtspMsg::SetHdr( const CString& strKey, const CString& strVal )
{
CRtspHdrList::Iterator itr( m_listHdrs.Begin() );
while( itr )
{
CRtspHdr* pHdr = *itr;
if( 0 == strcasecmp( strKey, pHdr->GetKey() ) )
{
pHdr->SetVal( strVal );
return;
}
itr++;
}
m_listHdrs.InsertTail( new CRtspHdr( strKey, strVal ) );
}
void CRtspMsg::SetHdr( const CRtspHdr& hdrNew )
{
CRtspHdrList::Iterator itr( m_listHdrs.Begin() );
while( itr )
{
CRtspHdr* pHdr = *itr;
if( hdrNew.GetKey() == pHdr->GetKey() )
{
pHdr->SetVal( hdrNew.GetVal() );
return;
}
itr++;
}
m_listHdrs.InsertTail( new CRtspHdr( hdrNew ) );
}
PBYTE CRtspMsg::GetBuf( void ) const
{
return m_pbuf;
}
void CRtspMsg::SetBuf( CPBYTE buf, size_t nLen )
{
delete[] m_pbuf; m_pbuf = NULL;
m_nBufLen = nLen;
if( m_nBufLen )
{
m_pbuf = new BYTE[ m_nBufLen ];
memcpy( m_pbuf, buf, m_nBufLen );
}
}
/**************************************
*
* CRtspRequestMsg
*
**************************************/
// These correspond with enum RtspVerb and must be sorted
static CPCHAR s_pVerbs[] = {
"-NONE-",
"ANNOUNCE",
"DESCRIBE",
"GET_PARAMETER",
"OPTIONS",
"PAUSE",
"PLAY",
"RECORD",
"REDIRECT",
"SETUP",
"SET_PARAMETER",
"TEARDOWN",
NULL
};
static const UINT s_nVerbs = sizeof(s_pVerbs)/sizeof(CPCHAR) - 1;
CRtspRequestMsg::CRtspRequestMsg( void ) :
CRtspMsg(),
m_verb(VERB_NONE)
{
// Empty
}
CRtspRequestMsg::CRtspRequestMsg( const CRtspRequestMsg& other ) :
CRtspMsg(other)
{
m_verb = other.m_verb;
m_strUrl = other.m_strUrl;
}
CRtspRequestMsg::~CRtspRequestMsg( void )
{
// Empty
}
const CRtspRequestMsg& CRtspRequestMsg::operator=( const CRtspRequestMsg& other )
{
m_verb = other.m_verb;
m_strUrl = other.m_strUrl;
return *this;
}
RtspMsgType CRtspRequestMsg::GetType( void ) const
{
return RTSP_TYPE_REQUEST;
}
RtspVerb CRtspRequestMsg::GetVerb( void ) const
{
return m_verb;
}
CPCHAR CRtspRequestMsg::GetVerbStr( void ) const
{
return s_pVerbs[m_verb];
}
void CRtspRequestMsg::SetVerb( RtspVerb verb )
{
assert( verb > VERB_NONE && verb < VERB_LAST );
m_verb = verb;
}
void CRtspRequestMsg::SetVerb( CPCHAR szVerb )
{
m_verb = VERB_NONE;
int hi = s_nVerbs;
int lo = -1;
int mid;
while( hi-lo > 1 )
{
mid = (hi+lo)/2;
if( strcmp( szVerb, s_pVerbs[mid] ) <= 0 )
hi = mid;
else
lo = mid;
}
if( 0 == strcmp( szVerb, s_pVerbs[hi] ) )
{
m_verb = (RtspVerb)hi;
}
assert( VERB_NONE != m_verb );
}
CPCHAR CRtspRequestMsg::GetUrl( void ) const
{
return (CPCHAR)m_strUrl;
}
void CRtspRequestMsg::SetUrl( const CString& strUrl )
{
m_strUrl = strUrl;
}
/**************************************
*
* CRtspResponseMsg
*
**************************************/
struct StatusMapEntry { UINT nCode; CPCHAR szName; };
// These must be sorted
static StatusMapEntry s_mapStatus[] =
{
{ 100, "Continue" },
{ 200, "OK" },
{ 201, "Created" },
{ 250, "Low on Storage Space" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Moved Temporarily" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Time-out" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Large" },
{ 415, "Unsupported Media Type" },
{ 451, "Parameter Not Understood" },
{ 452, "Conference Not Found" },
{ 453, "Not Enough Bandwidth" },
{ 454, "Session Not Found" },
{ 455, "Method Not Valid in This State" },
{ 456, "Header Field Not Valid for Resource" },
{ 457, "Invalid Range" },
{ 458, "Parameter Is Read-Only" },
{ 459, "Aggregate operation not allowed" },
{ 460, "Only aggregate operation allowed" },
{ 461, "Unsupported transport" },
{ 462, "Destination unreachable" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Time-out" },
{ 505, "RTSP Version not supported" },
{ 551, "Option not supported" },
{ 0, NULL }
};
static const UINT s_nStatusEntries = sizeof(s_mapStatus)/sizeof(StatusMapEntry) - 1;
CRtspResponseMsg::CRtspResponseMsg( void ) :
CRtspMsg(),
m_nCode(0)
{
// Empty
}
CRtspResponseMsg::CRtspResponseMsg( const CRtspResponseMsg& other ) :
CRtspMsg(other)
{
m_nCode = other.m_nCode;
m_strStatusMsg = other.m_strStatusMsg;
}
CRtspResponseMsg::~CRtspResponseMsg( void )
{
// Empty
}
const CRtspResponseMsg& CRtspResponseMsg::operator=( const CRtspResponseMsg& other )
{
m_nCode = other.m_nCode;
m_strStatusMsg = other.m_strStatusMsg;
return *this;
}
RtspMsgType CRtspResponseMsg::GetType( void ) const
{
return RTSP_TYPE_RESPONSE;
}
UINT CRtspResponseMsg::GetStatusCode( void ) const
{
return m_nCode;
}
const CString& CRtspResponseMsg::GetStatusMsg( void ) const
{
return m_strStatusMsg;
}
void CRtspResponseMsg::SetStatus( UINT nCode, CPCHAR szMsg /* = NULL */ )
{
assert( nCode >= 100 && nCode <= 999 );
m_nCode = nCode;
if( !szMsg )
{
szMsg = "Unknown";
int hi = s_nStatusEntries;
int lo = -1;
int mid;
while( hi-lo > 1 )
{
mid = (hi+lo)/2;
if( nCode <= s_mapStatus[mid].nCode )
hi = mid;
else
lo = mid;
}
if( nCode == s_mapStatus[hi].nCode )
{
szMsg = s_mapStatus[hi].szName;
}
}
m_strStatusMsg = szMsg;
}
syntax highlighted by Code2HTML, v. 0.9.1