upnp/upnpstack/dlnawebserver/src/upnptcpserver.cpp
changeset 0 f5a58ecadc66
child 9 5c72fd91570d
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 /** @file
       
     2 * Copyright (c) 2005-2006 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:  Declares ControlPoint class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "upnptcpserver.h"
       
    21 #include <commdb.h>
       
    22 
       
    23 #include "upnpcons.h"
       
    24 #include "upnphttpsession.h"
       
    25 #define KLogFile _L("DLNAWebServer.txt")
       
    26 #include "upnpcustomlog.h"
       
    27 #include "upnphttpservertransactioncreator.h"
       
    28 
       
    29 #ifdef RD_UPNP_REMOTE_ACCESS
       
    30 #include "upnpipfiltermanager.h"
       
    31 #endif
       
    32 
       
    33 // Include for Publish and Subscribe
       
    34 #include <e32math.h>
       
    35 
       
    36 // ================= MEMBER FUNCTIONS =======================
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CUpnpTcpServer::CUpnpTcpServer
       
    40 // C++ default constructor
       
    41 // -----------------------------------------------------------------------------
       
    42 //
       
    43 CUpnpTcpServer::CUpnpTcpServer( RSocketServ* aSocketServ,
       
    44                                 TInt aPort,
       
    45                                 TInt aIap )
       
    46     : CActive( EPriorityNormal )
       
    47     {
       
    48     CActiveScheduler::Add( this );
       
    49 
       
    50     iServerPort = aPort;
       
    51     iSocketServ = aSocketServ;
       
    52     iActiveIap = aIap;
       
    53 
       
    54     iServerAddress = TInetAddr( INET_ADDR(0,0,0,0), 0 );
       
    55     iRetrySocketTimer = NULL;
       
    56     iFileReadBufferSize  = KRcvBufSizeDefault;
       
    57     iFileWriteBufferSize = KServeFileSizeDefault;
       
    58     }
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CUpnpTcpServer::BaseConstructL
       
    62 // TcpServer might-leave initialization method.
       
    63 // NOTE: Must be called by extending class
       
    64 // -----------------------------------------------------------------------------
       
    65 //
       
    66 void CUpnpTcpServer::BaseConstructL()
       
    67     {
       
    68     iRetrySocketTimer = CUpnpNotifyTimer::NewL( this );
       
    69 
       
    70     CreateConnectionManagerSessionL();
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CUpnpTcpServer::CUpnpTcpServer
       
    75 // C++ default destructor
       
    76 // -----------------------------------------------------------------------------
       
    77 //
       
    78 CUpnpTcpServer::~CUpnpTcpServer()
       
    79     {
       
    80     LOG_FUNC_NAME;
       
    81     PrepareToCloseSockets();
       
    82     delete iRetrySocketTimer;
       
    83     
       
    84     #ifdef RD_UPNP_REMOTE_ACCESS
       
    85     delete iIPFilteringManager;
       
    86     #endif
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 // CUpnpTcpServer::CreateConnectionManagerSessionL
       
    91 //
       
    92 // -----------------------------------------------------------------------------
       
    93 //
       
    94 void CUpnpTcpServer::CreateConnectionManagerSessionL()
       
    95     {
       
    96     if ( !iConnectionManagerProxy )
       
    97         {
       
    98         iConnectionManagerProxy = CUpnpConnectionManagerProxy::NewL( *iSocketServ );
       
    99         TInt error = iConnectionManagerProxy->EnsureStart();
       
   100         if ( error )
       
   101             {
       
   102             LOGS1H( iHandle, "CUpnpTcpServer::OpenSocketL *** Error in attaching: %d", error );
       
   103 
       
   104             // Nothing else to do but leave, connection is not possible and
       
   105             // can't access network
       
   106             User::LeaveIfError( error );
       
   107             }
       
   108         }
       
   109     }
       
   110 
       
   111 // -----------------------------------------------------------------------------
       
   112 // CUpnpTcpServer::ListenL
       
   113 // Listen incoming connections
       
   114 // -----------------------------------------------------------------------------
       
   115 //
       
   116 void CUpnpTcpServer::OpenSocketL()
       
   117     {
       
   118     CreateConnectionManagerSessionL();
       
   119 
       
   120     SetServerAddress( iConnectionManagerProxy->LocalAddress() );
       
   121     iActiveIap = iConnectionManagerProxy->ActiveIap();
       
   122 
       
   123     LOGSH( iHandle, "CUpnpTcpServer::ListenL()");
       
   124 
       
   125     TInt error = iServerSocket.Open( *iSocketServ, KAfInet, KSockStream,
       
   126                                       KProtocolInetTcp,
       
   127                                       iConnectionManagerProxy->ConnectionL() );
       
   128 
       
   129     if ( error != KErrNone)
       
   130         {
       
   131         LOGSH( iHandle, "CUpnpTcpServer ListenL - Open failed.");
       
   132         User::Leave( error );
       
   133         }
       
   134     }
       
   135 
       
   136 // -----------------------------------------------------------------------------
       
   137 // CUpnpTcpServer::BindRandomPortL
       
   138 // -----------------------------------------------------------------------------
       
   139 //
       
   140 void CUpnpTcpServer::BindRandomPortL()
       
   141     {
       
   142     LOG_FUNC_NAME;
       
   143     iServerPort = NewPortNumberL();
       
   144 
       
   145     TInetAddr addr =  TInetAddr(iServerPort);
       
   146 
       
   147     TInt error = iServerSocket.Bind( addr );
       
   148 
       
   149     if ( KErrNone == error )
       
   150         {
       
   151         error = StartToListenL();
       
   152         }
       
   153     // If the port is in use, then get a new port number and try again.
       
   154     else if ( KErrInUse == error )
       
   155         {
       
   156             LOGS1H( iHandle, "CUpnpTcpServer ListenL - Bind fail, trying new port: %d", iServerPort);
       
   157 
       
   158 
       
   159         while ( KErrInUse == error )
       
   160             {
       
   161             iServerPort = NewPortNumberL();
       
   162             iServerAddress.SetPort( iServerPort );
       
   163             error = iServerSocket.Bind( iServerAddress );
       
   164             if ( KErrNone == error )
       
   165                 {
       
   166                 error = StartToListenL();
       
   167                 }
       
   168             }
       
   169         if ( KErrNone != error )
       
   170             {
       
   171                 LOGS1H( iHandle, "CUpnpTcpServer ListenL Bind fail: %d", error);
       
   172 
       
   173             iServerSocket.Close();
       
   174             }
       
   175         }
       
   176     // Bind failed, close socket and log problem
       
   177     else
       
   178         {
       
   179         iServerSocket.Close();
       
   180             LOGS1H( iHandle, "CUpnpTcpServer ListenL -RSocket::Bind fail: %d", error);
       
   181         }
       
   182     // In case of failure, there is nothing else to do but leave.
       
   183     // Construction will fail.
       
   184     if ( KErrNone != error )
       
   185         {
       
   186         LOGSH( iHandle, "CUpnpTcpServer ListenL - Bind or listen failed.");
       
   187 
       
   188         User::Leave( error );
       
   189         }
       
   190     }
       
   191 
       
   192 // -----------------------------------------------------------------------------
       
   193 // CUpnpTcpServer::BindL
       
   194 // -----------------------------------------------------------------------------
       
   195 //
       
   196 void CUpnpTcpServer::BindL( const TInt aPort)
       
   197 {
       
   198     LOGS1H( iHandle , "CUpnpTcpServer BindL to fixed port %d" , aPort);
       
   199     iServerPort = aPort;
       
   200 
       
   201     TInetAddr addr( iServerPort );
       
   202     TInt error( iServerSocket.Bind( addr ) );
       
   203     if( error == KErrNone )
       
   204         {
       
   205         User::LeaveIfError( StartToListenL() );
       
   206         }
       
   207     else
       
   208         {
       
   209         LOGSH( iHandle, "CUpnpTcpServer ListenL - open, Bind or listen failed");
       
   210         iServerSocket.Close();
       
   211         User::Leave( error ) ;
       
   212         }
       
   213 
       
   214 }
       
   215 
       
   216 // -----------------------------------------------------------------------------
       
   217 // CUpnpTcpServer::StartToListenL
       
   218 // Start to listen a socket.
       
   219 // -----------------------------------------------------------------------------
       
   220 //
       
   221 TInt CUpnpTcpServer::StartToListenL()
       
   222     {
       
   223     TInt error = iServerSocket.Listen( UpnpSocket::KMaxConnectionsInQueue );
       
   224     if ( KErrNone == error )
       
   225         {
       
   226         // Both bind and listen ok, accept connection if OK
       
   227         LOGS1H( iHandle, "CUpnpTcpServer::StartToListenL - at port %i", ServerPort() );
       
   228 
       
   229         AcceptConnectionL();
       
   230         }
       
   231     // Listen failed, close socket and log problem
       
   232     else
       
   233         {
       
   234         iServerSocket.Close();
       
   235         LOGS1H( iHandle, "CUpnpTcpServer StartToListenL - fail: %d" , error);
       
   236         }
       
   237     return error;
       
   238     }
       
   239 
       
   240 // -----------------------------------------------------------------------------
       
   241 // CUpnpTcpServer::AcceptConnection
       
   242 // Open connection
       
   243 // -----------------------------------------------------------------------------
       
   244 //
       
   245 void CUpnpTcpServer::AcceptConnectionL()
       
   246     {
       
   247     LOG_FUNC_NAME;
       
   248     TInt error = 0;
       
   249 
       
   250     if( iSessionList.Count() >= KMaxConnectionCount )
       
   251     {
       
   252         LOGSH( iHandle, "CUpnpTcpServer::AcceptConnectionL - HTTP *** SessionList full");
       
   253 
       
   254         StartRetryTimer();
       
   255         return;
       
   256     }
       
   257 
       
   258     error = iClientSocket.Open( *iSocketServ );
       
   259     if ( error < KErrNone )
       
   260         {
       
   261         LOGS1H( iHandle, "CUpnpTcpServer::AcceptConnectionL - error to open client socket,%i", error);
       
   262 
       
   263         iClientSocket.Close();
       
   264 
       
   265         StartRetryTimer();
       
   266         }
       
   267     else
       
   268         {
       
   269         iServerSocket.Accept( iClientSocket, iStatus );
       
   270         SetActive();
       
   271         iState = EAccepting;
       
   272         LOGSH( iHandle, "CUpnpTcpServer::AcceptConnection - State = EAccepting ");
       
   273         }
       
   274 
       
   275     }
       
   276 
       
   277 // -----------------------------------------------------------------------------
       
   278 // CUpnpTcpServer::DeleteSession
       
   279 // Delete sessions.
       
   280 // -----------------------------------------------------------------------------
       
   281 //
       
   282 void CUpnpTcpServer::DeleteSession( CUpnpTcpSession* aSession )
       
   283     {
       
   284     LOG_FUNC_NAME;
       
   285     TInt pos = iSessionList.Find( aSession );
       
   286 
       
   287     if( pos != KErrNotFound )
       
   288         {
       
   289         iSessionList.Remove( pos );
       
   290         iSessionList.Compress();
       
   291         delete aSession;
       
   292         aSession = NULL;
       
   293         }
       
   294     }
       
   295 
       
   296 // -----------------------------------------------------------------------------
       
   297 // CUpnpTcpServer::RunL
       
   298 // State machine
       
   299 // -----------------------------------------------------------------------------
       
   300 //
       
   301 void CUpnpTcpServer::RunL()
       
   302     {
       
   303      switch ( iState )
       
   304         {
       
   305         case EAccepting:
       
   306             {
       
   307             if( iStatus == KErrNone )
       
   308                 {
       
   309                 iClientSocket.SetOpt( KSoTcpNoDelay, KSolInetTcp, 1 );
       
   310 
       
   311                 #ifdef RD_UPNP_REMOTE_ACCESS
       
   312 /**************     IPFIltering    ********************/
       
   313                 TInetAddr tempAddr;
       
   314                 iClientSocket.RemoteName( tempAddr );
       
   315                 tempAddr.ConvertToV4();
       
   316 
       
   317                 if( iIPFilteringManager && !iIPFilteringManager->IsAllowed( tempAddr ) )
       
   318                     {
       
   319                     iClientSocket.Close();  //mozliwe ze konieczny bedzie jeszcze
       
   320                                             //Shutdown - EImmediate; default jest ENormal
       
   321                     AcceptConnectionL()  ;
       
   322                     break;
       
   323                     }
       
   324 
       
   325                 #if _DEBUG
       
   326                 TBuf<20> addrBuf;
       
   327                 tempAddr.Output( addrBuf );
       
   328                 #endif
       
   329 /******************* IPFiltering END *******************/
       
   330                 #endif
       
   331 
       
   332                 CUpnpTcpSession* sess = ConnectionAcceptedL( iClientSocket );
       
   333                 iSessionList.Append( sess );
       
   334 
       
   335                 }
       
   336             else
       
   337                 {
       
   338                 iClientSocket.Close();
       
   339                 }
       
   340 
       
   341             AcceptConnectionL();
       
   342 
       
   343             break;
       
   344             }
       
   345 
       
   346         default:
       
   347             break;
       
   348         }
       
   349     }
       
   350 
       
   351 // -----------------------------------------------------------------------------
       
   352 // CUpnpTcpServer::RunError
       
   353 // RunError is called when RunL leaves.
       
   354 // -----------------------------------------------------------------------------
       
   355 //
       
   356 TInt CUpnpTcpServer::RunError( TInt aError )
       
   357     {
       
   358     LOGS1H( iHandle, "CUpnpTcpServer::RunError - Error: %d", aError);
       
   359     StartRetryTimer();
       
   360     return KErrNone;
       
   361     }
       
   362 
       
   363 // -----------------------------------------------------------------------------
       
   364 // CUpnpTcpServer::StopTcpServerL
       
   365 // Stop session and reset the lists
       
   366 // -----------------------------------------------------------------------------
       
   367 //
       
   368 void CUpnpTcpServer::StopTcpServerL()
       
   369     {
       
   370     LOG_FUNC_NAME;      
       
   371     for( TInt i(0) ; i < iSessionList.Count() ; i++ )
       
   372         {
       
   373         iSessionList[i]->NotifyTimeoutL();
       
   374         }
       
   375     PrepareToCloseSockets();     
       
   376     }
       
   377 
       
   378 // -----------------------------------------------------------------------------
       
   379 // CUpnpTcpServer::PrepareToCloseSockets
       
   380 // -----------------------------------------------------------------------------
       
   381 //
       
   382 void CUpnpTcpServer::PrepareToCloseSockets()
       
   383     {
       
   384     iSessionList.ResetAndDestroy();
       
   385     if ( IsActive() )
       
   386         {
       
   387         Cancel();
       
   388         }
       
   389     else
       
   390         {
       
   391         CancelRetryTimer();
       
   392         CloseSockets();
       
   393         }  
       
   394     delete iConnectionManagerProxy;
       
   395     iConnectionManagerProxy = NULL;    
       
   396     }
       
   397     
       
   398 // -----------------------------------------------------------------------------
       
   399 // CUpnpTcpServer::DoCancel
       
   400 // Cancel outstanding operations and close the connection
       
   401 // -----------------------------------------------------------------------------
       
   402 //
       
   403 void CUpnpTcpServer::DoCancel()
       
   404     {
       
   405     CancelRetryTimer();
       
   406 
       
   407     iServerSocket.CancelAll();
       
   408 
       
   409     CloseSockets();
       
   410 
       
   411     LOGSH( iHandle, "CUpnpTcpServer::DoCancel - iState = ENotListening" );
       
   412     }
       
   413 
       
   414 // -----------------------------------------------------------------------------
       
   415 // CUpnpTcpServer::CloseSockets
       
   416 // -----------------------------------------------------------------------------
       
   417 //
       
   418 void CUpnpTcpServer::CloseSockets()
       
   419     {
       
   420     iServerSocket.Close();
       
   421 
       
   422     iClientSocket.Close();
       
   423 
       
   424     iState = ENotListening;
       
   425     LOGSH( iHandle, "CUpnpTcpServer::CloseSockets - iState = ENotListening" );
       
   426     }
       
   427     
       
   428 // -----------------------------------------------------------------------------
       
   429 // CUpnpTcpServer::ServerAddress
       
   430 // Return server address.
       
   431 // -----------------------------------------------------------------------------
       
   432 //
       
   433 void CUpnpTcpServer::ServerAddress( TInetAddr& aAddr )
       
   434     {
       
   435     LOG_FUNC_NAME;
       
   436     aAddr = iServerAddress;
       
   437     }
       
   438 
       
   439 // -----------------------------------------------------------------------------
       
   440 // CUpnpTcpServer::SetServerAddress
       
   441 // Set new server address.
       
   442 // -----------------------------------------------------------------------------
       
   443 //
       
   444 void CUpnpTcpServer::SetServerAddress( const TInetAddr& aAddr )
       
   445     {
       
   446     iServerAddress = aAddr;
       
   447     }
       
   448 
       
   449 // -----------------------------------------------------------------------------
       
   450 // CUpnpTcpServer::ServerPort
       
   451 // Return server port number,
       
   452 // -----------------------------------------------------------------------------
       
   453 //
       
   454 TUint CUpnpTcpServer::ServerPort()
       
   455     {
       
   456     return iServerPort;
       
   457     }
       
   458 
       
   459 // -----------------------------------------------------------------------------
       
   460 // CUpnpTcpServer::HWAddressL
       
   461 // Return hardware address.
       
   462 // -----------------------------------------------------------------------------
       
   463 //
       
   464 TSockAddr* CUpnpTcpServer::HWAddressL()
       
   465     {
       
   466     LOG_FUNC_NAME;
       
   467     // Fetch IP address
       
   468     ServerAddress(iServerAddress);
       
   469 
       
   470     // return value is TSockAddr* because it won't work
       
   471     // correctly always with TSockAddr
       
   472     TPckgBuf<TSoInetInterfaceInfo> item;
       
   473 
       
   474     RSocket sock;
       
   475 
       
   476     TInt result = sock.Open( *iSocketServ, KAfInet, KSockStream,
       
   477         KProtocolInetTcp, iConnectionManagerProxy->ConnectionL() );
       
   478     if ( KErrNone == result )
       
   479         {
       
   480         result = sock.GetOpt( KSoInetNextInterface, KSolInetIfCtrl, item );
       
   481 
       
   482         // checking all interfaces. If interface has same IP address as socket, is
       
   483         // the current active interface. In this case we get that interface's
       
   484         // hardware address.
       
   485         while ( result == KErrNone )
       
   486             {
       
   487             TSoInetInterfaceInfo& ifInfo = item();
       
   488             TInetAddr ifAddr = ifInfo.iAddress;
       
   489             ifAddr.ConvertToV4();
       
   490             ifAddr.SetPort( iServerAddress.Port() );
       
   491             if ( ifAddr == iServerAddress )
       
   492                 {
       
   493                 sock.Close();
       
   494                 TSockAddr tempAddr = ifInfo.iHwAddr;
       
   495                 return new (ELeave) TSockAddr( tempAddr );
       
   496                 }
       
   497             result = sock.GetOpt( KSoInetNextInterface, KSolInetIfCtrl, item );
       
   498             }
       
   499         }
       
   500 
       
   501     sock.Close();
       
   502     return new (ELeave) TSockAddr();
       
   503     }
       
   504 
       
   505 
       
   506 // -----------------------------------------------------------------------------
       
   507 // CUpnpTcpServer::NewPortNumberL
       
   508 //
       
   509 // -----------------------------------------------------------------------------
       
   510 //
       
   511 TInt CUpnpTcpServer::NewPortNumberL()
       
   512     {
       
   513     LOG_FUNC_NAME;
       
   514     TInt id( 0 );
       
   515 
       
   516     //get random port
       
   517     TTime now;
       
   518     now.HomeTime();
       
   519     TInt64 randSeed = now.Int64();
       
   520     id =  Math::Rand( randSeed ) % (KInetMaxAutoPort-KInetMinAutoPort+1) + KInetMinAutoPort;
       
   521     return id;
       
   522     }
       
   523 
       
   524 // -----------------------------------------------------------------------------
       
   525 // CUpnpTcpServer::TimerEventL
       
   526 // Function is callback from iRetrySocketTimer. This timer is used
       
   527 // to retry to open new server socket.
       
   528 // -----------------------------------------------------------------------------
       
   529 //
       
   530 void CUpnpTcpServer::TimerEventL( CUpnpNotifyTimer* /*aTimer*/)
       
   531     {
       
   532     // Timer has expired, now trying to bind server socket again.
       
   533     LOGSH( iHandle, "CUpnpTcpServer::TimerEventL - retrying to open new socket server");
       
   534     AcceptConnectionL();
       
   535     }
       
   536 
       
   537 // -----------------------------------------------------------------------------
       
   538 // CUpnpTcpServer::StartRetryTimer
       
   539 // -----------------------------------------------------------------------------
       
   540 //
       
   541 void CUpnpTcpServer::StartRetryTimer()
       
   542     {
       
   543     CancelRetryTimer();
       
   544     iRetrySocketTimer->After(KRetryTime);
       
   545     }
       
   546 
       
   547 // -----------------------------------------------------------------------------
       
   548 // CUpnpTcpServer::SetFileWriteBufferSize
       
   549 // -----------------------------------------------------------------------------
       
   550 //
       
   551 void CUpnpTcpServer::SetFileWriteBufferSize(TInt aSize)
       
   552     {
       
   553     iFileWriteBufferSize = aSize;
       
   554     }
       
   555 
       
   556 
       
   557 // -----------------------------------------------------------------------------
       
   558 // CUpnpTcpServer::FileWriteBufferSize
       
   559 // -----------------------------------------------------------------------------
       
   560 //
       
   561 TInt CUpnpTcpServer::FileWriteBufferSize()
       
   562     {
       
   563     return iFileWriteBufferSize;
       
   564     }
       
   565 
       
   566 // -----------------------------------------------------------------------------
       
   567 // CUpnpTcpServer::SetFileReadBufferSize
       
   568 // -----------------------------------------------------------------------------
       
   569 //
       
   570 void CUpnpTcpServer::SetFileReadBufferSize(TInt aSize)
       
   571     {
       
   572     iFileReadBufferSize = aSize;
       
   573     }
       
   574 
       
   575 
       
   576 // -----------------------------------------------------------------------------
       
   577 // CUpnpTcpServer::FileReadBufferSize
       
   578 // -----------------------------------------------------------------------------
       
   579 //
       
   580 TInt CUpnpTcpServer::FileReadBufferSize()
       
   581     {
       
   582     return iFileReadBufferSize;
       
   583     }
       
   584 
       
   585 // -----------------------------------------------------------------------------
       
   586 // CUpnpTcpServer::GetServerAddress
       
   587 // Return server address.
       
   588 // -----------------------------------------------------------------------------
       
   589 //
       
   590 TBool CUpnpTcpServer::GetServerAddress( TInetAddr& aAddr )
       
   591     {
       
   592     aAddr = iServerAddress;
       
   593     return (iServerAddress.Address() != 0);
       
   594     }
       
   595 
       
   596 // -----------------------------------------------------------------------------
       
   597 // CUpnpTcpServer::CancelRetryTimer
       
   598 // -----------------------------------------------------------------------------
       
   599 //    
       
   600 void CUpnpTcpServer::CancelRetryTimer()
       
   601     {
       
   602     if ( iRetrySocketTimer )
       
   603         {
       
   604         iRetrySocketTimer->Cancel();
       
   605         }
       
   606     }
       
   607 
       
   608 //  End of File