--- 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
--- 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
--- 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<KHostNameSize> 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<KHostNameSize> host;
- host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters
-
- TBuf<KIpv6MaxAddrSize> ip16bit;
- iAddress.Output(ip16bit);
-
- TBuf8<KIpv6MaxAddrSize> 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<KHostNameSize> 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<KHostNameSize> host;
+ host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters
+
+ TBuf<KIpv6MaxAddrSize> ip16bit;
+ iAddress.Output(ip16bit);
+
+ TBuf8<KIpv6MaxAddrSize> 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;
+ }
+
+
--- 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
/**
--- 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();
+ }
--- 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<CSocketController> iControllerStore;
+ RArray<RHostResolver> iHostResolverCache;
+
TBool iPriority;
/** Logger handle
--- 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__
--- 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
--- 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;