--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerpluginsandutils/httptransportplugins/httptransporthandler/csocketconnector.cpp Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,433 @@
+// Copyright (c) 2003-2009 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:
+//
+
+#include "csocketconnector.h"
+
+#include "csocket.h"
+#include "msocketconnectobserver.h"
+#include "msocketconnectorstore.h"
+#include "msocketcontrollerfactory.h"
+#include "mcommsinfoprovider.h"
+#include "csocketcontroller.h"
+#include "httptransporthandlercommon.h"
+#include "thttptrlayerpanic.h"
+
+#if defined (_DEBUG) && defined (_LOGGING)
+const TInt KHostNameSize = 126;
+#endif
+
+CSocketConnector* CSocketConnector::NewL(
+ MSocketConnectorStore& aStore,
+ MSocketControllerFactory& aSocketControllerFactory,
+ MCommsInfoProvider& aCommsInfoProvider, TBool aPriority
+ )
+/**
+ The factory constructor.
+ @param aStore The socket connector store.
+ @param aSocketControllerFactory The socket controller factory.
+ @param aCommsInfoProvider The comms info provider.
+ @return A pointer to a fully constructed object.
+*/
+ {
+ return new (ELeave) CSocketConnector(aStore, aSocketControllerFactory, aCommsInfoProvider,aPriority);
+ }
+
+CSocketConnector::~CSocketConnector()
+/**
+ Destructor.
+*/
+ {
+ // Cancel any outstanding requests
+ Cancel();
+
+ // Cleanup...
+ delete iHost;
+ delete iConnectingSocket;
+ iHostResolver.Close();
+
+// __FLOG_CLOSE;
+ }
+
+CSocketConnector::CSocketConnector(
+ MSocketConnectorStore& aStore,
+ MSocketControllerFactory& aSocketControllerFactory,
+ MCommsInfoProvider& aCommsInfoProvider,
+ TBool aPriority
+ )
+: CActive(aPriority ? CActive::EPriorityHigh : CActive::EPriorityStandard), iStore(aStore),
+ iSocketControllerFactory(aSocketControllerFactory),
+ iCommsInfoProvider(aCommsInfoProvider)
+/**
+ Constructor.
+ @param aStore The socket connector store.
+ @param aSocketControllerFactory The socket controller factory.
+ @param aCommsInfoProvider The comms info provider.
+*/ {
+ if(aPriority)
+ {
+ CActive::SetPriority(CActive::EPriorityHigh);
+ }
+
+ CActiveScheduler::Add(this);
+
+// __FLOG_OPEN("http", "httptransporthandler.txt");
+ }
+
+void CSocketConnector::ConnectL(MSocketConnectObserver& aObserver, const TDesC8& aRemoteHost, TUint16 aRemotePort, TInetAddr* aRemoteAddress)
+/**
+ Start connection to specified remote host. The socket connector starts
+ connecting to the specified remote host on the specified port.
+ @param aRemoteHost The host name/IP address of the remote host
+ @param aRemotePort The port number of the remote host
+ @pre The socket connector is in the Idle state.
+ @post The socket connector is not in the Idle state.
+*/
+ {
+ __ASSERT_DEBUG( iState == EIdle, THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadSocketConnectorState) );
+
+ // Set the observer
+ iObserver = &aObserver;
+
+ // Copy the remote host IP address and port
+ iHost = HBufC::NewL(aRemoteHost.Length());
+ iHost->Des().Copy(aRemoteHost);
+ iPort = aRemotePort;
+
+ // Move to the PendingDNSLookup state and self complete.
+ if(aRemoteAddress == NULL)
+ {
+ // Address is unknown / DNS lookup is needed
+ iState = EPendingDNSLookup;
+ }
+ else
+ {
+ // Address is know. No lookup is needed. Just go and connect.
+ iHostDnsEntry().iAddr = *aRemoteAddress;
+ iState = EConnecting;
+ }
+ CompleteSelf();
+ }
+
+void CSocketConnector::CompleteSelf()
+/**
+ Requests that the socket connector complete itself. This will caused the
+ RunL() to be called by the scheduler at the next opportunity.
+ @pre The socket connector object is not active.
+ @post The socket connector object is active and the request has been
+ completed.
+*/
+ {
+ TRequestStatus* pStat = &iStatus;
+ User::RequestComplete(pStat, KErrNone);
+ SetActive();
+ }
+
+void CSocketConnector::Suicide()
+/**
+ The socket connector is finished, it needs to remove itself from the store
+ and self-destruct.
+*/
+ {
+ // Inform store that connection is complete and then suicide.
+ iStore.ConnectionCompleted(*this);
+ delete this;
+ }
+
+/*
+ * Methods from MSocketConnector
+ */
+
+void CSocketConnector::StopConnect()
+/**
+ @see MSocketConnector
+*/
+ {
+ // Cancel any outstanding requests.
+ Cancel();
+
+#if defined (_DEBUG) && defined (_LOGGING)
+ TBuf8<KHostNameSize> host;
+ host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters
+
+ __FLOG_0(_T8("!! Stopping connection"));
+ __FLOG_1(_T8("-> connect to host %S stopped"), &host);
+#endif
+
+ Suicide();
+ }
+
+void CSocketConnector::MSocketConnector_Reserved()
+/**
+ @see MSocketConnector
+*/
+ {
+ User::Invariant();
+ }
+
+/*
+ * Methods from CActive
+ */
+
+void CSocketConnector::RunL()
+/**
+ The request servicing function. Behaviour depends on the state of the socket
+ connector.
+*/
+ {
+ // Leave if there has been an error
+ User::LeaveIfError(iStatus.Int());
+
+ switch( iState )
+ {
+ 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();
+ } 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();
+ } break;
+ case EConnected:
+ {
+ __OOM_LEAVE_TEST
+
+#if defined (_DEBUG) && defined (_LOGGING)
+ TBuf8<KHostNameSize> host;
+ host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters
+
+ TInetAddr addr;
+ iConnectingSocket->RemoteName(addr);
+
+ TBuf<KIpv6MaxAddrSize> ip16bit;
+ addr.Output(ip16bit);
+
+ TBuf8<KIpv6MaxAddrSize> ip;
+ ip.Copy(ip16bit);
+
+ TInetAddr local;
+ iConnectingSocket->LocalName(local);
+
+ __FLOG_1(_T8("!! Connection with host %S established"), &host);
+ __FLOG_3(_T8("-> on local port %d with %S, remote port %d"), local.Port(), &ip, addr.Port());
+#endif
+
+ // A connection has been made with the remote client - lose ownership of
+ // the connecting socket.
+ CSocket* connectedSocket = iConnectingSocket;
+ iConnectingSocket = NULL;
+
+ // Create a socket controller object to own the connected socket.
+ CSocketController* socketController = iSocketControllerFactory.CreateSocketControllerLC(connectedSocket, *iHost, iPort, iAddress);
+
+ // Inform the socket connect observer that a TCP connection is established -
+ // pass back the input and output stream objects.
+ iObserver->ConnectionMadeL(socketController->InputStream(), socketController->OutputStream());
+
+ // Remove socket controller from cleanup stack - transferring ownership
+ // to the store.
+ CleanupStack::Pop(socketController);
+
+ // Add the socket controller in the store - ownership is transferred to
+ // the store.
+ iSocketControllerFactory.AddToStoreL(socketController);
+
+ // Socket connector is finished - suicide.
+ Suicide();
+ } break;
+ case EIdle:
+ default:
+ THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadSocketConnectorState);
+ break;
+ }
+ }
+
+void CSocketConnector::DoCancel()
+/**
+ The asynchronous request cancel.
+*/
+ {
+ // Check state
+ switch( iState )
+ {
+ case EConnecting:
+ {
+ // DNS lookup is pending - cancel
+ iHostResolver.Cancel();
+ } break;
+ case EConnected:
+ {
+ if( iConnectingSocket )
+ {
+ // Connection is pending - cancel and delete the socket
+ iConnectingSocket->CancelConnect();
+ delete iConnectingSocket;
+ iConnectingSocket = NULL;
+ }
+ } break;
+ case EIdle:
+ case EPendingDNSLookup:
+ default:
+ // Do nothing...
+ break;
+ }
+ }
+
+TInt CSocketConnector::RunError(TInt aError)
+/**
+ The error handler for when RunL() leaves. This function does any necessary
+ cleanup. The socket connector is then set to suicide.
+ @param aError The leave code.
+ @return A value of KErrNone.if the error has been handled, any other
+ value if it has not been handled.
+ @post The socket connector is in the Suicide state.
+*/
+ {
+#if defined (_DEBUG) && defined (_LOGGING)
+ TBuf8<KHostNameSize> host;
+ host.Copy((*iHost).Left(KHostNameSize)); //just get the KHostNameSize characters
+
+ __FLOG_1(_T8("!! Error : %d"), aError);
+ __FLOG_1(_T8("-> connect to host %S failed"), &host);
+#endif
+
+ TInt errorToPropagate = aError;
+ TInt error = KErrNone;
+
+ switch( iState )
+ {
+ case EPendingDNSLookup:
+ case EConnecting:
+ {
+ // In EReadyForDNS or EReadyToConnect states, KErrNotReady may be
+ // returned by the comms call that require a connection. The RConnection
+ // that is passed in MUST be started or this error will occur. If we own
+ // the RConnection we should start the RConnection again, else if our
+ // client own the RConnection, we just propagate the Comms error.
+ if( iCommsInfoProvider.HasConnection() && iCommsInfoProvider.OwnsConnection() && aError == KErrNotReady )
+ {
+ __FLOG_0(_T8("-> re-starting comms interface..."));
+
+ // We own the RConnection and the error is KErrNotReady
+ errorToPropagate = iCommsInfoProvider.Connection().Start();
+
+ if( errorToPropagate == KErrNone )
+ {
+ __FLOG_0(_T8("!! Re-started comms interface"));
+ __FLOG_1(_T8("-> try connecting to host %S again"), &host);
+
+ // RConnection started successfully, try to connect again
+ CompleteSelf();
+ return KErrNone;
+ }
+#if defined (_DEBUG) && defined (_LOGGING)
+ else
+ {
+ __FLOG_1(_T8("!! Error : %d"), errorToPropagate);
+ __FLOG_0(_T8("-> failed to re-start comms interface"));
+ __FLOG_1(_T8("-> connect to host %S failed"), &host);
+ }
+#endif
+ }
+ // Opening the connecting socket has failed or the DNS lookup completed
+ // with an error code - suicide after notifying the observer - do nothing
+ // except drop through to the Connected state case...
+ }
+ case EConnected:
+ {
+ // Either the socket controller factory left in AddToStoreL() or in
+ // CreateSocketControllerLC(), or the observer left in ConnectionMadeL()
+ // or the connect request completed with an error code. Inform the
+ // observer of the error.
+ error = iObserver->HandleConnectError(errorToPropagate);
+ } break;
+ case EIdle:
+ default:
+ THttpTrLayerPanic::Panic(THttpTrLayerPanic::EBadSocketConnectorState);
+ break;
+ }
+
+ Suicide();
+
+ return error;
+ }