upnp/upnpstack/ssdpserver/src/upnpudpserver.cpp
changeset 0 f5a58ecadc66
child 31 b51a6f4f15ba
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 /** @file
       
     2 * Copyright (c) 2005-2008 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 "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:  CUpnpUdpServer
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <in_iface.h>
       
    21 #include <e32math.h>
       
    22 #include <commdb.h>
       
    23 
       
    24 #include "upnpcons.h"
       
    25 #include "upnpudpsendrequest.h"
       
    26 #include "upnpudpserver.h"
       
    27 #define KLogFile _L("upnpudpserver.txt")
       
    28 #include "upnpcustomlog.h"
       
    29 #include "upnpstring.h"
       
    30 #include "upnplist.h"
       
    31 #include "upnpconnectionmanagerproxy.h"
       
    32 
       
    33 
       
    34 // CONSTANTS
       
    35 const TUint32 KUdpMessageSize = 2048;
       
    36 const TInt KTTLValue = 4;
       
    37 const TInt KMicrosecond = 1000000;
       
    38 const TInt KMXMaxValue = 120;
       
    39 const TInt KInetAddrPrefixMatchLen = 16;
       
    40 
       
    41 // ============================= LOCAL FUNCTIONS ===============================
       
    42 // -----------------------------------------------------------------------------
       
    43 // CleanupArray
       
    44 // Used by TCleanupItem to clean a RPointerArray<TPtrC>
       
    45 // -----------------------------------------------------------------------------
       
    46 //
       
    47 void CleanupArray( TAny* aArray )
       
    48     {
       
    49     ( reinterpret_cast<RPointerArray<TPtrC8>*>( aArray ) )->ResetAndDestroy();
       
    50     }
       
    51 
       
    52 // ============================ MEMBER FUNCTIONS ===============================
       
    53 
       
    54 // -----------------------------------------------------------------------------
       
    55 // CUpnpUdpServer::CUpnpUdpServer
       
    56 // C++ default constructor can NOT contain any code, that
       
    57 // might leave.
       
    58 // -----------------------------------------------------------------------------
       
    59 //
       
    60 CUpnpUdpServer::CUpnpUdpServer( RSocketServ* aSocketServ,
       
    61                         MUpnpUdpServerObserver* aObserver,
       
    62                         TInt aListeningPort )
       
    63     : CActive( EPriorityHigh ),
       
    64       iMulticastFlags( 0 ),
       
    65       iMessagePtr( NULL, 0,0 ),
       
    66       iIsStarted( EFalse )
       
    67     {
       
    68     LOGS( "SSDP *** CUpnpUdpServer::CUpnpUdpServer");
       
    69 
       
    70     CActiveScheduler::Add( this );
       
    71     iSocketServ = aSocketServ;
       
    72     iObserver = aObserver;
       
    73     iServerPort = aListeningPort;
       
    74 
       
    75     iRandomSeed = KErrNone;
       
    76     }
       
    77 
       
    78 // -----------------------------------------------------------------------------
       
    79 // CUpnpUdpServer::UdpConstructL
       
    80 // Symbian 2nd phase constructor can leave.
       
    81 // -----------------------------------------------------------------------------
       
    82 //
       
    83 void CUpnpUdpServer::UdpConstructL()
       
    84     {
       
    85     iSendMessage = NULL;
       
    86 
       
    87     iPendingTimerMessages = new (ELeave) CArrayPtrSeg<CUpnpSsdpMessage>( 1 );
       
    88 
       
    89     // Create local timer
       
    90     User::LeaveIfError( iSendTimer.CreateLocal() );
       
    91 
       
    92     iConnectionManagerProxy = CUpnpConnectionManagerProxy::NewL( *iSocketServ );
       
    93     TInt error = iConnectionManagerProxy->EnsureStart();
       
    94 
       
    95     if ( error )
       
    96         {
       
    97         LOGS1( "CUpnpTcpServer::ListenL *** Error in attaching RConnection: error: %d",
       
    98             error );
       
    99         // Nothing else to do but leave, connection is not possible and
       
   100         // can't access network
       
   101         User::LeaveIfError( error );
       
   102         }
       
   103 
       
   104     iActiveIap = iConnectionManagerProxy->ActiveIap();
       
   105     iLocalInterfaceAddress = iConnectionManagerProxy->LocalAddress();
       
   106 
       
   107     RefreshLocalAddressInfo();
       
   108     }
       
   109 
       
   110 // -----------------------------------------------------------------------------
       
   111 // CUpnpUdpServer::~CUpnpUdpServer()
       
   112 // Destructor.
       
   113 // -----------------------------------------------------------------------------
       
   114 //
       
   115 CUpnpUdpServer::~CUpnpUdpServer()
       
   116     {
       
   117     LOGS( "SSDP *** CUpnpUdpServer::~CUpnpUdpServer");
       
   118     Cancel();
       
   119     Close();
       
   120 
       
   121     iSendTimer.Close();
       
   122 
       
   123     iSendRequestList.ResetAndDestroy();
       
   124     iSendRequestList.Close();
       
   125 
       
   126     delete iSendMessage;
       
   127 
       
   128     delete iMessage;
       
   129 
       
   130     if( iPendingTimerMessages )
       
   131         {
       
   132         // Go through the messages and cancel timers
       
   133         for(TInt i=0; i< iPendingTimerMessages->Count(); i++)
       
   134             {
       
   135             CUpnpSsdpMessage* arrayMsg = iPendingTimerMessages->At( i );
       
   136             if( arrayMsg )
       
   137                 {
       
   138                 // Cancel the timer in the message
       
   139                 arrayMsg->CancelMessageTimeout();
       
   140                 }
       
   141             }
       
   142         // Destroy the whole message array
       
   143         iPendingTimerMessages->ResetAndDestroy();
       
   144         delete iPendingTimerMessages;
       
   145         iPendingTimerMessages = NULL;
       
   146         }
       
   147 
       
   148     // close network connection
       
   149     delete iConnectionManagerProxy;
       
   150     }
       
   151 
       
   152 // -----------------------------------------------------------------------------
       
   153 // CUpnpUdpServer::JoinMulticastGroupL
       
   154 // -----------------------------------------------------------------------------
       
   155 //
       
   156 void CUpnpUdpServer::JoinMulticastGroupL()
       
   157     {
       
   158     TIp6Mreq mreq;
       
   159     // the ipv4 multicast address that should use
       
   160     TInetAddr addr;
       
   161     addr.SetAddress( KDefaultMulticastAddress );
       
   162     addr.SetFamily( KAfInet );
       
   163     addr.ConvertToV4Mapped();
       
   164 
       
   165     mreq.iAddr = addr.Ip6Address();
       
   166     mreq.iInterface = 0;
       
   167     TPckgBuf< TIp6Mreq > opt( mreq );
       
   168 
       
   169     LOGS( "SSDP CUpnpUdpServer::JoinMulticastGroupL" );
       
   170     User::LeaveIfError( iSocket.SetOpt( KSoIp6JoinGroup, KSolInetIp, opt ) );
       
   171 
       
   172     }
       
   173 
       
   174 // -----------------------------------------------------------------------------
       
   175 // CUpnpUdpServer::ApplyMulticastSocketSettingsL
       
   176 // -----------------------------------------------------------------------------
       
   177 //
       
   178 void CUpnpUdpServer::ApplyMulticastSocketSettingsL()
       
   179     {
       
   180     LOGS( "SSDP CUpnpUdpServer::ApplyMulticastSocketSettingsL" );
       
   181 
       
   182     User::LeaveIfError( iSocket.SetOpt( KSoIp6MulticastLoop, KProtocolInetIp, 0 ) );
       
   183     User::LeaveIfError( iSocket.SetOpt( KSoReuseAddr, KProtocolInetIp, 1 ) );
       
   184 
       
   185     JoinMulticastGroupL();
       
   186     }
       
   187 
       
   188 // -----------------------------------------------------------------------------
       
   189 // CUpnpUdpServer::ApplyCommonSocketSettingsL
       
   190 // -----------------------------------------------------------------------------
       
   191 //
       
   192 void CUpnpUdpServer::ApplyCommonSocketSettingsL()
       
   193     {
       
   194     LOGS( "SSDP CUpnpUdpServer::ApplyCommonSocketSettingsL Socket TTL" );
       
   195 
       
   196     User::LeaveIfError( iSocket.SetOpt( KSoIpTTL, KSolInetIp, KTTLValue ) );
       
   197     User::LeaveIfError( iSocket.SetOpt( KSoIp6MulticastHops, KSolInetIp,
       
   198                                         KTTLValue ) );
       
   199     }
       
   200 
       
   201 // -----------------------------------------------------------------------------
       
   202 // CUpnpUdpServer::OpenL
       
   203 // -----------------------------------------------------------------------------
       
   204 //
       
   205 void CUpnpUdpServer::OpenL( )
       
   206     {
       
   207     if ( !IsStarted() )
       
   208         {
       
   209         TRAPD( error, OpenSocketAndStartReceiveL() )
       
   210         if ( error )
       
   211             {
       
   212             LOGS1( "SSDP CUpnpUdpServer::OpenL error: %d", error );
       
   213             Close();
       
   214             User::Leave( error );
       
   215             }
       
   216         else
       
   217             {
       
   218             iIsStarted = ETrue;
       
   219             }
       
   220         }
       
   221     }
       
   222 
       
   223 // -----------------------------------------------------------------------------
       
   224 // CUpnpUdpServer::OpenSocketAndStartReceiveL
       
   225 // -----------------------------------------------------------------------------
       
   226 //
       
   227 void CUpnpUdpServer::OpenSocketAndStartReceiveL( )
       
   228     {
       
   229     LOGS( "SSDP CUpnpUdpServer::OpenSocketAndStartReceiveL");
       
   230     TInt error = iSocket.Open( *iSocketServ, KAfInet,
       
   231         KSockDatagram, KProtocolInetUdp, iConnectionManagerProxy->ConnectionL() );
       
   232     User::LeaveIfError( error );
       
   233 
       
   234     User::LeaveIfError( iSocket.SetLocalPort( iServerPort ) );
       
   235     // for multicast start
       
   236     if ( KDefaultMulticastPort == iServerPort )
       
   237         {
       
   238         ApplyMulticastSocketSettingsL();
       
   239         }
       
   240 
       
   241     ApplyCommonSocketSettingsL();
       
   242 
       
   243     TInetAddr bindAddr;
       
   244     error = iSocket.Bind( bindAddr ) ;
       
   245     if( KErrNone != error && KErrAlreadyExists != error )
       
   246         {
       
   247         LOGS( "SSDP CUpnpUdpServer::OpenSocketAnd.. bind error: %d");
       
   248         User::Leave( error );
       
   249         }
       
   250 
       
   251     ReceiveL();
       
   252     }
       
   253 
       
   254 // -----------------------------------------------------------------------------
       
   255 // CUpnpUdpServer::IsStarted
       
   256 // -----------------------------------------------------------------------------
       
   257 //
       
   258 TBool CUpnpUdpServer::IsStarted()
       
   259     {
       
   260     return iIsStarted;
       
   261     }
       
   262 
       
   263 // -----------------------------------------------------------------------------
       
   264 // CUpnpUdpServer::SendL
       
   265 // Send a message.
       
   266 // -----------------------------------------------------------------------------
       
   267 //
       
   268 void CUpnpUdpServer::SendL( TDesC8& aBuffer, TInetAddr& anAddr )
       
   269     {
       
   270     LOGS( "SSDP *** CUpnpUdpServer::SendL");
       
   271 
       
   272     if ( !IsStarted() )
       
   273         {
       
   274         return;
       
   275         }
       
   276 
       
   277     if ( IsActive() && ( iState == ESendingTimer || iState == ESendDone ) )
       
   278         {
       
   279         CUpnpUdpSendRequest* req = CUpnpUdpSendRequest::NewL( aBuffer, anAddr );
       
   280         CleanupStack::PushL( req );
       
   281         iSendRequestList.AppendL( req );
       
   282         CleanupStack::Pop( req );
       
   283         }
       
   284     else
       
   285         {
       
   286         Cancel();
       
   287 
       
   288         delete iSendMessage;
       
   289         iSendMessage = NULL;
       
   290         iSendMessage = aBuffer.AllocL();
       
   291 
       
   292         iSenderAddress = anAddr;
       
   293         iSenderAddress.SetFamily( KAfInet );
       
   294 
       
   295         iSenderAddress.ConvertToV4Mapped();
       
   296 
       
   297         iSocket.SendTo( *iSendMessage,
       
   298                         iSenderAddress,
       
   299                         iMulticastFlags,
       
   300                         iStatus );
       
   301 
       
   302         iState = ESendingTimer; // in this state when RunL will be called after sending
       
   303                                 // message successfuly, the delay timer will start
       
   304         SetActive();
       
   305         }
       
   306     }
       
   307 
       
   308 // -----------------------------------------------------------------------------
       
   309 // CUpnpUdpServer::SendDoneL
       
   310 // Sending is done.
       
   311 // -----------------------------------------------------------------------------
       
   312 //
       
   313 void CUpnpUdpServer::SendDoneL()
       
   314     {
       
   315     LOGS( "SSDP *** CUpnpUdpServer::SendDoneL");
       
   316 
       
   317     delete iSendMessage;
       
   318     iSendMessage = NULL;
       
   319 
       
   320     if ( iSendRequestList.Count() > 0 )
       
   321         {
       
   322         CUpnpUdpSendRequest* request = iSendRequestList[0];
       
   323         iSendRequestList.Remove(0);
       
   324         iSendRequestList.Compress();
       
   325         CleanupStack::PushL( request );
       
   326         SendL( *(request->iBuffer), request->iAddr );
       
   327         CleanupStack::PopAndDestroy( request );
       
   328         }
       
   329     else
       
   330         {
       
   331         ReceiveL();
       
   332         }
       
   333     }
       
   334 
       
   335 // -----------------------------------------------------------------------------
       
   336 // CUpnpUdpServer::ReceiveL
       
   337 // Receive message.
       
   338 // -----------------------------------------------------------------------------
       
   339 //
       
   340 void CUpnpUdpServer::ReceiveL()
       
   341     {
       
   342     LOGS( "SSDP *** CUpnpUdpServer::ReceiveL");
       
   343 
       
   344     if ( !IsActive() )
       
   345         {
       
   346         // If iMessage is not yet created, do it now.
       
   347         // This pointer will be used until SSDP server is closed down.
       
   348         if ( !iMessage )
       
   349             {
       
   350             iMessage = HBufC8::NewL( KUdpMessageSize );
       
   351             }
       
   352 
       
   353         // Set data length to zero for the next RecvFrom
       
   354         iMessage->Des().SetLength( 0 );
       
   355 
       
   356         iMessagePtr.Set( (unsigned char*) iMessage->Ptr(), 0, KUdpMessageSize );
       
   357 
       
   358         iClientAddr.SetPort( iServerPort );
       
   359 
       
   360         iSocket.RecvFrom( iMessagePtr, iClientAddr, iMulticastFlags, iStatus );
       
   361 
       
   362         SetActive();
       
   363         iState = EReceiving;
       
   364         }
       
   365     }
       
   366 
       
   367 // -----------------------------------------------------------------------------
       
   368 // CUpnpUdpServer::RunL
       
   369 // -----------------------------------------------------------------------------
       
   370 //
       
   371 void CUpnpUdpServer::RunL()
       
   372     {
       
   373 
       
   374     if ( iStatus.Int() != KErrNone )
       
   375         {
       
   376         LOGS1( "SSDP *** CUpnpUdpServer::RunL - UDPServer error, error code: %d",
       
   377             iStatus.Int() );
       
   378 
       
   379         if ( iStatus.Int() != KErrCancel )
       
   380             {
       
   381             ReceiveL();
       
   382             }
       
   383         else
       
   384             {
       
   385             RestartOrContinueSendProcessingL();
       
   386             }
       
   387         }
       
   388     else
       
   389         {
       
   390         switch ( iState )
       
   391             {
       
   392             case ESendingTimer:                                // Introduce delay between sending messages to prevent from
       
   393                 // Introduce delay between sending messages to prevent from
       
   394                 iSendTimer.Cancel();               
       
   395                 iSendTimer.After( iStatus, KSendingDelay ); // SSDP notification storm.
       
   396                 iState = ESendDone;
       
   397                 SetActive();
       
   398                 break;
       
   399             case EReceiving:
       
   400                 {
       
   401                 TUint temp = iClientAddr.Address();
       
   402 
       
   403                 TUint port = iClientAddr.Port();
       
   404 
       
   405                 TInetAddr addr = TInetAddr( temp, port );
       
   406 
       
   407                 addr.SetFamily( KAfInet );
       
   408 #ifdef _DEBUG
       
   409                 TBuf8<KAddressLength> address;
       
   410                 CUpnpHttpMessage::AddrOutput(addr, address);
       
   411 
       
   412                 TBuf<KMaxName> logBuf;
       
   413                     logBuf.Copy( address.Left( logBuf.MaxLength() ) );
       
   414                 LOGS1( "SSDP *** CUpnpUdpServer::RunL - Received buffer from: %S",
       
   415                     &logBuf );
       
   416 #endif //_DEBUG
       
   417 
       
   418                 CUpnpSsdpMessage* msg = NULL;
       
   419 
       
   420                 TRAPD( err, msg = CUpnpSsdpMessage::NewL(
       
   421                     (TDesC8&) iMessagePtr, addr ) );
       
   422                 if ( err )
       
   423                     {
       
   424                     delete msg;
       
   425                     msg = NULL;
       
   426                     LOGS( "SSDP *** CUpnpUdpServer::RunL - Ssdp message parse failed. Ingoring message.");
       
   427                     RestartOrContinueProcessingL();
       
   428                     return;
       
   429                     }
       
   430                 CleanupStack::PushL(msg);
       
   431                 // check that given message is valid.
       
   432                 TInt error = ValidateSsdpMessageL( msg );
       
   433                 if( error == KErrNone )
       
   434                     {
       
   435 
       
   436                     // no error, message is put to receive queue, and it gets
       
   437                     // handled when the timer expires.
       
   438                     // KErrNone used for constant, because it always remains
       
   439                     // the same.
       
   440                     if( msg->IsSsdpMSearch() )
       
   441                         {
       
   442                         CleanupStack::Pop( msg );
       
   443 
       
   444                         AddPendingTimerMessageL( msg );
       
   445 
       
   446                         // no delete, message in array
       
   447                         msg = NULL;
       
   448                         }
       
   449                     else
       
   450                         {
       
   451                         //checks wether the Source IP is in same network i.e. auto-IP(169.254.X.X) or non-auto-IP range
       
   452 
       
   453                         TInetAddr autoIPAddr = TInetAddr( KDefaultAutoIPAddress,
       
   454                                                           KDefaultMulticastPort );
       
   455                         autoIPAddr.SetFamily( KAfInet );
       
   456 
       
   457                         if ( iAutoIP && autoIPAddr.Match( addr, KInetAddrPrefixMatchLen ) )
       
   458                             {
       
   459                             LOGS( "SSDP *** MESSAGE_FROM_AUTO_VERIFIED_NETWORK");
       
   460                             iObserver->UdpMessageReceivedL( msg );
       
   461                             }
       
   462                         else if ( !autoIPAddr.Match( addr, KInetAddrPrefixMatchLen ) )
       
   463                             {
       
   464                             LOGS( "SSDP *** MESSAGE_FROM_NON_AUTO_VERIFIED_NETWORK");
       
   465                             iObserver->UdpMessageReceivedL( msg );
       
   466                             }
       
   467 
       
   468                         CleanupStack::PopAndDestroy(msg);
       
   469                         }
       
   470                     }
       
   471                 else
       
   472                     {
       
   473                     // message not valid, delete it.
       
   474                     LOGS( "SSDP *** CUpnpUdpServer::RunL - Invalid SSDP message. Ingoring message.");
       
   475                     CleanupStack::PopAndDestroy(msg);
       
   476                     }
       
   477 
       
   478                 RestartOrContinueProcessingL();
       
   479 
       
   480                 }
       
   481                 break;
       
   482             case ESending:
       
   483                 delete iSendMessage;
       
   484                 iSendMessage = NULL;
       
   485                 RestartOrContinueProcessingL();
       
   486                 break;
       
   487 
       
   488             case ESendDone:
       
   489                 SendDoneL();
       
   490                 break;
       
   491 
       
   492             default:
       
   493                 // message not valid, delete it.
       
   494                 LOGS( "SSDP *** CUpnpUdpServer::RunL - DEFAULT CASE, NOTHING TO DO!");
       
   495                 break;
       
   496             }
       
   497         }
       
   498     }
       
   499 
       
   500 // -----------------------------------------------------------------------------
       
   501 // CUpnpSsdpServer::RunError
       
   502 // Active Object RunError called when RunL leaves.
       
   503 // -----------------------------------------------------------------------------
       
   504 //
       
   505 TInt CUpnpUdpServer::RunError( TInt aError )
       
   506     {
       
   507 LOGS1( "SSDP *** CUpnpUdpServer::RunError: %d", aError );
       
   508     TRAP_IGNORE( RestartOrContinueProcessingL() );
       
   509     return KErrNone;
       
   510     }
       
   511 
       
   512 // -----------------------------------------------------------------------------
       
   513 // CUpnpUdpServer::DoCancel
       
   514 // Active object DoCancel cancels active request.
       
   515 // -----------------------------------------------------------------------------
       
   516 //
       
   517 void CUpnpUdpServer::DoCancel()
       
   518     {
       
   519     iSocket.CancelAll();
       
   520     iSendTimer.Cancel();    
       
   521     }
       
   522 
       
   523 // -----------------------------------------------------------------------------
       
   524 // CUpnpUdpServer::CloseL
       
   525 // -----------------------------------------------------------------------------
       
   526 //
       
   527 void CUpnpUdpServer::Close()
       
   528     {
       
   529     LOGS( "SSDP *** CUpnpUdpServer::Close");
       
   530 
       
   531     if ( IsStarted() ) // socket can be not open correctly
       
   532         {
       
   533         Cancel();
       
   534         // for multicast start
       
   535         if(iServerPort == KDefaultMulticastPort)
       
   536             {
       
   537             TIp6Mreq mreq;
       
   538 
       
   539             TInetAddr addr;
       
   540             addr.SetAddress( KDefaultMulticastAddress );
       
   541             addr.SetPort(KDefaultMulticastPort);
       
   542             addr.SetFamily(KAfInet);
       
   543             addr.ConvertToV4Mapped();
       
   544             mreq.iAddr = addr.Ip6Address();
       
   545 
       
   546             mreq.iInterface = 0;
       
   547             TPckgBuf< TIp6Mreq > opt(mreq);
       
   548             iSocket.SetOpt(KSoIp6LeaveGroup, KSolInetIp, opt);
       
   549             }
       
   550         // for multicast end.
       
   551         }
       
   552     iSocket.Close();
       
   553     iIsStarted = EFalse;
       
   554     }
       
   555 
       
   556 // -----------------------------------------------------------------------------
       
   557 // CUpnpUdpServer::ValidateSsdpMessageL
       
   558 // Function validates SSDP messages. It checks that correct headers are
       
   559 // found etc.
       
   560 // (other items were commented in a header).
       
   561 // -----------------------------------------------------------------------------
       
   562 //
       
   563 CUpnpUdpServer::TSsdpValidity CUpnpUdpServer::ValidateSsdpMessageL( CUpnpSsdpMessage* aMsg )
       
   564     {
       
   565     CUpnpUdpServer::TSsdpValidity validity = CUpnpUdpServer::EMessageOk;
       
   566 
       
   567     // Message is search message
       
   568     if( aMsg->IsSsdpMSearch() )
       
   569         {
       
   570         // checking first line of message
       
   571         CUpnpHttpHeaderList* list=aMsg->HeaderList();
       
   572         CUpnpHttpHeader* header = list->First();
       
   573         if( header )
       
   574             {
       
   575             if(!CompareLinesL(header->Name(),UpnpSSDP::KMethodMSearch()))
       
   576                 {
       
   577                 // First line of message not "M-SEARCH * HTTP/1.1".
       
   578                 // Invalid message.
       
   579                validity = CUpnpUdpServer::EHeaderNotMSearch;
       
   580                 }
       
   581             }
       
   582         else
       
   583             {
       
   584             // no headers. Invalid message. no further handling.
       
   585             validity = CUpnpUdpServer::EHeadersMissing;
       
   586             return validity;
       
   587             }
       
   588 
       
   589         // no delete, owned by message.
       
   590         header=NULL;
       
   591         // no delete, owned by message.
       
   592         list=NULL;
       
   593 
       
   594         TDesC8& mxString = aMsg->GetHeaderValue( UpnpSSDP::KHdrMx() );
       
   595 
       
   596         // if no MX header found, not valid message.
       
   597         if( mxString != KNullDesC8() )
       
   598             {
       
   599             // try to parse value to TInt. If possible, then message is valid for MX check.
       
   600             TInt mxValue = 0;
       
   601             TInt errorInConversion = 0;
       
   602             TLex8 lex( mxString );
       
   603             errorInConversion = lex.Val(mxValue);
       
   604             // check that there are no errors in conversion. If error in conversion,
       
   605             // not valid SSDP MX header.
       
   606             if( errorInConversion != KErrNone || lex.Remainder().Length() > 0)
       
   607                 {
       
   608                 validity = CUpnpUdpServer::EErrorInMxConversion;
       
   609                 }
       
   610             else if( mxValue < 0 )
       
   611                 {
       
   612                 // check that MX value is positive. Negative value not valid.
       
   613                 validity = CUpnpUdpServer::EInvalidMXValue;
       
   614                 }
       
   615 
       
   616             // Checking if MAN header is found.
       
   617             TDesC8& manString = aMsg->GetHeaderValue( UpnpSSDP::KHdrMan() );
       
   618             if( manString != KNullDesC8() )
       
   619                 {
       
   620                 // MAN header found. Checking that is has valid value.
       
   621                 if( manString != UpnpSSDP::KNotificationDiscover() )
       
   622                     {
       
   623                     // MAN header value not "ssdp:discover". Invalid header.
       
   624                     validity = CUpnpUdpServer::EInvalidManHeader;
       
   625                     }
       
   626                 }
       
   627             else
       
   628                 {
       
   629                 // MAN header not found. Invalid message.
       
   630                 validity = CUpnpUdpServer::EInvalidManHeader;
       
   631                 }
       
   632 
       
   633             // Check that ST header is found.
       
   634             TDesC8& stString = aMsg->GetHeaderValue( UpnpSSDP::KHdrSt() );
       
   635             if( stString == KNullDesC8() )
       
   636                 {
       
   637                 // no ST header found. invalid SSDP search.
       
   638                 validity = CUpnpUdpServer::EInvalidStHeader;
       
   639                 }
       
   640 
       
   641             TDesC8& hostString = aMsg->GetHeaderValue( UpnpSSDP::KHdrHost() );
       
   642             if( hostString != UpnpSSDP::KDefaultHost() )
       
   643                 {
       
   644                 // HOST header not "239.255.255.250:1900". Invalid message.
       
   645                 validity = CUpnpUdpServer::EInvalidHostHeader;
       
   646                 }
       
   647             }
       
   648         else
       
   649             {
       
   650             // no MX header.
       
   651             validity = CUpnpUdpServer::EInvalidMXValue;
       
   652             }
       
   653         }
       
   654 
       
   655 
       
   656     // Message is SSDP response
       
   657     else if( aMsg->IsSsdpResponse() )
       
   658         {
       
   659         // if message is SSDP response, header should
       
   660         // be "HTTP/1.1 200 OK".
       
   661         CUpnpHttpHeaderList* list=aMsg->HeaderList();
       
   662         CUpnpHttpHeader* header = list->First();
       
   663         if( header )
       
   664             {
       
   665             if (!CompareLinesL(header->Name(),UpnpHTTP::KHTTPOk()))
       
   666                 {
       
   667                 // First line of message not "HTTP/1.1 200 OK".
       
   668                 // Invalid message.
       
   669                 LOGS( "SSDP *** CUpnpUdpServer::EBadSsdpResponse");
       
   670                 validity = CUpnpUdpServer::EBadSsdpResponse;
       
   671                 }
       
   672             }
       
   673         else
       
   674             {
       
   675             // no headers. Invalid message. no further handling.
       
   676             LOGS( "SSDP *** CUpnpUdpServer::EHeadersMissing");
       
   677             validity = CUpnpUdpServer::EHeadersMissing;
       
   678             return validity;
       
   679             }
       
   680 
       
   681         // no delete, owned by message.
       
   682         header=NULL;
       
   683         // no delete, owned by message.
       
   684         list=NULL;
       
   685 
       
   686         TDesC8& cache = aMsg->GetHeaderValue( UpnpSSDP::KHdrCacheControl() );
       
   687         if( cache != KNullDesC8() )
       
   688             {
       
   689             TPtrC8 cachePtr;
       
   690             cachePtr.Set( cache );
       
   691 
       
   692             TInt posOfMaxAge = cachePtr.FindC( UpnpSSDP::KSsdpMaxAge() );
       
   693             TInt posOfEqual = cachePtr.FindC( UpnpString::KEqual() );
       
   694             if (posOfMaxAge != KErrNotFound && posOfEqual!= KErrNotFound
       
   695                                             && posOfMaxAge < posOfEqual)
       
   696                 {
       
   697                 cachePtr.Set( cachePtr.Right((cachePtr.Length()
       
   698                     - UpnpString::KEqual().Length()) - posOfEqual) );
       
   699                 }
       
   700 
       
   701             TInt cacheValue = 0;
       
   702             TInt errorInConversion = 0;
       
   703             TLex8 lex( cachePtr );
       
   704             lex.SkipSpace();
       
   705             errorInConversion = lex.Val(cacheValue);
       
   706             // check that there are no errors in conversion.
       
   707             // If error in conversion, not valid
       
   708             // SSDP CACHE-CONTROL header.
       
   709             if( errorInConversion < KErrNone )
       
   710                 {
       
   711                 LOGS( "SSDP *** CUpnpUdpServer::EInvalidCacheControlHeader");
       
   712                 validity = CUpnpUdpServer::EInvalidCacheControlHeader;
       
   713                 }
       
   714             else if ( cacheValue < 0 )
       
   715                 {
       
   716                 // check that CACHE-CONTROL value is positive.
       
   717                 // Negative value not valid.
       
   718                 LOGS( "SSDP *** CUpnpUdpServer::EInvalidCacheControlHeader");
       
   719                 validity = CUpnpUdpServer::EInvalidCacheControlHeader;
       
   720                 }
       
   721             }
       
   722         else
       
   723             {
       
   724             // no CACHE-CONTROL header. Invalid message.
       
   725             LOGS( "SSDP *** CUpnpUdpServer::EInvalidCacheControlHeader");
       
   726             validity = CUpnpUdpServer::EInvalidCacheControlHeader;
       
   727             }
       
   728 
       
   729         }
       
   730 
       
   731     return validity;
       
   732     }
       
   733 
       
   734 // -----------------------------------------------------------------------------
       
   735 // CUpnpUdpServer::CompareLines
       
   736 // Compare two line ignoring number of space between elements
       
   737 // -----------------------------------------------------------------------------
       
   738 //
       
   739 TBool CUpnpUdpServer::CompareLinesL(const TDesC8& aValue, const TDesC8& aPattern)
       
   740     {
       
   741     TBool result = EFalse;
       
   742     TPtrC8 value(aValue);
       
   743     TPtrC8 pattern(aPattern);
       
   744     RPointerArray<TPtrC8> values;
       
   745     RPointerArray<TPtrC8> patterns;
       
   746     CleanupStack::PushL( TCleanupItem( CleanupArray, &values ) );
       
   747     CleanupStack::PushL( TCleanupItem( CleanupArray, &patterns ) );
       
   748 
       
   749     UpnpString::CutToPiecesL(value,UpnpString::KSpace()[0], values);
       
   750     UpnpString::CutToPiecesL(pattern,UpnpString::KSpace()[0], patterns);
       
   751 
       
   752     if (values.Count() == patterns.Count())
       
   753         {
       
   754         result = ETrue;
       
   755         for (TInt i = 0; i < values.Count(); i++)
       
   756             {
       
   757             if (patterns[i]->Compare(*(values[i])) != 0)
       
   758                 {
       
   759                 result = EFalse;
       
   760                 break;
       
   761                 }
       
   762             }
       
   763         }
       
   764 
       
   765     CleanupStack::PopAndDestroy( &patterns );
       
   766     CleanupStack::PopAndDestroy( &values );
       
   767     return result;
       
   768     }
       
   769 
       
   770 // -----------------------------------------------------------------------------
       
   771 // CUpnpUdpServer::RestartOrContinueSendProcessingL()
       
   772 // -----------------------------------------------------------------------------
       
   773 //
       
   774 TBool CUpnpUdpServer::RestartOrContinueSendProcessingL()
       
   775     {
       
   776     if ( iSendRequestList.Count() > 0 )
       
   777         {
       
   778         CUpnpUdpSendRequest* request = iSendRequestList[0];
       
   779         CleanupStack::PushL( request );
       
   780         iSendRequestList.Remove( 0 );
       
   781         iSendRequestList.Compress();
       
   782         SendL( *( request->iBuffer ), request->iAddr );
       
   783         CleanupStack::PopAndDestroy( request );
       
   784         return ETrue;
       
   785         }
       
   786     return EFalse;
       
   787     }
       
   788 
       
   789 // -----------------------------------------------------------------------------
       
   790 // CUpnpUdpServer::RestartOrContinueProcessing
       
   791 // -----------------------------------------------------------------------------
       
   792 //
       
   793 void CUpnpUdpServer::RestartOrContinueProcessingL()
       
   794     {
       
   795     if ( !RestartOrContinueSendProcessingL() )
       
   796         {
       
   797         ReceiveL();
       
   798         }
       
   799     }
       
   800 
       
   801 // -----------------------------------------------------------------------------
       
   802 // CUpnpUdpServer::MessageExpiredL
       
   803 // Function gets called when message's timer expires. This means that this
       
   804 // message should be sent.
       
   805 // -----------------------------------------------------------------------------
       
   806 //
       
   807 void CUpnpUdpServer::MessageExpiredL( CUpnpHttpMessage* aMessage )
       
   808     {
       
   809     LOGS( "SSDP *** CUpnpUdpServer::MessageExpiredL" );
       
   810 
       
   811     CUpnpSsdpMessage* msg = static_cast<CUpnpSsdpMessage*>( aMessage );
       
   812 
       
   813     // going thru array and removing current message from it.
       
   814     for ( TInt i = 0; i < iPendingTimerMessages->Count(); i++ )
       
   815         {
       
   816         CUpnpSsdpMessage* arrayMsg = iPendingTimerMessages->At( i );
       
   817         if ( arrayMsg == msg )
       
   818             {
       
   819             // Remove message from array and compress array.
       
   820             iPendingTimerMessages->Delete( i );
       
   821             iPendingTimerMessages->Compress();
       
   822             break;
       
   823             }
       
   824         }
       
   825     // Prevents WLan lost MessageHandler panic 
       
   826     // don't remove because if this function leaves msg is destroyed. 
       
   827     // Msg has CActive responsible for RunError as member so it will be destroyed and therefore
       
   828     // CActiveSheduler will cause unhandled exception which is seen as messagehandler panic
       
   829     TRAP_IGNORE( iObserver->UdpMessageReceivedL( msg ) );
       
   830     delete msg; 
       
   831     }
       
   832 
       
   833 // -----------------------------------------------------------------------------
       
   834 // CUpnpUdpServer::AddressChangedL()
       
   835 // Function gets called when the IP address of server is changed
       
   836 // -----------------------------------------------------------------------------
       
   837 //
       
   838 EXPORT_C void CUpnpUdpServer::AddressChangedL( TInetAddr& aAddr )
       
   839     {
       
   840     Close();
       
   841     iLocalInterfaceAddress = aAddr;
       
   842     RefreshLocalAddressInfo();
       
   843     OpenL();
       
   844     }
       
   845 
       
   846 // -----------------------------------------------------------------------------
       
   847 // CUpnpUdpServer::UpdateLocalAddressInfoL()
       
   848 // -----------------------------------------------------------------------------
       
   849 //
       
   850 void CUpnpUdpServer::RefreshLocalAddressInfo()
       
   851     {
       
   852 #ifdef _DEBUG
       
   853     TBuf<KAddressLength> buf;
       
   854     iLocalInterfaceAddress.Output( buf );
       
   855     LOGS1( "SSDP AddressChangedL IP: %S", &buf );
       
   856 #endif //_DEBUG
       
   857 
       
   858     TInetAddr addr = TInetAddr( KDefaultAutoIPAddress, KDefaultMulticastPort );
       
   859     addr.SetFamily( KAfInet );
       
   860 
       
   861     if ( iLocalInterfaceAddress.Match( addr, KInetAddrPrefixMatchLen ) )
       
   862         {
       
   863         iAutoIP = ETrue;
       
   864         LOGS( "SSDP AddressChangedL AUTO_IP" );
       
   865         }
       
   866     else
       
   867         {
       
   868         iAutoIP = EFalse;
       
   869         LOGS( "SSDP AddressChangedL NO_AUTO_IP" );
       
   870         }
       
   871     }
       
   872 
       
   873 // -----------------------------------------------------------------------------
       
   874 // CUpnpUdpServer::CalculateMxValue()
       
   875 // -----------------------------------------------------------------------------
       
   876 //
       
   877 TInt CUpnpUdpServer::CalculateMxValue( const TDesC8& aMxString )
       
   878     {
       
   879     TReal rand = Math::FRand( iRandomSeed );
       
   880 
       
   881     TLex8 lex( aMxString );
       
   882     TInt mxValue( 0 );
       
   883 
       
   884     TInt lexError = lex.Val( mxValue );
       
   885     if (( lexError != KErrNone ) || ( mxValue > KMXMaxValue )) // if delay in responsing more than 120 sec then it should be decreased until 120 sec
       
   886         {
       
   887         mxValue = KMXMaxValue;
       
   888         }
       
   889 
       
   890     // divide by two to ensure that the responses
       
   891     // come before the time expires
       
   892     TReal mx = rand * KMicrosecond * mxValue / 2;
       
   893     return mx;
       
   894     }
       
   895 
       
   896 // -----------------------------------------------------------------------------
       
   897 // CUpnpUdpServer::AddPendingTimerMessageL()
       
   898 // -----------------------------------------------------------------------------
       
   899 //
       
   900 void CUpnpUdpServer::AddPendingTimerMessageL( CUpnpSsdpMessage* aMessage )
       
   901     {
       
   902     // only 20 messages allowed from one IP
       
   903     const TInt KMaxMessageNumberFromOneIP = 20;
       
   904     
       
   905     TInt cnt = 0;
       
   906     for ( TInt i = 0; i < iPendingTimerMessages->Count(); i++ )
       
   907         {
       
   908         CUpnpSsdpMessage* msg = iPendingTimerMessages->At( i );
       
   909         if ( msg->Sender().Address() == aMessage->Sender().Address() )
       
   910             {
       
   911             if ( ++cnt > KMaxMessageNumberFromOneIP )
       
   912                 {
       
   913                 delete aMessage;
       
   914                 return;
       
   915                 }
       
   916             }
       
   917         }
       
   918 
       
   919     CleanupStack::PushL( aMessage );
       
   920 
       
   921     // parsing value for wait timer
       
   922     TInt mxUse = CalculateMxValue(
       
   923                         aMessage->GetHeaderValue( UpnpSSDP::KHdrMx() ) );
       
   924 
       
   925     // set message timeout so when timout occurs, message
       
   926     // get's handled.
       
   927     aMessage->SetMessageTimeoutL( this, mxUse );
       
   928 
       
   929     // appending message to array
       
   930     iPendingTimerMessages->AppendL( aMessage );
       
   931 
       
   932     CleanupStack::Pop( aMessage );
       
   933     }
       
   934 
       
   935 //  End of File
       
   936