diff -r 000000000000 -r f5a58ecadc66 upnp/upnpstack/dlnawebserver/src/upnptcpserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnp/upnpstack/dlnawebserver/src/upnptcpserver.cpp Tue Feb 02 01:12:20 2010 +0200 @@ -0,0 +1,608 @@ +/** @file +* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Declares ControlPoint class. +* +*/ + + +// INCLUDE FILES +#include "upnptcpserver.h" +#include + +#include "upnpcons.h" +#include "upnphttpsession.h" +#define KLogFile _L("DLNAWebServer.txt") +#include "upnpcustomlog.h" +#include "upnphttpservertransactioncreator.h" + +#ifdef RD_UPNP_REMOTE_ACCESS +#include "upnpipfiltermanager.h" +#endif + +// Include for Publish and Subscribe +#include + +// ================= MEMBER FUNCTIONS ======================= + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::CUpnpTcpServer +// C++ default constructor +// ----------------------------------------------------------------------------- +// +CUpnpTcpServer::CUpnpTcpServer( RSocketServ* aSocketServ, + TInt aPort, + TInt aIap ) + : CActive( EPriorityNormal ) + { + CActiveScheduler::Add( this ); + + iServerPort = aPort; + iSocketServ = aSocketServ; + iActiveIap = aIap; + + iServerAddress = TInetAddr( INET_ADDR(0,0,0,0), 0 ); + iRetrySocketTimer = NULL; + iFileReadBufferSize = KRcvBufSizeDefault; + iFileWriteBufferSize = KServeFileSizeDefault; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::BaseConstructL +// TcpServer might-leave initialization method. +// NOTE: Must be called by extending class +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::BaseConstructL() + { + iRetrySocketTimer = CUpnpNotifyTimer::NewL( this ); + + CreateConnectionManagerSessionL(); + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::CUpnpTcpServer +// C++ default destructor +// ----------------------------------------------------------------------------- +// +CUpnpTcpServer::~CUpnpTcpServer() + { + LOG_FUNC_NAME; + PrepareToCloseSockets(); + delete iRetrySocketTimer; + + #ifdef RD_UPNP_REMOTE_ACCESS + delete iIPFilteringManager; + #endif + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::CreateConnectionManagerSessionL +// +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::CreateConnectionManagerSessionL() + { + if ( !iConnectionManagerProxy ) + { + iConnectionManagerProxy = CUpnpConnectionManagerProxy::NewL( *iSocketServ ); + TInt error = iConnectionManagerProxy->EnsureStart(); + if ( error ) + { + LOGS1H( iHandle, "CUpnpTcpServer::OpenSocketL *** Error in attaching: %d", error ); + + // Nothing else to do but leave, connection is not possible and + // can't access network + User::LeaveIfError( error ); + } + } + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::ListenL +// Listen incoming connections +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::OpenSocketL() + { + CreateConnectionManagerSessionL(); + + SetServerAddress( iConnectionManagerProxy->LocalAddress() ); + iActiveIap = iConnectionManagerProxy->ActiveIap(); + + LOGSH( iHandle, "CUpnpTcpServer::ListenL()"); + + TInt error = iServerSocket.Open( *iSocketServ, KAfInet, KSockStream, + KProtocolInetTcp, + iConnectionManagerProxy->ConnectionL() ); + + if ( error != KErrNone) + { + LOGSH( iHandle, "CUpnpTcpServer ListenL - Open failed."); + User::Leave( error ); + } + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::BindRandomPortL +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::BindRandomPortL() + { + LOG_FUNC_NAME; + iServerPort = NewPortNumberL(); + + TInetAddr addr = TInetAddr(iServerPort); + + TInt error = iServerSocket.Bind( addr ); + + if ( KErrNone == error ) + { + error = StartToListenL(); + } + // If the port is in use, then get a new port number and try again. + else if ( KErrInUse == error ) + { + LOGS1H( iHandle, "CUpnpTcpServer ListenL - Bind fail, trying new port: %d", iServerPort); + + + while ( KErrInUse == error ) + { + iServerPort = NewPortNumberL(); + iServerAddress.SetPort( iServerPort ); + error = iServerSocket.Bind( iServerAddress ); + if ( KErrNone == error ) + { + error = StartToListenL(); + } + } + if ( KErrNone != error ) + { + LOGS1H( iHandle, "CUpnpTcpServer ListenL Bind fail: %d", error); + + iServerSocket.Close(); + } + } + // Bind failed, close socket and log problem + else + { + iServerSocket.Close(); + LOGS1H( iHandle, "CUpnpTcpServer ListenL -RSocket::Bind fail: %d", error); + } + // In case of failure, there is nothing else to do but leave. + // Construction will fail. + if ( KErrNone != error ) + { + LOGSH( iHandle, "CUpnpTcpServer ListenL - Bind or listen failed."); + + User::Leave( error ); + } + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::BindL +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::BindL( const TInt aPort) +{ + LOGS1H( iHandle , "CUpnpTcpServer BindL to fixed port %d" , aPort); + iServerPort = aPort; + + TInetAddr addr( iServerPort ); + TInt error( iServerSocket.Bind( addr ) ); + if( error == KErrNone ) + { + User::LeaveIfError( StartToListenL() ); + } + else + { + LOGSH( iHandle, "CUpnpTcpServer ListenL - open, Bind or listen failed"); + iServerSocket.Close(); + User::Leave( error ) ; + } + +} + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::StartToListenL +// Start to listen a socket. +// ----------------------------------------------------------------------------- +// +TInt CUpnpTcpServer::StartToListenL() + { + TInt error = iServerSocket.Listen( UpnpSocket::KMaxConnectionsInQueue ); + if ( KErrNone == error ) + { + // Both bind and listen ok, accept connection if OK + LOGS1H( iHandle, "CUpnpTcpServer::StartToListenL - at port %i", ServerPort() ); + + AcceptConnectionL(); + } + // Listen failed, close socket and log problem + else + { + iServerSocket.Close(); + LOGS1H( iHandle, "CUpnpTcpServer StartToListenL - fail: %d" , error); + } + return error; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::AcceptConnection +// Open connection +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::AcceptConnectionL() + { + LOG_FUNC_NAME; + TInt error = 0; + + if( iSessionList.Count() >= KMaxConnectionCount ) + { + LOGSH( iHandle, "CUpnpTcpServer::AcceptConnectionL - HTTP *** SessionList full"); + + StartRetryTimer(); + return; + } + + error = iClientSocket.Open( *iSocketServ ); + if ( error < KErrNone ) + { + LOGS1H( iHandle, "CUpnpTcpServer::AcceptConnectionL - error to open client socket,%i", error); + + iClientSocket.Close(); + + StartRetryTimer(); + } + else + { + iServerSocket.Accept( iClientSocket, iStatus ); + SetActive(); + iState = EAccepting; + LOGSH( iHandle, "CUpnpTcpServer::AcceptConnection - State = EAccepting "); + } + + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::DeleteSession +// Delete sessions. +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::DeleteSession( CUpnpTcpSession* aSession ) + { + LOG_FUNC_NAME; + TInt pos = iSessionList.Find( aSession ); + + if( pos != KErrNotFound ) + { + iSessionList.Remove( pos ); + iSessionList.Compress(); + delete aSession; + aSession = NULL; + } + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::RunL +// State machine +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::RunL() + { + switch ( iState ) + { + case EAccepting: + { + if( iStatus == KErrNone ) + { + iClientSocket.SetOpt( KSoTcpNoDelay, KSolInetTcp, 1 ); + + #ifdef RD_UPNP_REMOTE_ACCESS +/************** IPFIltering ********************/ + TInetAddr tempAddr; + iClientSocket.RemoteName( tempAddr ); + tempAddr.ConvertToV4(); + + if( iIPFilteringManager && !iIPFilteringManager->IsAllowed( tempAddr ) ) + { + iClientSocket.Close(); //mozliwe ze konieczny bedzie jeszcze + //Shutdown - EImmediate; default jest ENormal + AcceptConnectionL() ; + break; + } + + #if _DEBUG + TBuf<20> addrBuf; + tempAddr.Output( addrBuf ); + #endif +/******************* IPFiltering END *******************/ + #endif + + CUpnpTcpSession* sess = ConnectionAcceptedL( iClientSocket ); + iSessionList.Append( sess ); + + } + else + { + iClientSocket.Close(); + } + + AcceptConnectionL(); + + break; + } + + default: + break; + } + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::RunError +// RunError is called when RunL leaves. +// ----------------------------------------------------------------------------- +// +TInt CUpnpTcpServer::RunError( TInt aError ) + { + LOGS1H( iHandle, "CUpnpTcpServer::RunError - Error: %d", aError); + StartRetryTimer(); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::StopTcpServerL +// Stop session and reset the lists +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::StopTcpServerL() + { + LOG_FUNC_NAME; + for( TInt i(0) ; i < iSessionList.Count() ; i++ ) + { + iSessionList[i]->NotifyTimeoutL(); + } + PrepareToCloseSockets(); + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::PrepareToCloseSockets +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::PrepareToCloseSockets() + { + iSessionList.ResetAndDestroy(); + if ( IsActive() ) + { + Cancel(); + } + else + { + CancelRetryTimer(); + CloseSockets(); + } + delete iConnectionManagerProxy; + iConnectionManagerProxy = NULL; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::DoCancel +// Cancel outstanding operations and close the connection +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::DoCancel() + { + CancelRetryTimer(); + + iServerSocket.CancelAll(); + + CloseSockets(); + + LOGSH( iHandle, "CUpnpTcpServer::DoCancel - iState = ENotListening" ); + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::CloseSockets +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::CloseSockets() + { + iServerSocket.Close(); + + iClientSocket.Close(); + + iState = ENotListening; + LOGSH( iHandle, "CUpnpTcpServer::CloseSockets - iState = ENotListening" ); + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::ServerAddress +// Return server address. +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::ServerAddress( TInetAddr& aAddr ) + { + LOG_FUNC_NAME; + aAddr = iServerAddress; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::SetServerAddress +// Set new server address. +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::SetServerAddress( const TInetAddr& aAddr ) + { + iServerAddress = aAddr; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::ServerPort +// Return server port number, +// ----------------------------------------------------------------------------- +// +TUint CUpnpTcpServer::ServerPort() + { + return iServerPort; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::HWAddressL +// Return hardware address. +// ----------------------------------------------------------------------------- +// +TSockAddr* CUpnpTcpServer::HWAddressL() + { + LOG_FUNC_NAME; + // Fetch IP address + ServerAddress(iServerAddress); + + // return value is TSockAddr* because it won't work + // correctly always with TSockAddr + TPckgBuf item; + + RSocket sock; + + TInt result = sock.Open( *iSocketServ, KAfInet, KSockStream, + KProtocolInetTcp, iConnectionManagerProxy->ConnectionL() ); + if ( KErrNone == result ) + { + result = sock.GetOpt( KSoInetNextInterface, KSolInetIfCtrl, item ); + + // checking all interfaces. If interface has same IP address as socket, is + // the current active interface. In this case we get that interface's + // hardware address. + while ( result == KErrNone ) + { + TSoInetInterfaceInfo& ifInfo = item(); + TInetAddr ifAddr = ifInfo.iAddress; + ifAddr.ConvertToV4(); + ifAddr.SetPort( iServerAddress.Port() ); + if ( ifAddr == iServerAddress ) + { + sock.Close(); + TSockAddr tempAddr = ifInfo.iHwAddr; + return new (ELeave) TSockAddr( tempAddr ); + } + result = sock.GetOpt( KSoInetNextInterface, KSolInetIfCtrl, item ); + } + } + + sock.Close(); + return new (ELeave) TSockAddr(); + } + + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::NewPortNumberL +// +// ----------------------------------------------------------------------------- +// +TInt CUpnpTcpServer::NewPortNumberL() + { + LOG_FUNC_NAME; + TInt id( 0 ); + + //get random port + TTime now; + now.HomeTime(); + TInt64 randSeed = now.Int64(); + id = Math::Rand( randSeed ) % (KInetMaxAutoPort-KInetMinAutoPort+1) + KInetMinAutoPort; + return id; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::TimerEventL +// Function is callback from iRetrySocketTimer. This timer is used +// to retry to open new server socket. +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::TimerEventL( CUpnpNotifyTimer* /*aTimer*/) + { + // Timer has expired, now trying to bind server socket again. + LOGSH( iHandle, "CUpnpTcpServer::TimerEventL - retrying to open new socket server"); + AcceptConnectionL(); + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::StartRetryTimer +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::StartRetryTimer() + { + CancelRetryTimer(); + iRetrySocketTimer->After(KRetryTime); + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::SetFileWriteBufferSize +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::SetFileWriteBufferSize(TInt aSize) + { + iFileWriteBufferSize = aSize; + } + + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::FileWriteBufferSize +// ----------------------------------------------------------------------------- +// +TInt CUpnpTcpServer::FileWriteBufferSize() + { + return iFileWriteBufferSize; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::SetFileReadBufferSize +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::SetFileReadBufferSize(TInt aSize) + { + iFileReadBufferSize = aSize; + } + + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::FileReadBufferSize +// ----------------------------------------------------------------------------- +// +TInt CUpnpTcpServer::FileReadBufferSize() + { + return iFileReadBufferSize; + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::GetServerAddress +// Return server address. +// ----------------------------------------------------------------------------- +// +TBool CUpnpTcpServer::GetServerAddress( TInetAddr& aAddr ) + { + aAddr = iServerAddress; + return (iServerAddress.Address() != 0); + } + +// ----------------------------------------------------------------------------- +// CUpnpTcpServer::CancelRetryTimer +// ----------------------------------------------------------------------------- +// +void CUpnpTcpServer::CancelRetryTimer() + { + if ( iRetrySocketTimer ) + { + iRetrySocketTimer->Cancel(); + } + } + +// End of File