This release addresses the following issues:
1. The crash bug fix when receiving file
2. Now the sending is based on MSRP messages, there is no longer file receiving or sending. Client sends data as MSRP was designed.
3. Soma MSRP stack was created so that the client told the correct session-id, Symbian stack generated it by itself. This is not allowed, it was changed so that clients tell the session-id (same as used in SIP INVITE).
4. Unnecessary division of data to chunks removed when there is no need to interrupt sending. The message is sent in as few chunks as possible.
5. Stack can now receive files and chunks with ?unlimited? size. Old stack wrote the incoming data to memory and did not utilize disk space until the end of chunk was reached (large chunks from another client crashed it).
6. Now when writing the incoming data to file, it will take into account the byte-range header values. So, this complies with the RFC4975 requirements that stack must be able to handle chunks that come in any sequence.
7. Some buffering changes to outgoing/incoming data.
8. The outgoing data is now checked that it does not contain the created transaction-id before sending the data.
9. MSRP success reports are now implemented and tested against servers.
10. Progress report system fixed so progress is now visible on client (all the way to 100%).
11. Message Cancel receiving / Cancel sending now corrected and made to work as rfc4975 requires. (termination from sender and error code from receiver when cancelling).
12. Bug correction related to messages received not belonging to any session, old stack implementation did send error response, but after response was written it did give the buffer to client anyway. Now corrected.
/*
* Copyright (c) 2002-2003 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
// INCLUDES
#include <e32base.h>
#include <e32std.h>
#include "rtpstppacket.h"
//
// RTPLite header
//
// ****************************************
// Extract from "PoC Core Network RTP RP01"
// ****************************************
// 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |F M R C S| PT | Sequence nbr | Checksum (optional) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Full header indication (F) 1 bit
// If this bit is set to zero then header format
// is reduced (otherwise full)
//
// Marker (M) 1 bit
// Indication of the start of speech item (value 1).
// It is set on the Nth first RTP packets including
// speech frames within the RTP payload. N is expected
// to have a constant value in the order of 3 to 5.
// Note: M-bit is zero for all embedded control packets.
//
// Reserved bit (R) 1 bit
// This bit is reserved for future use. Default value is 1.
//
// Checksum indication (C) 1 bit
// C-bit is an indication if header includes at the end an
// optional checksum field. Value 1 indicates that checksum
// field exist on the header.
//
// Speech Item toggle indication (S) 1 bit
// S-bit is used as an indication (toggled value) that speech
// item has been changed (toggled between two speech items
// from same source; toggled between two speech items from
// different users; toggled between two speech items from
// different groups 1-to-1 call). This bit is on the same
// position for the respective leader, speech and trailing
// packets.
//
// Payload Type (PT) 3 bits
// PT-field indicates what kind of information
// is carried on the paylaod area. Only two codes
// (000 and 001) are reserved at the first phase,
// other values are reserved for future use.000 is
// used to indicate that embedded control signal
// information is in payload area and 001 indicates
// that payload contains speech packets coded with
// IETF AMR speech coding 8. In case of embedded
// control signal coding then the first byte on the payload
// area has special coding rules, which are defined on section 5.3.4.
// Note: GSM HR (HalfRate) will be used for 1st integration testing
// and related PT is 010.
// Note: Standard RTP header uses 7 bits for the same indication.
//
// Sequence Nbr (SN) 8 bits
// The sequence nbr increments by one for each
// RTP data packet sent, and may be used by the
// receiver to detect packet loss and restore
// packet sequence. The initial value (when S
// bit is toggled) of the sequence number is zero.
// Note one exception: during talkspurt
// (for 1-to-1 call or group call) if one/few
// RTP packets are not sent (on N*20ms interval)
// due to DTX usage (silence periods not sent)
// the sequency number at the originator side
// is anyhow incremented by one with the N*20ms
// frequency. The value for N is 3 by default.
// Very probably RTP packets are always sent in
// GPRS terminals during talkspurt to avoid TBF
// drop. RTP packet payload contains during
// silence periods three NO_DATA -indication
// bytes to AMR decoder. In the future extented
// TFB timer feature may change this behaviour,
// i.e. the sending of NO_DATA -indication bytes
// might be dropped (over GPRS).Within standard
// version of RTP header the length of SN is 16
// bits , but within PoC application it is enough
// to have 8 bits; it provides 7.62s (127*3*20ms)
// jitter buffering without any special number wrap
// control tricks (shown values are valid with N=3).
// Note: On the uplink direction on each speech item,
// the Sequency Nbr is zero for all leading packets
// (the first leading packet is replicated few times,
// but the replicated messages are identical
// (even concerning the SN field)) and the first RTP
// packet containing speech has SN value one.
// Note: for all embedded control signals the SN
// is set to zero.
//
// CheckSum (CS) 16 bits (optional)
// Checksum field is optional and the existence
// of this field is indicated on the first octet
// by C-bit. Checksum will be needed with RP01
// interface if RLC/LLC/UDP checksums are not
// available/used. UDP checksum is optional
// with IPv4. Further more by using RTP level
// CRC in combination of UDP-lite it would be
// possible to implement more efficient unequal
// error protection on AMR bits than UDP-lite
// alone would offer.If checksum error is detected
// then whole RTP packet is discarded.
// Note: Checksum information is not available
// within standard RTP header.
// Note: Taking the other aspects (header compression
// with Degermark) into account it currently means
// that if checksum is included on RTPLite header
// the whole packet does fit to 8 kbit/s channel
// on the AIR interface only with AMR 4.75 coding.
// ================= MEMBER FUNCTIONS =======================
// ---------------------------------------------------------------------------
// C++ default constructor can NOT contain any code, that
// might leave.
// ---------------------------------------------------------------------------
//
CRtpStpPacket::CRtpStpPacket() :
iSize( 0 ),
iData( 0 ),
iDataPtr( 0 ),
iSessionId( 0 )
{
}
// ---------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave.
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::ConstructL( TUint aPacketSize, TRtpId aSessionId )
{
iBuf = HBufC8::NewL( aPacketSize );
iData = ( TUint8* ) iBuf->Des().Ptr();
iSize = 0;
iDataPtr = iData;
iSessionId = aSessionId;
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CRtpStpPacket::~CRtpStpPacket()
{
delete iBuf;
}
// ---------------------------------------------------------------------------
// CRtpStpPacket::Close()
// works as destructor
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::Close()
{
delete this;
}
// ---------------------------------------------------------------------------
// CRtpStpPacket::RtpPacketReset()
//
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::RtpPacketReset()
{
iSize = 0;
iDataPtr = iData;
}
// ---------------------------------------------------------------------------
// CRtpStpPacket::RtpPacketResetPtr()
//
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::RtpPacketResetPtr()
{
iDataPtr = iData;
}
// ---------------------------------------------------------------------------
// TInt CRtpStpPacket::RtpPacketBuild()
//
// ---------------------------------------------------------------------------
//
TInt CRtpStpPacket::RtpPacketBuild( const TRtpSendHeader& aHeader, const TDesC8& aPayloadData )
{
TUint8* dataP;
dataP = iData;
// build the packet content
Mem::FillZ( dataP, 4 );
// Full header indication (F)
dataP[0] |= ( 0 << 7 );
// Marker (M)
dataP[0] |= static_cast<TUint8>( aHeader.iMarker << 6 );
// Padding bit (P) = 1
dataP[0] |= static_cast<TUint8>( aHeader.iPadding << 5 );
// Checksum indecation (C) if checkSumInd == 1, need checksum in the header
dataP[0] |= static_cast<TUint8>( aHeader.iChecksumInd << 4 );
// Speech Item toggle indication (S)
dataP[0] |= static_cast<TUint8>( aHeader.iSpeechItemToggle << 3 );
// payload type
dataP[0] |= ( aHeader.iPayloadType & 0x07 );
// sequence number
dataP[1] = aHeader.iSeqNum;
dataP += 2;
// Optinal checksum
if ( aHeader.iChecksumInd == 1 )
{
write16( dataP, aHeader.iChecksum );
dataP += 2;
}
// copy payload data
Mem::Copy( dataP, aPayloadData.Ptr(), aPayloadData.Length() );
iSize = aPayloadData.Length() + ( dataP - iData );
return 0;
}
// ---------------------------------------------------------------------------
// CRtpStpPacket::RtpPacketProcess()
// Return Value:
// KErrNone if STP packet has been processed OK, or
// KErrCorrupt if packet is invalid or some other error has occured
// ---------------------------------------------------------------------------
//
TInt CRtpStpPacket::RtpPacketProcess( TUint8* aBuf, TInt* aLength )
{
TRtpRecvHeader header;
TUint8* dataP;
dataP = iData;
// Full header indication (F)
if ( ( dataP[0] & 0x80 ) != 0 )
return KErrCorrupt;
// Marker (M)
header.iMarker = ( TUint8 ) ( ( dataP[0] & 0x40 ) >> 6 );
// Padding bit (P)
header.iPadding = ( TUint8 ) ( ( dataP[0] & 0x20 ) >> 5 );
// Checksum indication (C)
header.iChecksumInd = ( TUint8 ) ( ( dataP[0] & 0x10 ) >> 4 );
// Speech item toggle indication (S)
header.iSpeechItemToggle = ( TUint8 ) ( ( dataP[0] & 0x08 ) >> 3 );
// Payload type (PT)
header.iPayloadType = ( TUint8 ) ( ( dataP[0] & 0x07 ) );
// Sequence number
header.iSeqNum = ( TUint8 ) ( dataP[1] );
dataP += 2;
// Optinal checksum
if ( header.iChecksumInd == 1 )
{
header.iChecksum = ( TUint16 ) read16( dataP );
dataP += 2;
}
*aLength = iSize - ( dataP - iData );
aBuf = ( TUint8 * ) dataP;
TPtrC8 buf( aBuf, *aLength );
if ( iObserver )
iObserver->RtpPacketReceived( iSessionId /* streamId */, header, buf );
return KErrNone;
}
// ---------------------------------------------------------------------------
// Write a 16-bit value as 2 consecutive bytes in MSB order
// Memory (at least 2 bytes) must have been allocated to pointer
// before the function is called.
// ---------------------------------------------------------------------------
//
void CRtpStpPacket::write16( TUint8* const aPointer, TUint32 aValue )
{
// check value range (16 bits)
aPointer[0] = ( TUint8 ) ( ( aValue & 0xFF00 ) >> 8 );
aPointer[1] = ( TUint8 ) ( aValue & 0x00FF );
}
// ---------------------------------------------------------------------------
// Read a 16-bit value given as 2 consecutive bytes in MSB order
// Memory (at least 2 bytes) must have been allocated to pointer
// before the function is called.
// ---------------------------------------------------------------------------
//
TUint32 CRtpStpPacket::read16( const TUint8* const aPointer )
{
return( aPointer[1] + ( ( TUint32 ) aPointer[0] << 8 ) );
}
#if !defined ( EKA2 ) && !defined ( RTP_UNIT_TEST )
// The E32Dll() entry point function
GLDEF_C TInt E32Dll( TDllReason /*aReason*/ )
{
return( KErrNone );
}
#endif // EKA2
// ---------------------------------------------------------------------------
// Function to construct a CRtpPacketExt object. Note that this function
// is exported at ordinal 1 and is not a member of any class.
// ---------------------------------------------------------------------------
//
EXPORT_C MRtpPacketExt* NewL()
{
return new ( ELeave ) CRtpStpPacket;
}
// End of File