tcpiputils/dhcp/src/DHCPIP4ServerControl.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dhcp/src/DHCPIP4ServerControl.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,295 @@
+// Copyright (c) 2007-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:
+// Implements the DHCP IP4 Server control class which controls the upper states
+// The Upper state machine for DHCP server are
+// - Wait For Discover or Inform
+// - Wait For Discover / release / decline / renew and rebind request msgs
+// 
+//
+
+/**
+ @file DHCPIP4ServerControl.cpp
+ @internalTechnology
+*/
+
+#include "DHCPIP4ServerControl.h"
+#include "DHCPIP4Msg.h"
+#include "DHCPDb.h"
+#include "ExpireTimer.h"
+#include "DHCPConfigListener.h"
+#include "DHCPStatesDebug.h"
+
+//Dns proxy related includes
+#ifdef SYMBIAN_DNS_PROXY
+#include <dnsproxyupdateif.h>
+#endif // SYMBIAN_DNS_PROXY
+
+CDHCPIP4ServerControl::~CDHCPIP4ServerControl()
+	{	
+#ifdef SYMBIAN_DNS_PROXY
+    __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4ServerControl::~CDHCPIP4ServerControl()")));
+    iDnsProxySession.Close();
+    delete iDnsProxyPlugin;
+#endif // SYMBIAN_DNS_PROXY
+	}
+
+
+void CDHCPIP4ServerControl::ConfigureL(const TConnectionInfo& aInfo, const RMessage2* aMessage)
+/**
+  * Open and attach to the RConnection
+  *
+  * @internalTechnology
+  */
+	{
+#ifdef SYMBIAN_DNS_PROXY
+	//configure Dns Proxy Server
+	ConfigureDnsProxyL(aMessage);
+#endif // SYMBIAN_DNS_PROXY
+	// use the base class functionality
+	CDHCPIP4Control::ConfigureL(aInfo,aMessage);
+	// bind the server socket with the static IP address from Comms database
+	// we use a bind state  for server to implement timer and continue in the bind state
+	// unless the tcpip6 is successful in binding the socket with the IP address
+	iDhcpStateMachine->InitServerBinding(this);
+
+	iDhcpStateMachine->iSvrState = ESvrBinding;
+	iDhcpStateMachine->SetServerState(ETrue);
+
+#ifdef SYMBIAN_DNS_PROXY
+	//read DNS proxy entries from database.should not leave even if host name is not available
+	TRAPD(err,iDhcpDb->ReadHostNameL(*iDhcpStateMachine));
+	if(err!= KErrNone)
+		{
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4ServerControl::ConfigureL().Host name not found")));
+		}
+
+	if(iDhcpStateMachine->iProxyDomainName.Length())
+	    {
+	    TRequestStatus aStatus;
+		iDnsProxySession.UpdateDomainName(iDhcpStateMachine->iProxyDomainName, aStatus);
+	    User::WaitForRequest(aStatus);
+	    }
+
+#endif // SYMBIAN_DNS_PROXY
+
+	}
+
+void CDHCPIP4ServerControl::TimerExpired()
+/**
+  * Called by the timer to signal that the timer has expired
+  *
+  * @internalTechnology
+  */
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP4ServerControl::TimerExpired()")));
+
+	iDhcpStateMachine->Cancel();
+	iDhcpStateMachine->InitServerStateMachineL(this);
+	// bind the socket with the session
+	iDhcpStateMachine->BindServerInterface();
+
+	// There is a only rebind timer for this simplified DHCP Server implementation
+	// After the discover or renew-request a timer until the rebind time is run
+	// We service only a single client and the server does not check if the client
+	// failed with DAD. Hence if the timer expired after rebind timer then we know we
+	// no longer service any client , so we go back to original state (ESvrWaitForDiscoverInform)
+
+	if(iDhcpStateMachine->iSvrState == ESvrWaitForAnyDHCPMsgs)
+		{
+	   	iDhcpStateMachine->iSvrState = ESvrWaitForDiscoverInform;
+		}
+	else
+		{
+		_LIT(KDhcpPanicReason, "Timer expired in unexpected state");
+		User::Panic(KDhcpPanicReason, KErrNotSupported);
+		}
+	}
+
+void CDHCPIP4ServerControl::TaskCompleteL(TInt aError)
+	{
+	__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+		         _L8("CDHCPIP4ServerControl::TaskCompleteL (%d) with error = %d") ,
+		         iDhcpStateMachine->iSvrState, aError));
+
+	// cancel possibly working message sender & socket activity
+	// and delete current states cancels the timer
+	iDhcpStateMachine->Cancel();
+	iTimer->Cancel();
+	// we re-intialise the server state to wait for next message (in any state)
+	iDhcpStateMachine->InitServerStateMachineL(this);
+
+	if ( aError == KErrServerTerminated )
+		{
+		__CFLOG_VAR((KLogSubSysDHCP, KLogCode,
+		         _L8("CDHCPServerControl::TaskCompleteL server terminated => complete client request & going to idle")));
+		iDhcpStateMachine->iSvrState = ESvrEnd;
+
+		CompleteServerConfigureMessage(aError);
+		CompleteServerIoctlMessage(aError);
+		// we cant wait for client messages any more as the server has terminated
+		return;
+		}
+
+	switch (iDhcpStateMachine->iSvrState)
+		{
+		case ESvrBinding:
+			// we are done with binding the server socket, now start waiting for client messages
+			iDhcpStateMachine->iSvrState = ESvrWaitForDiscoverInform;
+			if(iDNSRawOption)
+				{
+				TPtr8 ptr = iDNSRawOption->Des();
+				iDhcpStateMachine->SetDNSInformation(&ptr);
+				}
+
+#ifdef SYMBIAN_DNS_PROXY
+			//update DNS Proxy database
+			iInterfaceAddr = iDhcpStateMachine->GetListenerAddress();
+			iInterfaceAddr.Output(iAddrStr);
+			if((iInterfaceAddr.Address()) && (iDhcpStateMachine->iProxyHostName.Length()))
+                {
+                TRequestStatus aStatus;
+                iDnsProxyPlugin->AddDbEntry(iDhcpStateMachine->iProxyHostName, iAddrStr, aStatus);
+                User::WaitForRequest(aStatus);
+                }
+			iUpdateDnsProxyDb = ETrue;
+
+#endif // SYMBIAN_DNS_PROXY
+			break;
+
+		case ESvrWaitForDiscoverInform:
+			// some error , go back to intial state (ESvrWaitForDiscoverInform)
+			if (KErrNone != aError)
+				{
+				// some error, reset to intial server state
+				iDhcpStateMachine->iSvrState = ESvrWaitForDiscoverInform;
+				}
+			else
+				{
+				// if inform msg processed, go back to initial state
+				if(iDhcpStateMachine->iSvrSpecificState == ESvrInformInProgress)
+					{
+					iDhcpStateMachine->iSvrState = ESvrWaitForDiscoverInform;
+#ifdef SYMBIAN_DNS_PROXY
+					iDhcpStateMachine->iClientStaticAddr.Output(iAddrStr);
+                    if((iDhcpStateMachine->iClientStaticAddr.Address()) && (iDhcpStateMachine->iClientHostName.Length()))
+                        {
+                        TRequestStatus aStatus;
+                        iDnsProxyPlugin->AddDbEntry(iDhcpStateMachine->iClientHostName, iAddrStr, aStatus);
+                        User::WaitForRequest(aStatus);
+                        }
+					
+#endif // SYMBIAN_DNS_PROXY
+    				}
+				else
+					{
+					// discover was successful, so we now wait for renew, rebind,release, decline
+					// or a discover msg from another client (just in case)
+
+#ifdef SYMBIAN_DNS_PROXY
+					if(iUpdateDnsProxyDb )
+                    	{
+                    	iOfferedAddr.SetAddress(iDhcpStateMachine->iOfferedAddress);
+						iOfferedAddr.Output(iAddrStr);
+
+                        if((iOfferedAddr.Address()) && (iDhcpStateMachine->iClientHostName.Length()))
+                            {
+                            TRequestStatus aStatus;
+                            iDnsProxyPlugin->AddDbEntry(iDhcpStateMachine->iClientHostName, iAddrStr, aStatus);
+                            User::WaitForRequest(aStatus);
+                            }
+
+						iUpdateDnsProxyDb = EFalse;
+		      	   		}
+#endif // SYMBIAN_DNS_PROXY
+
+					iDhcpStateMachine->iSvrState = ESvrWaitForAnyDHCPMsgs;
+					iTimer->After(static_cast<TTimeIntervalSeconds>(KDefaultLeaseTime/2 + KDefaultLeaseTime/4), *this);
+					}
+				iDhcpStateMachine->BindServerInterface();
+				SaveMessageBufferForLaterReference();
+				DHCP_DEBUG_PUBLISH_READY(DHCPDebug::EReady);
+				}
+
+			break;
+		// waiting for any DHCP messages like Discover, Renew and rebind requests,
+		// decline release except inform message
+		case ESvrWaitForAnyDHCPMsgs:
+			if (KErrNone != aError)
+				{
+				//Complete client request with error if there is any
+				CompleteServerIoctlMessage(aError);
+				iDhcpStateMachine->iSvrState = ESvrWaitForAnyDHCPMsgs;
+				}
+			else
+				{
+				switch(iDhcpStateMachine->iSvrSpecificState)
+					{
+				case ESvrDiscoverInProgress:
+				case ESvrRenewInProgress:
+				case ESvrRebindInProgress:
+
+					iDhcpStateMachine->iSvrState = ESvrWaitForAnyDHCPMsgs;
+					iTimer->After(static_cast<TTimeIntervalSeconds>(KDefaultLeaseTime/2 + KDefaultLeaseTime/4), *this);
+
+					iDhcpStateMachine->BindServerInterface();
+					SaveMessageBufferForLaterReference();
+					DHCP_DEBUG_PUBLISH_READY(DHCPDebug::EReady);
+					break;
+
+				case ESvrReleaseInProgress:
+				case ESvrDeclineInProgress:
+					// go back to intial state, client released ..
+
+	#ifdef SYMBIAN_DNS_PROXY
+					iDhcpStateMachine->iClientStaticAddr.Output(iAddrStr);
+
+					TRequestStatus aStatus;
+					iDnsProxyPlugin->RemoveDbEntry(iAddrStr, aStatus);
+					User::WaitForRequest(aStatus);
+
+					iUpdateDnsProxyDb = ETrue;
+	#endif // SYMBIAN_DNS_PROXY
+
+					iDhcpStateMachine->iSvrState = ESvrWaitForDiscoverInform;
+					break;
+					}
+				}
+			break;
+
+		default: // some unknown state may be, so reset the state to receive any message (<- unlikely)
+			iDhcpStateMachine->iSvrState = ESvrWaitForAnyDHCPMsgs;
+		}
+	}
+	
+#ifdef SYMBIAN_DNS_PROXY	
+void CDHCPIP4ServerControl::ConfigureDnsProxyL(const RMessage2* aMessage)
+	{
+	//load DNS Proxy Server
+    TConnectionInfoBuf configInfo;
+    TRequestStatus aStatus;
+	
+	aMessage->Read(0, configInfo);
+	User::LeaveIfError(iDnsProxySession.Connect());
+	
+	iDnsProxySession.ConfigureDnsProxyServer(configInfo, aStatus);
+    User::WaitForRequest(aStatus);
+	User::LeaveIfError(aStatus.Int());
+	
+	TUid uid = {0x200215F5};  
+	//load proxy plugin  
+    TRAPD(err, iDnsProxyPlugin = CDNSProxyUpdateIf::NewL(uid));
+    User::LeaveIfError(err);
+    }
+    
+#endif // SYMBIAN_DNS_PROXY