# HG changeset patch # User Dremov Kirill (Nokia-D-MSW/Tampere) # Date 1276067817 -10800 # Node ID 26ce6fb6aee268f54cbe7593e67ecbacbf150d30 # Parent f21293830889c53a45e4e9449f3cd79a7237f84f Revision: 201019 Kit: 2010123 diff -r f21293830889 -r 26ce6fb6aee2 applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.cpp --- a/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.cpp Tue May 25 13:17:20 2010 +0300 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.cpp Wed Jun 09 10:16:57 2010 +0300 @@ -43,6 +43,21 @@ return self; } +CSocket* CSocket::New(MCommsInfoProvider& aCommsInfoProvider, TSocketType aSocketType) + { + CSocket* self = new CSocket(aCommsInfoProvider); + if(self) + { + TInt error = self->Construct(aSocketType); + if(error != KErrNone) + { + delete self; + self = NULL; + } + } + return self; + } + CSocket::~CSocket() /** Destructor. @@ -70,54 +85,62 @@ @param aSocketType The type of the socket. */ { - switch( aSocketType ) - { - case EProtocolSocket: - { - if ( iCommsInfoProvider.HasConnection() ) - { - // Open a protocol socket with a RConnection - User::LeaveIfError(iSocket.Open( - iCommsInfoProvider.SocketServer(), - iCommsInfoProvider.ProtocolDescription().iAddrFamily, - iCommsInfoProvider.ProtocolDescription().iSockType, - iCommsInfoProvider.ProtocolDescription().iProtocol, - iCommsInfoProvider.Connection() - )); - } - else - { - // Open a protocol socket without a RConnection, we don't need one ( Loopback address ) - User::LeaveIfError(iSocket.Open( - iCommsInfoProvider.SocketServer(), - iCommsInfoProvider.ProtocolDescription().iAddrFamily, - iCommsInfoProvider.ProtocolDescription().iSockType, - iCommsInfoProvider.ProtocolDescription().iProtocol - )); - } - } break; - case EBlankSocket: - { - // Open a blank socket - User::LeaveIfError(iSocket.Open(iCommsInfoProvider.SocketServer())); - } break; - default: - User::Invariant(); - } - TInt id = iCommsInfoProvider.SessionId(); - if(id>=0) - { - // set socket option - iSocket.SetOpt(KSOHttpSessionId, KSOLHttpSessionInfo, id); - iSocket.SetOpt(KSoTcpKeepAlive, KSolInetTcp, KTcpTriggeredKeepAlive); - } - if(aSocketType != EBlankSocket) - { - iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1); // Disable the nagle. - iSocket.SetOpt(KSORecvBuf, KSOLSocket, KSocketRecvBufSize); // Set the socket recv buf to be 16K - } + User::LeaveIfError(Construct(aSocketType)); } +TInt CSocket::Construct(TSocketType aSocketType) + { + TInt error = KErrNone; + switch( aSocketType ) + { + case EProtocolSocket: + { + if ( iCommsInfoProvider.HasConnection() ) + { + // Open a protocol socket with a RConnection + error = iSocket.Open(iCommsInfoProvider.SocketServer(), + iCommsInfoProvider.ProtocolDescription().iAddrFamily, + iCommsInfoProvider.ProtocolDescription().iSockType, + iCommsInfoProvider.ProtocolDescription().iProtocol, + iCommsInfoProvider.Connection() + ); + } + else + { + // Open a protocol socket without a RConnection, we don't need one ( Loopback address ) + error = iSocket.Open(iCommsInfoProvider.SocketServer(), + iCommsInfoProvider.ProtocolDescription().iAddrFamily, + iCommsInfoProvider.ProtocolDescription().iSockType, + iCommsInfoProvider.ProtocolDescription().iProtocol + ); + } + } break; + case EBlankSocket: + { + // Open a blank socket + error = iSocket.Open(iCommsInfoProvider.SocketServer()); + } break; + default: + User::Invariant(); + } + if(error == KErrNone) + { + TInt id = iCommsInfoProvider.SessionId(); + if(id>=0) + { + // set socket option + iSocket.SetOpt(KSOHttpSessionId, KSOLHttpSessionInfo, id); + iSocket.SetOpt(KSoTcpKeepAlive, KSolInetTcp, KTcpTriggeredKeepAlive); + } + if(aSocketType != EBlankSocket) + { + iSocket.SetOpt(KSoTcpNoDelay,KSolInetTcp,1); // Disable the nagle. + iSocket.SetOpt(KSORecvBuf, KSOLSocket, KSocketRecvBufSize); // Set the socket recv buf to be 16K + } + } + return error; + } + TInt CSocket::Listen(TUint aQSize, TUint16 aPort) /** Start the listen service. The socket is bound to the local port specified by diff -r f21293830889 -r 26ce6fb6aee2 applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.h --- a/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.h Tue May 25 13:17:20 2010 +0300 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocket.h Wed Jun 09 10:16:57 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2003-2010 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" @@ -51,7 +51,9 @@ public: // methods static CSocket* NewL(MCommsInfoProvider& aCommsInfoProvider, TSocketType aSocketType); - + + static CSocket* New(MCommsInfoProvider& aCommsInfoProvider, TSocketType aSocketType); + virtual ~CSocket(); TInt Listen(TUint aQSize, TUint16 aPort); @@ -97,7 +99,8 @@ CSocket(MCommsInfoProvider& aCommsInfoProvider); void ConstructL(TSocketType aSocketType); - + + TInt Construct(TSocketType aSocketType); private: /** The comms info provider diff -r f21293830889 -r 26ce6fb6aee2 applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketconnector.cpp --- a/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketconnector.cpp Tue May 25 13:17:20 2010 +0300 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketconnector.cpp Wed Jun 09 10:16:57 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2003-2010 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" @@ -55,7 +55,6 @@ // Cleanup... delete iHost; delete iConnectingSocket; - iHostResolver.Close(); // __FLOG_CLOSE; } @@ -104,20 +103,33 @@ iHost = HBufC::NewL(aRemoteHost.Length()); iHost->Des().Copy(aRemoteHost); iPort = aRemotePort; - + + TInt error = KErrNone; // Move to the PendingDNSLookup state and self complete. if(aRemoteAddress == NULL) { + RDebug::Printf("RemoteAddress is NULL so doing a DNS lookup"); + iState = EPendingDNSLookup; // Address is unknown / DNS lookup is needed - iState = EPendingDNSLookup; + error = DoPendingDNSLookup(); } else { + RDebug::Printf("Remote address is known so doing a direct connect"); + iState = EConnecting; // Address is know. No lookup is needed. Just go and connect. iHostDnsEntry().iAddr = *aRemoteAddress; - iState = EConnecting; + error = DoConnect(); } - CompleteSelf(); + + if(error != KErrNone) + { + iState = EPendingDNSLookup; + // Error the AO and handle the error in the normal path. + TRequestStatus* pStat = &iStatus; + User::RequestComplete(pStat, error); + SetActive(); + } } void CSocketConnector::CompleteSelf() @@ -193,80 +205,11 @@ { case EPendingDNSLookup: { -#if defined (_DEBUG) && defined (_LOGGING) - TBuf8 host; - host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters - - __FLOG_1(_T8("Doing DNS lookup -> searching for host %S"), &host); -#endif - - __OOM_LEAVE_TEST - - if ( iCommsInfoProvider.HasConnection() ) - { - // Open the host resolver session with the preffered connection - User::LeaveIfError(iHostResolver.Open( - iCommsInfoProvider.SocketServer(), - iCommsInfoProvider.ProtocolDescription().iAddrFamily, - KProtocolInetUdp, - iCommsInfoProvider.Connection() - )); - } - else - { - // Open the host resolver session with no connection - User::LeaveIfError(iHostResolver.Open( - iCommsInfoProvider.SocketServer(), - iCommsInfoProvider.ProtocolDescription().iAddrFamily, - KProtocolInetUdp - )); - } - - // Start the DNS lookup for the remote host name. - iHostResolver.GetByName(*iHost, iHostDnsEntry, iStatus); - - // Move to the Connecting state and go active - iState = EConnecting; - SetActive(); + User::LeaveIfError(DoPendingDNSLookup()); } break; case EConnecting: { - __OOM_LEAVE_TEST - - // DNS lookup successful - form the internet address object - iAddress = TInetAddr(iHostDnsEntry().iAddr); - iAddress.SetPort(iPort); - -#if defined (_DEBUG) && defined (_LOGGING) - TBuf8 host; - host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters - - TBuf ip16bit; - iAddress.Output(ip16bit); - - TBuf8 ip; - ip.Copy(ip16bit); - - __FLOG_2(_T8("DNS lookup complete -> host %S has IP address %S"), &host, &ip); -#endif - - // Start a default RConnection, if one is not started and not local loopback address - if ( !iCommsInfoProvider.HasConnection() && !iAddress.IsLoopback() ) - { - iCommsInfoProvider.StartDefaultCommsConnectionL (); - } - - // Create the connecting socket - iConnectingSocket = CSocket::NewL(iCommsInfoProvider, CSocket::EProtocolSocket); - - // Start connecting to the remote client - iConnectingSocket->Connect(iAddress, iStatus); - - __FLOG_2(_T8("Connecting -> to host %S on IP address %S"), &host, &ip); - - // Move to the Connected state and go active - iState = EConnected; - SetActive(); + User::LeaveIfError(DoConnect()); } break; case EConnected: { @@ -334,6 +277,7 @@ { // DNS lookup is pending - cancel iHostResolver.Cancel(); + iCommsInfoProvider.AddToHostResolverCache(iHostResolver); // Add to the cache. } break; case EConnected: { @@ -431,3 +375,103 @@ return error; } + +TInt CSocketConnector::DoPendingDNSLookup() + { +#if defined (_DEBUG) && defined (_LOGGING) + TBuf8 host; + host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters + + __FLOG_1(_T8("Doing DNS lookup -> searching for host %S"), &host); +#endif + TInt error = KErrNone; + + iCommsInfoProvider.HostResolverFromCache(iHostResolver); // Get the RHostResolver from the cache + if(iHostResolver.SubSessionHandle() <= 0) + { + RDebug::Printf("No host resolver. Open a new one..."); + if ( iCommsInfoProvider.HasConnection() ) + { + // Open the host resolver session with the preffered connection + error = iHostResolver.Open(iCommsInfoProvider.SocketServer(), + iCommsInfoProvider.ProtocolDescription().iAddrFamily, + KProtocolInetUdp, + iCommsInfoProvider.Connection()); + } + else + { + // Open the host resolver session with no connection + error = iHostResolver.Open(iCommsInfoProvider.SocketServer(), + iCommsInfoProvider.ProtocolDescription().iAddrFamily, + KProtocolInetUdp); + } + } + + if(error != KErrNone) + { + return error; + } + + // Start the DNS lookup for the remote host name. + iHostResolver.GetByName(*iHost, iHostDnsEntry, iStatus); + + // Move to the Connecting state and go active + iState = EConnecting; + SetActive(); + return error; + } + +TInt CSocketConnector::DoConnect() + { + // DNS lookup successful - form the internet address object + iAddress = TInetAddr(iHostDnsEntry().iAddr); + iAddress.SetPort(iPort); + + // Add the RHostResolver to the cache. + if(iHostResolver.SubSessionHandle() > 0) + { + iCommsInfoProvider.AddToHostResolverCache(iHostResolver); + } + +#if defined (_DEBUG) && defined (_LOGGING) + TBuf8 host; + host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters + + TBuf ip16bit; + iAddress.Output(ip16bit); + + TBuf8 ip; + ip.Copy(ip16bit); + + __FLOG_2(_T8("DNS lookup complete -> host %S has IP address %S"), &host, &ip); +#endif + + // Start a default RConnection, if one is not started and not local loopback address + if ( !iCommsInfoProvider.HasConnection() && !iAddress.IsLoopback() ) + { + // it is ok to TRAP here as the method will be called only once. + TRAPD(error, iCommsInfoProvider.StartDefaultCommsConnectionL ()); + if(error != KErrNone) + { + return error; + } + } + + // Create the connecting socket + iConnectingSocket = CSocket::New(iCommsInfoProvider, CSocket::EProtocolSocket); + if(!iConnectingSocket) + { + return KErrNoMemory; + } + + // Start connecting to the remote client + iConnectingSocket->Connect(iAddress, iStatus); + SetActive(); + __FLOG_2(_T8("Connecting -> to host %S on IP address %S"), &host, &ip); + + // Move to the Connected state and go active + iState = EConnected; + return KErrNone; + } + + diff -r f21293830889 -r 26ce6fb6aee2 applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketconnector.h --- a/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketconnector.h Tue May 25 13:17:20 2010 +0300 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketconnector.h Wed Jun 09 10:16:57 2010 +0300 @@ -101,7 +101,9 @@ void CompleteSelf(); void Suicide(); - + + TInt DoPendingDNSLookup(); + TInt DoConnect(); private: // enums /** diff -r f21293830889 -r 26ce6fb6aee2 applayerpluginsandutils/httptransportplugins/httptransporthandler/ctcptransportlayer.cpp --- a/applayerpluginsandutils/httptransportplugins/httptransporthandler/ctcptransportlayer.cpp Tue May 25 13:17:20 2010 +0300 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/ctcptransportlayer.cpp Wed Jun 09 10:16:57 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2001-2010 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" @@ -25,6 +25,9 @@ _LIT(KTcpProtName, "tcp"); +const TInt KMaxHostResolverCacheCount = 8; // 8 Should be sufficient here as we can have maximum of 8 connections + // at anytime to the host. And it is not neccassarly mean that 8 host resolvers + // will be operating simulataneously. CTcpTransportLayer* CTcpTransportLayer::NewL(TAny* aTransportConstructionParams) /** The factory constructor. @@ -54,7 +57,12 @@ // Delete the socket controllers iControllerStore.ResetAndDestroy(); - + + + // Empty and close the host resolver cache. + EmptyHostResolverCache(); + iHostResolverCache.Close(); + // Close the socket server session if owned if( iOwnsConnection ) { @@ -73,7 +81,7 @@ } CTcpTransportLayer::CTcpTransportLayer(MConnectionPrefsProvider& aTransLayerObserver) -: CHttpTransportLayer(), iConnectionPrefsProvider(aTransLayerObserver) +: CHttpTransportLayer(), iConnectionPrefsProvider(aTransLayerObserver), iHostResolverCache(KMaxHostResolverCacheCount) /** Constructor. */ @@ -191,6 +199,7 @@ // Socket and controller will be deleted by itself } iConnectorStore.ResetAndDestroy(); + EmptyHostResolverCacheIfNeeded(); } } } @@ -332,6 +341,9 @@ // Remove the socket connector from the store and compress the store. iConnectorStore.Remove(index); iConnectorStore.Compress(); + + // Empty the host resolver cache if needed + EmptyHostResolverCacheIfNeeded(); } /* @@ -355,6 +367,9 @@ // Remove the socket controller from the store and compress the store. iControllerStore.Remove(index); iControllerStore.Compress(); + + // Empty the host resolver cache if needed + EmptyHostResolverCacheIfNeeded(); } /* @@ -474,4 +489,48 @@ return ( iConnection != NULL ); } +void CTcpTransportLayer::HostResolverFromCache(RHostResolver& aResolver) + { + TInt count = iHostResolverCache.Count(); + if(count > 0) + { + RDebug::Printf("Returning the host resolver from cache..."); + // Returns the last host resolver that is added + aResolver = iHostResolverCache[count - 1]; + iHostResolverCache.Remove(count - 1); // Remove from the cache. + } + } +void CTcpTransportLayer::AddToHostResolverCache(RHostResolver& aResolver) + { + if(iHostResolverCache.Append(aResolver) != KErrNone) + { + aResolver.Close(); + } + } + +void CTcpTransportLayer::EmptyHostResolverCacheIfNeeded() + { + // Remove the host resolver if + // 1/ if the Connector store is empty and + // 2/ if the socket controller is empty + // This is important to get the mobility and one click connectivity cases working + // Otherwise the inconsistent behaviour will result as the RConnection & RSocketServ can be handled + // entirely outside of the HTTP stack, ie; from the application + if(iConnectorStore.Count() == 0 && iControllerStore.Count() == 0) + { + EmptyHostResolverCache(); + } + } + +void CTcpTransportLayer::EmptyHostResolverCache() + { + TInt count = iHostResolverCache.Count(); + while(count > 0) + { + // Close the RHostResolver and remove from the array + iHostResolverCache[count - 1].Close(); + iHostResolverCache.Remove(--count); + } + iHostResolverCache.Compress(); + } diff -r f21293830889 -r 26ce6fb6aee2 applayerpluginsandutils/httptransportplugins/httptransporthandler/ctcptransportlayer.h --- a/applayerpluginsandutils/httptransportplugins/httptransporthandler/ctcptransportlayer.h Tue May 25 13:17:20 2010 +0300 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/ctcptransportlayer.h Wed Jun 09 10:16:57 2010 +0300 @@ -103,7 +103,11 @@ virtual TBool HasConnection(); - void StartDefaultCommsConnectionL (); + virtual void StartDefaultCommsConnectionL (); + + virtual void HostResolverFromCache(RHostResolver& aResolver); + + virtual void AddToHostResolverCache(RHostResolver& aResolver); private: // methods @@ -119,6 +123,10 @@ inline MCommsInfoProvider& CommsInfoProvider(); + void EmptyHostResolverCacheIfNeeded(); + + void EmptyHostResolverCache(); + private: // attributes /** The connection preferences provider @@ -157,6 +165,8 @@ */ RPointerArray iControllerStore; + RArray iHostResolverCache; + TBool iPriority; /** Logger handle diff -r f21293830889 -r 26ce6fb6aee2 applayerpluginsandutils/httptransportplugins/httptransporthandler/mcommsinfoprovider.h --- a/applayerpluginsandutils/httptransportplugins/httptransporthandler/mcommsinfoprovider.h Tue May 25 13:17:20 2010 +0300 +++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/mcommsinfoprovider.h Wed Jun 09 10:16:57 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2003-2010 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" @@ -78,6 +78,17 @@ Starts a default RConnection */ virtual void StartDefaultCommsConnectionL () =0; + + /** + Returns the RHostResolver if available in cache. + */ + virtual void HostResolverFromCache(RHostResolver& aResolver) =0; + + /** + Add the RHostResolver to cache. If the adding fails then the RHostResolver will be + closed + */ + virtual void AddToHostResolverCache(RHostResolver& aResolver) =0; }; #endif // __MCOMMSINFOPROVIDER_H__ diff -r f21293830889 -r 26ce6fb6aee2 applayerprotocols/httptransportfw/core/CTransaction.cpp --- a/applayerprotocols/httptransportfw/core/CTransaction.cpp Tue May 25 13:17:20 2010 +0300 +++ b/applayerprotocols/httptransportfw/core/CTransaction.cpp Wed Jun 09 10:16:57 2010 +0300 @@ -42,6 +42,7 @@ Cancel(); // And send the cancel event SynchronousSendEvent(THTTPEvent::ECancel, THTTPEvent::EOutgoing, aStart); + if (iStatus != EInFilter && iStatus != ECancelled) iStatus = EPassive; else diff -r f21293830889 -r 26ce6fb6aee2 applayerprotocols/httptransportfw/core/TFilterConfigurationIter.cpp --- a/applayerprotocols/httptransportfw/core/TFilterConfigurationIter.cpp Tue May 25 13:17:20 2010 +0300 +++ b/applayerprotocols/httptransportfw/core/TFilterConfigurationIter.cpp Wed Jun 09 10:16:57 2010 +0300 @@ -76,10 +76,10 @@ } else { - ++iCurrentFilterIndex; // If the next filter is a mandatory filter then move on to the next filter if( iFilterInfoList[iCurrentFilterIndex]->iCategory == TSessionFilterInfo::EMandatory ) return Next(); + ++iCurrentFilterIndex; } return KErrNone;