dvrengine/CommonRecordingEngine/src/CCRRTSPResponse.cpp
branchRCL_3
changeset 22 826cea16efd9
parent 21 798ee5f1972c
child 23 13a33d82ad98
equal deleted inserted replaced
21:798ee5f1972c 22:826cea16efd9
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    RTSP response parser and producer*
       
    15 */
       
    16 
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CCRRtspResponse.h"
       
    22 #include "CRRTSPCommon.h"
       
    23 #include "videoserviceutilsLogger.h"
       
    24 
       
    25 // CONSTANTS
       
    26 const TInt KDVRMinRTSPResponseLen( 14 );
       
    27 
       
    28 // ============================ MEMBER FUNCTIONS ===============================
       
    29 
       
    30 // -----------------------------------------------------------------------------
       
    31 // CCRRtspResponse::CCRRtspResponse
       
    32 // C++ default constructor can NOT contain any code, that might leave.
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 CCRRtspResponse::CCRRtspResponse()
       
    36   : iStatusCode( ERTSPRespContinue ),
       
    37     iServerPort( KErrNotFound ),
       
    38     iSSRC( NULL, 0 )
       
    39     {  
       
    40     // None
       
    41     }
       
    42 
       
    43 // -----------------------------------------------------------------------------
       
    44 // CCRRtspResponse::NewL
       
    45 // Two-phased constructor.
       
    46 // -----------------------------------------------------------------------------
       
    47 //
       
    48 CCRRtspResponse* CCRRtspResponse::NewL()
       
    49     {
       
    50     CCRRtspResponse* self = new( ELeave ) CCRRtspResponse();
       
    51     CleanupStack::PushL( self );
       
    52     self->ConstructL();
       
    53     CleanupStack::Pop( self );
       
    54     return self;
       
    55     }
       
    56 
       
    57 // -----------------------------------------------------------------------------
       
    58 // CCRRtspResponse::ConstructL
       
    59 // Symbian 2nd phase constructor can leave.
       
    60 // -----------------------------------------------------------------------------
       
    61 //
       
    62 void CCRRtspResponse::ConstructL()
       
    63     {
       
    64     // None
       
    65     }
       
    66 
       
    67 // -----------------------------------------------------------------------------
       
    68 // CCRRtspResponse::~CCRRtspResponse
       
    69 // Destructor.
       
    70 // -----------------------------------------------------------------------------
       
    71 //
       
    72 CCRRtspResponse::~CCRRtspResponse()
       
    73     {
       
    74     LOG( "CCRRtspResponse::~CCRRtspResponse" );
       
    75     }
       
    76 
       
    77 // -----------------------------------------------------------------------------
       
    78 // CCRRtspResponse::TryParseL
       
    79 // 
       
    80 // -----------------------------------------------------------------------------
       
    81 //
       
    82 void CCRRtspResponse::TryParseL( const TDesC8 &aString ) 
       
    83     {
       
    84     if ( aString.Length() < KDVRMinRTSPResponseLen )
       
    85         {
       
    86         LOG( "CCRRtspResponse::TryParseL(), Length less than minimum, Leaved: KErrUnderflow" );
       
    87         User::Leave( KErrUnderflow ); 
       
    88         }
       
    89         
       
    90     // Copy the stuff into local variable:      
       
    91     delete iRtspText; iRtspText = NULL; 
       
    92     iRtspText = aString.AllocL(); 
       
    93     
       
    94     const TInt KReplyHeaderOffset( KCRRTSPReplyHeader().Length() );
       
    95     const TInt KStatusNumberLen( 5 );
       
    96     
       
    97     // Try to find out if end of the command has been received
       
    98     // "RTSP/1.0 XXX\r\n\r\n" at least..
       
    99     TInt replyEndOffSet = aString.FindC( KCR2NewLines() ); 
       
   100     if ( replyEndOffSet == KErrNotFound )
       
   101         {
       
   102         // Need to have more, do nothing yet.. except that some servers 
       
   103         // do not append 2 newlines to 404 or other error responses:
       
   104         if ( !aString.Left( KReplyHeaderOffset ).CompareC( KCRRTSPReplyHeader() ) )
       
   105             {
       
   106             TPtrC8 statusNumberString( 
       
   107                 aString.Mid( KReplyHeaderOffset, KStatusNumberLen ) );
       
   108             TLex8 statusNumberLex( statusNumberString ); 
       
   109             TInt statusCodeInteger( KErrNotFound ); 
       
   110             User::LeaveIfError ( statusNumberLex.Val( statusCodeInteger ) ) ;
       
   111             iStatusCode = static_cast<TResponseCode>( statusCodeInteger ); 
       
   112             if ( iStatusCode != ERTSPRespOK &&
       
   113                  iStatusCode != ERTSPRespCreated &&
       
   114                  iStatusCode != ERTSPRespProxyAuthenticationRequired &&
       
   115                  iStatusCode != ERTSPRespUnauthorized )
       
   116                 { 
       
   117                 // Was something else than ok or unauthorized-401
       
   118                 FindCSeqL();
       
   119                 LOG1( "CCRRtspResponse::TryParseL() out, with rtsp error code: %d", iStatusCode );
       
   120                 return; 
       
   121                 }
       
   122             }
       
   123         
       
   124         LOG( "CCRRtspResponse::TryParseL() out, because response not complete" );
       
   125         User::Leave( KErrUnderflow ); 
       
   126         }
       
   127         
       
   128     LOG1( "CCRRtspResponse::TryParseL(), replyEndOffSet: %d", replyEndOffSet );
       
   129 
       
   130     // Find status code:    
       
   131     if ( iRtspText->Left( KReplyHeaderOffset ).CompareC( KCRRTSPReplyHeader() ) == 0 )
       
   132         {
       
   133         TPtrC8 statusNumberString( iRtspText->Mid(
       
   134             KReplyHeaderOffset, KStatusNumberLen ) );
       
   135         TLex8 statusNumberLex( statusNumberString ); 
       
   136         TInt statusCodeInteger( KErrNotFound ); 
       
   137         User::LeaveIfError ( statusNumberLex.Val( statusCodeInteger ) );
       
   138         iStatusCode = ( TResponseCode )( statusCodeInteger ); 
       
   139         }
       
   140     else
       
   141         {
       
   142         LOG( "CCRRtspResponse::TryParseL(), Statuscode integer not found !" );
       
   143         User::Leave( KErrNotSupported ); 
       
   144         }       
       
   145         
       
   146     LOG1( "CCRRtspResponse::TryParseL(), iStatusCode: %d", iStatusCode );
       
   147 
       
   148     FindContentL(); 
       
   149     // Then find CSeq
       
   150     FindCSeqL();    
       
   151     // Then find session id
       
   152     FindSessionIdL(); 
       
   153     // Then find server ports
       
   154     FindServerPorts();
       
   155     // Then find SSRC
       
   156     FindSSRC();  
       
   157     // Then try finding rtp-info header if it was play reply
       
   158     FindRTPInfoHeader();
       
   159     // Find possible transport method
       
   160     // IMPORTANT: should be done before parsing client port
       
   161     FindTransport();
       
   162     // Find possible client port
       
   163     FindClientPorts(); 
       
   164     if ( iServerPort == KErrNotFound && iClientPort != KErrNotFound )
       
   165         {
       
   166         LOG( "CCRRtspResponse::TryParseL(), using client port as server port -> UGLY!!" );
       
   167         iServerPort = iClientPort ; 
       
   168         }
       
   169     // Find destination address is existing
       
   170     FindDestination();
       
   171     // Try finding authentication
       
   172     FindRTPAuthenticationL();
       
   173     // Try to find range header
       
   174     ParseRange(); 
       
   175     // Try to find session-base header
       
   176     FindContentBase(); 
       
   177     }
       
   178 
       
   179 // -----------------------------------------------------------------------------
       
   180 // CCRRtspResponse::StatusCode
       
   181 // 
       
   182 // -----------------------------------------------------------------------------
       
   183 //
       
   184 CCRRtspResponse::TResponseCode CCRRtspResponse::StatusCode( void ) 
       
   185     {
       
   186     return iStatusCode;     
       
   187     }
       
   188     
       
   189 // -----------------------------------------------------------------------------
       
   190 // CCRRtspResponse::FindServerPorts
       
   191 //
       
   192 // method that finds server port numeric value
       
   193 // -----------------------------------------------------------------------------
       
   194 //  
       
   195 void CCRRtspResponse::FindServerPorts( void )
       
   196     {
       
   197     iServerPort = KErrNotFound;                 
       
   198     TInt portNumberOffset( iRtspText->FindC( KCRServerPort ) ); 
       
   199     if ( portNumberOffset != KErrNotFound )
       
   200         {
       
   201         const TInt KDVRPortNumberMaxLen ( 5 ) ; 
       
   202         TPtrC8 portNumberStr( iRtspText->Mid( 
       
   203            portNumberOffset + KCRServerPort().Length() + 1, KDVRPortNumberMaxLen ) );
       
   204         TLex8 portNumberLex( portNumberStr );
       
   205         if ( portNumberLex.Val( iServerPort ) != KErrNone )
       
   206             { // something wrong? 
       
   207             LOG( "CCRRtspResponse::FindServerPorts(), portNumberLex.Val() != KErrNone" );
       
   208             iServerPort = KErrNotFound;             
       
   209             }
       
   210         }
       
   211     }
       
   212 
       
   213 // -----------------------------------------------------------------------------
       
   214 // CCRRtspResponse::ServerPort
       
   215 //
       
   216 // method that returns server port numeric value
       
   217 // -----------------------------------------------------------------------------
       
   218 //  
       
   219 TInt CCRRtspResponse::ServerPort( void )
       
   220     {
       
   221     return iServerPort; 
       
   222     }
       
   223 
       
   224 // -----------------------------------------------------------------------------
       
   225 // CCRRtspResponse::FindSSRC
       
   226 //
       
   227 // -----------------------------------------------------------------------------
       
   228 //
       
   229 void CCRRtspResponse::FindSSRC( void ) 
       
   230     {
       
   231     LOG( "CCRRtspResponse::FindSSRC() in" );
       
   232     TInt SSRCOffset( KErrNotFound );
       
   233     iSSRC.Set( NULL, 0 );
       
   234         
       
   235     if ( ( SSRCOffset = iRtspText->FindC( KCRSSRC ) ) != KErrNotFound )
       
   236         {
       
   237         TPtrC8 SSRCStr( iRtspText->Right( 
       
   238                       ( iRtspText->Length() -  SSRCOffset ) - 6 ) );
       
   239         TInt SSRCLen( 0 ); 
       
   240         for ( TInt i( 0 ); i < SSRCStr.Length(); i++ )
       
   241             {
       
   242             if ( TChar( SSRCStr[i] ).IsAlphaDigit() ) 
       
   243                 {
       
   244                 SSRCLen++;
       
   245                 }
       
   246             else
       
   247                 {
       
   248                 iSSRC.Set( SSRCStr.Mid( 0, SSRCLen ) );
       
   249                 }
       
   250             }
       
   251         }
       
   252     }
       
   253 
       
   254 // -----------------------------------------------------------------------------
       
   255 // CCRRtspResponse::SSRC
       
   256 //
       
   257 // method that returns SSRC string
       
   258 // -----------------------------------------------------------------------------
       
   259 //  
       
   260 TInt CCRRtspResponse::SSRC( TPtrC8& aSSRC ) 
       
   261     {
       
   262     if ( iSSRC.Ptr() != NULL )  
       
   263         {
       
   264         aSSRC.Set( iSSRC ); 
       
   265         return KErrNone;
       
   266         }
       
   267     else
       
   268         {
       
   269         return KErrNotFound; 
       
   270         }       
       
   271     }
       
   272     
       
   273 // -----------------------------------------------------------------------------
       
   274 // CCRRtspResponse::FindRTPInfoHeader
       
   275 //
       
   276 // method that partially parses rtp info header
       
   277 // -----------------------------------------------------------------------------
       
   278 //  
       
   279 void CCRRtspResponse::FindRTPInfoHeader( void ) 
       
   280     {
       
   281     TInt offset = iRtspText->FindC( KCRRtpInfo ); // "Rtp-Info: "
       
   282     TInt url2OffSet( KErrNotFound );
       
   283 
       
   284     iRTPInfoHeader.iFirstURL.Set( NULL , 0 );
       
   285     iRTPInfoHeader.iFirstSeq = 0; 
       
   286     iRTPInfoHeader.iFirstTS = 0; 
       
   287     iRTPInfoHeader.iSecondURL.Set( NULL, 0 );
       
   288     iRTPInfoHeader.iSecondSeq = 0; 
       
   289     iRTPInfoHeader.iSecondTS = 0;   
       
   290     
       
   291     if ( offset > 0 ) 
       
   292         { 
       
   293         // Yes, there is header. That seems to be sucky to parse. We have delimiting 
       
   294         // characters ,; and nl and we may or may not find words url, seq and rtptime
       
   295         // and maybe something else. We  may be confident that there will be at max
       
   296         // 2 url  srings
       
   297         offset += KCRRtpInfo().Length(); // add the len of "RTP-Info: "
       
   298         TPtrC8 rtpInfoContent = iRtspText->Right( iRtspText->Length() - offset );
       
   299         TInt urlOffSet = rtpInfoContent.FindC( KCRUrlStr );
       
   300         
       
   301         for ( TInt i( 0 ); urlOffSet != KErrNotFound && i < 2; i ++ ) 
       
   302             { 
       
   303             // At least one url string found
       
   304             TPtrC8 urlContent( iRtspText->Right( iRtspText->Length() -
       
   305                              ( offset + urlOffSet + 4 ) ) );
       
   306             // Above string now contains rest of the PLAY commands RTSP OK response
       
   307             // so in practice there is 2 url-strings. If so, find the next one 
       
   308             // and cut our string 
       
   309             if ( ( url2OffSet = urlContent.FindC( KCRUrlStr ) ) > 0 )  
       
   310                 {
       
   311                 urlContent.Set( urlContent.Left( url2OffSet ) );
       
   312                 }
       
   313             
       
   314             // Ok, now there is only one url string in urlContent. 
       
   315             // then just find seq and ts
       
   316             TInt seqOffSet = urlContent.FindC( KCRSeqStr ); 
       
   317             if ( seqOffSet != KErrNotFound ) 
       
   318                 {
       
   319                 TPtrC8 seqContent( urlContent.Right( urlContent.Length() -
       
   320                                  ( seqOffSet + KCRSeqStr().Length() ) ) );
       
   321                 TLex8 seqLex( seqContent ); 
       
   322                 if ( seqLex.Val( ( iRTPInfoHeader.iFirstURL.Length() == 0 )? 
       
   323                     iRTPInfoHeader.iFirstSeq : iRTPInfoHeader.iSecondSeq,
       
   324                     EDecimal ) == KErrNone )
       
   325                     {
       
   326                     TInt tsOffSet( urlContent.FindC( KCRRtptimeStr ) );
       
   327                     if ( tsOffSet != KErrNotFound ) 
       
   328                         {
       
   329                         TPtrC8 tsContent( urlContent.Right( urlContent.Length() -
       
   330                                         ( tsOffSet + KCRRtptimeStr().Length() ) ) );
       
   331                         TLex8 tsLex( tsContent ); 
       
   332                         tsLex.Val( ( iRTPInfoHeader.iFirstURL.Length() == 0 )? 
       
   333                                      iRTPInfoHeader.iFirstTS: 
       
   334                                      iRTPInfoHeader.iSecondTS, EDecimal );
       
   335                         }
       
   336                     }
       
   337                 else
       
   338                     {
       
   339                     urlContent.Set ( NULL , 0 ) ;
       
   340                     }                   
       
   341                 }    
       
   342             else
       
   343                 {
       
   344                 urlContent.Set ( NULL , 0 ) ;
       
   345                 }           
       
   346             
       
   347             if ( urlContent.Length() > 0 ) 
       
   348                 {
       
   349                 TInt semicolonOffSet( urlContent.Locate(';') );  
       
   350                 const TInt KDVRMinSemicolonOffset ( 5 ) ;
       
   351                 if ( iRTPInfoHeader.iFirstURL.Length() == 0 && semicolonOffSet > KDVRMinSemicolonOffset )
       
   352                     {
       
   353                     iRTPInfoHeader.iFirstURL.Set(
       
   354                         urlContent.Mid( 0, semicolonOffSet ) ); 
       
   355                     }
       
   356                 else
       
   357                     {
       
   358                     const TInt KDVRURLBeginOffset ( 4 ) ; 
       
   359                     iRTPInfoHeader.iSecondURL.Set( 
       
   360                         urlContent.Mid( KDVRURLBeginOffset,
       
   361                         semicolonOffSet - KDVRURLBeginOffset ) ); 
       
   362                     }
       
   363                 }
       
   364             
       
   365             // Then continue with next url
       
   366             urlOffSet = url2OffSet;
       
   367             } 
       
   368         }   
       
   369     }   
       
   370 
       
   371 // -----------------------------------------------------------------------------
       
   372 // CCRRtspResponse::RTPInfoHeader
       
   373 //
       
   374 // method that returns rtp-info header content
       
   375 // -----------------------------------------------------------------------------
       
   376 //  
       
   377 TInt CCRRtspResponse::RTPInfoHeader(
       
   378     CCRRtspResponse::SRTPInfoHeader &aRTPInfoHeader ) 
       
   379     {
       
   380     if ( iRTPInfoHeader.iFirstURL.Length() == 0  )
       
   381         {
       
   382         return KErrNotFound;
       
   383         }
       
   384     else
       
   385         {
       
   386         aRTPInfoHeader.iFirstURL.Set( iRTPInfoHeader.iFirstURL ); 
       
   387         aRTPInfoHeader.iFirstSeq = iRTPInfoHeader.iFirstSeq; 
       
   388         aRTPInfoHeader.iFirstTS = iRTPInfoHeader.iFirstTS; 
       
   389         aRTPInfoHeader.iSecondURL.Set( iRTPInfoHeader.iSecondURL ); 
       
   390         aRTPInfoHeader.iSecondSeq = iRTPInfoHeader.iSecondSeq; 
       
   391         aRTPInfoHeader.iSecondTS = iRTPInfoHeader.iSecondTS;
       
   392                 
       
   393         return KErrNone; 
       
   394         }
       
   395     }
       
   396     
       
   397 // -----------------------------------------------------------------------------
       
   398 // CCRRtspResponse::FindRTPAuthenticationL
       
   399 //
       
   400 // method that partially parses rtp authentication header
       
   401 // -----------------------------------------------------------------------------
       
   402 //  
       
   403 void CCRRtspResponse::FindRTPAuthenticationL( void ) 
       
   404     {
       
   405     TInt endPos( KErrNotFound );
       
   406     
       
   407     // First look for authorization method(basic / digest)
       
   408     TInt pos = iRtspText->FindC( KCRAuthDigest );
       
   409     
       
   410     // digest
       
   411     if ( pos != KErrNotFound ) 
       
   412         {       
       
   413         // Digest found, we can continue
       
   414         LOG( "CCRRtspResponse::FindRTPAuthenticationL() Digest found" );
       
   415         
       
   416         delete iAuthType;
       
   417         iAuthType = NULL;
       
   418         iAuthType = HBufC8::NewL( KCRAuthDigest().Length() );
       
   419         iAuthType->Des().Copy( KCRAuthDigest );
       
   420             
       
   421         // find "realm"
       
   422         pos = iRtspText->FindC( KCRAuthRealm );
       
   423         if ( pos != KErrNotFound ) 
       
   424             {
       
   425             LOG( "CCRRtspResponse::FindRTPAuthenticationL() realm found" );
       
   426             pos = pos + KCRAuthRealm().Length(); // realm
       
   427             endPos = iRtspText->Mid( pos ).LocateF( '"' );
       
   428             
       
   429             if ( endPos != KErrNotFound ) 
       
   430                 {
       
   431                 TPtrC8 data = iRtspText->Mid( pos ).Left( endPos );
       
   432                 delete iRealm;
       
   433                 iRealm = NULL;
       
   434                 iRealm = HBufC8::NewL( data.Length() );
       
   435                 iRealm->Des().Copy( data ); 
       
   436                 }
       
   437             }
       
   438         
       
   439         // Find "nonce"
       
   440         pos = iRtspText->FindC( KCRAuthNonce() );
       
   441         if ( pos != KErrNotFound ) 
       
   442             {
       
   443             LOG( "CCRRtspResponse::FindRTPAuthenticationL() nonce found" );
       
   444             pos = pos + KCRAuthNonce().Length(); // nonce
       
   445             endPos = iRtspText->Mid( pos ).LocateF( '"' );
       
   446             if ( endPos != KErrNotFound ) 
       
   447                 {
       
   448                 TPtrC8 nonceData = iRtspText->Mid( pos ).Left( endPos );
       
   449                 delete iNonce;
       
   450                 iNonce = NULL;
       
   451                 iNonce = HBufC8::NewL( nonceData.Length() );
       
   452                 iNonce->Des().Copy( nonceData );
       
   453                 }
       
   454             }
       
   455         
       
   456         // Find "opaque"(it seems that Darwin streaming server does not send this one)
       
   457         pos = iRtspText->FindC( KCRAuthOpaque() );
       
   458         if ( pos != KErrNotFound )
       
   459             {
       
   460             LOG( "CCRRtspResponse::FindRTPAuthenticationL() opaque found" );
       
   461             pos = pos + KCRAuthOpaque().Length(); // opaque
       
   462             endPos = iRtspText->Mid( pos ).LocateF( '"' );
       
   463             if ( endPos != KErrNotFound ) 
       
   464                 {
       
   465                 TPtrC8 opaqData = iRtspText->Mid( pos ).Left( endPos );
       
   466                 delete iOpaque;
       
   467                 iOpaque = NULL;
       
   468                 iOpaque = HBufC8::NewL( opaqData.Length() );
       
   469                 iOpaque->Des().Copy( opaqData );
       
   470                 }
       
   471             }
       
   472         }
       
   473     
       
   474     // basic
       
   475     else
       
   476         {
       
   477         pos = iRtspText->FindC( KCRAuthBasic );
       
   478         
       
   479         if ( pos != KErrNotFound ) 
       
   480             {
       
   481             LOG( "CCRRtspResponse::FindRTPAuthenticationL() Basic found" );
       
   482             
       
   483             delete iAuthType;
       
   484             iAuthType = NULL;
       
   485             iAuthType = HBufC8::NewL( KCRAuthBasic().Length() );
       
   486             iAuthType->Des().Copy( KCRAuthBasic );
       
   487                       
       
   488             // find "realm"
       
   489             pos = iRtspText->FindC( KCRAuthRealm );
       
   490             
       
   491             if ( pos != KErrNotFound ) 
       
   492                 {
       
   493                 LOG( "CCRRtspResponse::FindRTPAuthenticationL() realm found" );
       
   494                 pos = pos + KCRAuthRealm().Length(); // realm
       
   495                 endPos = iRtspText->Mid( pos ).LocateF( '"' );
       
   496                         
       
   497                 if ( endPos != KErrNotFound ) 
       
   498                     {
       
   499                     TPtrC8 data = iRtspText->Mid( pos ).Left( endPos );
       
   500                     delete iRealm;
       
   501                     iRealm = NULL;
       
   502                     iRealm = HBufC8::NewL( data.Length() );
       
   503                     iRealm->Des().Copy( data ); 
       
   504                     }
       
   505                 }
       
   506             }
       
   507         }
       
   508     }
       
   509 
       
   510 //  End of File