tcpiputils/dnd/inc/dns_sock.h
changeset 0 af10295192d8
child 53 7e41d162e158
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpiputils/dnd/inc/dns_sock.h	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,379 @@
+// Copyright (c) 2004-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:
+// dns_sock.h - Domain Name resolver socket
+//
+
+#ifndef __DNS_SOCK_H__
+#define __DNS_SOCK_H__
+
+/**
+@file dns_sock.h
+Basic class for sending and receiving DNS protocol packets
+@internalComponent	Domain Name Resolver
+*/
+
+
+#include <e32std.h>
+class TMsgBuf;
+class CDnsSocketWriter;
+class TDnsRequest;
+
+
+class CDnsSocket : public CBase
+/**
+Manage sending and receiving of DNS protocol packets on a socket
+
+  @internalComponent	Domain Name Resolver
+
+  Class contains the basic control mechanisms for reading and
+  writing the socket. A number of send requests (TDnsRequest) can
+  be queued into the "system" and they will be processed one
+  after another as socket becomes available for a new send.
+  At same time, any incoming packets are received and offered
+  for processing.
+*/
+    {
+	friend class CDnsSocketWriter;
+protected:
+	CDnsSocket(TUint aMaxDnsMessage = 0);
+	virtual ~CDnsSocket();
+	void ConstructL();
+	/**
+	Open and activate the UDP socket for DNS traffic (unless already done).
+	
+	The CDnsSocket has private memory for local address and port, which
+	both are initialized to unspecified. However, if the
+	ActivateSocketL(const TInetAddr &) has been called, then the last
+	such call defines the local address and port for this method also.
+	The aNetworkId parameter is used to pickup the correct RConnection
+ 	handle when the EXPLICIT_SOCKET_BINDING option and NON_SEAMLESS_
+	BEARER mobility is enabled.
+	*/
+	void ActivateSocketL(TUint aNetworkId=0);
+
+	/**
+	Open and activate the UDP socket for DNS traffic (unless already done).
+	
+	@param aBind
+		defines the local port and addres for the socket. Address
+		and port can be unspecified (the default, if nothing is specified).
+	*/
+	void ActivateSocketL(const TInetAddr &aBind);
+	/**
+	Open and activate the TCP listen socket for DNS traffic.
+	
+	@param aBind
+		defines the local port and addres for the socket. Address
+		and port can be unspecified (the default, if nothing is specified).
+	*/
+	void ActivateListenL(const TInetAddr &aBind, TInt aTTL);
+	// Close and deactivate the UDP socket for DNS traffic
+	void DeactivateSocket(TInt aReason = KErrCancel);
+	void SetHoplimit(const TInt aTTL);
+	/**
+	(Re)Queue the request for processing.
+	
+	@param aRequest to be queued
+	@param aId of the request, if >= 0. If < 0, then a new random ID is generated
+	*/
+	void Queue(TDnsRequest &aRequest, const TInt aId = -1);
+	/**
+	(Re)Queue the request for processing.
+	
+	@param aRequest to be queued
+	@param aSocket identifies a specific active socket within the
+			CDnsSocket to be used (see CDnsSocket::Query).
+	@param aId of the request, if >= 0. If < 0, then a new random ID is generated
+	@return
+		@li KErrNone, if queued successfully,
+		@li KErrNotFound, if the socket does not exist (not queued)
+	*/
+	TInt Queue(TDnsRequest &aRequest, const RSocket &aSocket, const TInt aId = -1);
+	/**
+	(Re)Queue the request for processing using connected socket (TCP)
+	
+	@param aRequest to be queued
+	@param aServer The address and port of the DNS server
+	@param aId of the request, if >= 0. If < 0, then a new random ID is generated
+	@param aTTL of the connection (= -1, the default, requests the system default)
+	
+	@return KErrNone, if queued successfully, or error code if failed.
+	*/
+	TInt Queue(TDnsRequest &aRequest, const TInetAddr &aServer, const TInt aId = -1, const TInt aTTL = -1);
+	/**
+	Reque the request for a resend with same ID (if was queued).
+	
+	If the request is not already queued, action defaults to
+	normal Queue().
+	
+	@param aRequest to be queued
+	*/
+	void ReSend(TDnsRequest &aRequest);
+
+	/**
+	Received a Query or unmatched Reply packet
+	
+	The Query method must be implemented by the derived class. The
+	Query is called when a DNS protocol message containing a query
+	or a reply which is not accepted by any of the current requests,
+	is received.
+	
+	@param aBuf		the received message
+	@param aServer	from which the messsage came
+	@parma aSocket
+		identify originating socket. Note that this
+		"const", you cannot do any socket oprartions with
+		this. It is only provided for the special Queue
+		function, which queues a request to a specific
+		socket.
+	*/
+	virtual void Query(const TMsgBuf &aBuf, const TInetAddr &aServer, const RSocket &aSocket) = 0;
+	/**
+	Communication error with a destination
+
+    The Error method can be implemented by the derived class. The
+	Error is called when DNS socket receives an ICMP error notification
+	when communicating with this target.
+
+	@param aServer for which the error relates
+	@param the error from the socket
+	*/
+	virtual void Error(const TInetAddr &aServer, TInt aError) { (void)aServer; (void)aError; };
+
+private:
+	TInt AddSecondaryWriter(CDnsSocketWriter *aWriter);
+	void DeleteWriter(CDnsSocketWriter *aWriter, TInt aReason);
+	CDnsSocketWriter *iWriter;	//< Primary Socket Reader/Writer
+protected:
+	const TUint iMaxDnsMessage;	//< Max DNS message length.
+	/**
+	Get the primary RSocket
+	
+	@return a reference to primary RSocket (UDP)
+	*/
+	RSocket& Socket();
+	TBool IsOpened() const;
+
+	RSocketServ iSS;			//< Keep own Socket Server Session
+	RSocket iListener;			//< Used for listening incoming TCP connections, if enabled.
+	TUint iConnected:1;			//< = 1, if Socket Server Session is connected.
+	TUint iListening:1;			//< = 1, if iListener is open
+
+private:
+	TUint iNetworkId;           		//< = network id fetched from the request
+	};
+
+class TDnsRequestLink : public TDblQueLink
+/**
+Link field of requests.
+
+This object is ONLY used as a member of TDnsRequest to maintain
+the links when the request is queued for processing.
+*/
+	{
+	friend class TDnsRequest;
+	friend class CDnsSocketWriter;
+public:
+	inline TDnsRequestLink() : iWriter(NULL) {}
+	// @return TRUE, if request is currently queued
+	inline TBool IsQueued() const { return iWriter != NULL; }
+private:
+	// @return The current socket object, or NULL if not queued
+	inline CDnsSocketWriter *Writer() { return iWriter; }
+	/**
+	Set new DNS socket object.
+	@param	aWriter	The new socket object
+	*/
+	inline void SetWriter(CDnsSocketWriter *aWriter) { iWriter = aWriter; }
+	/**
+	Identifies the queued status and handler for the request.
+	@li == NULL,
+		when the request is not queued.
+	@li != NULL,
+		a pointer to the internal socket handling object, which
+		is currently assigned to handle the request.			
+	*/
+	CDnsSocketWriter *iWriter;
+	};
+
+	
+class TDnsRequest
+/**
+// The base class for the DNS query request.
+//
+// The request is controlled by three CDnsScoket methods:
+//
+// @li CDnsSocket::Queue, (re)enter request into CDnsSocket
+// @li CDnsSocket::ReSend, (re)enter request into CDnsSocket
+// @li CDnsSocket::Remove, remove request from CDnsSocket
+//
+// While request is "active in the system" (inside CDnsSocket),
+// it's state and progress is reported by the following callbacks:
+//
+// @li TDnsRequest::Build, ready to send a packet
+// @li TDnsRequest::Sent, packet sent
+// @li TDnsRequest::Reply, possible reply received
+// @li TDnsRequest::Abort, request aborted
+//
+// The main life cycle of a request is as follows:
+@verbatim
+    .----->.
+   /        \
+Remove      Queue
+ ^           |
+ |___        |
+ ^   \       V 
+ |  ReSend   /
+ |      \   /
+ |       \ /
+ |< - - - |
+ |   wait for send
+ |     possible
+ |< - - - |-------> Build()
+ |    send packet
+ |     to socket
+ |   and wait for
+ |    completion
+ |< - - - |-------> Sent()
+ |        .
+ |        .
+ |        |
+ |   reply matching
+ |   the request id
+ |     arrives
+  < - - - |-------> Reply()
+
+@endverbatim
+
+  In addition to above, at any point in the lifetime, TDnsRequest::Abort()
+  could be called, if the request cannot be processed. For example,
+  deactivation of the socket will cause Abort call to all requests.
+
+  At any point, the owner of the request can ReSend, Queue or Remove it
+  from the system, regardless of the current state of the request. If
+  ReSend is called with request that is not already in the system, the
+  Queue action happens instead. Remove does nothing, if request is not
+  in the system.
+
+  Note that, when a request is queued, it is only a kind of <em>token</em>
+  that is placed into queue to wait for its turn on sending socket.
+  Nothing about the actual packet to be sent needs to be present, until
+  the DnsRequest::Build is called.
+*/
+	{
+	friend class TRequestQueue;
+	friend class CDnsSocketWriter;
+public:
+	/** @brief Build the DNS packet for the request into buffer
+	//
+	// Build callback occurs just before the socket is ready to send a message
+	// corresponding this request. This method should build the desired
+	// message into aBuf, determine the actual destination address (aServer)
+	// return TRUE (= 1). The DnsSocket will start a socket send for the
+	// message. TDnsRequest::Sent will be called, when the socket send
+	// operation completes.
+	//
+	// If message cannot be build (or should not be sent), return FALSE (= 0)
+	//
+	// In either case, the request will remain queued in DnsSocket (unless
+	// removed).
+	//
+	// Build CAN call CDnsSocket::Remove, even if it returns TRUE (in which
+	// case the message will be sent, but there will not be any Sent callback).
+	//
+	// @param aSource	the dns socket instance owning the request
+	// @retval aBuf		the buffer to be initialized (it has already been preinitialized
+	//					using the TDndHeader::Init method). Build method can
+	//					either ignore this or use it as a base.
+	// @retval aServer	must be initialized with the destination address and port
+	//					of the message (if return is TRUE). If the request is
+	//					using TCP, this is ignored.
+	// @param aRecvLength
+	//				the current size of the receive buffer
+	//
+	// @returns
+	//	@li	TRUE,	if message and server has been set, and socket should send the
+	//				message out, request is moved into "wait" state.
+	//	@li	FALSE,	if socket should not send any message from this request. This
+	//				causes the request to be moved into "wait" state.
+	*/
+	virtual TBool Build(CDnsSocket &aSource, TMsgBuf &aBuf, TInetAddr &aServer, TInt aRecvLength) = 0;
+	/** @brief A packet has been sent to the server
+	//
+	// Sent callback occurs when the "send" of the message completes on the socket.
+	// This is a notification only. The request remains queued (unless removed).
+	//
+	// Sent CAN call CDnsSocket::Remove.
+	//
+	// @param aSource	the dns socket instance owning the request
+	*/
+	virtual void Sent(CDnsSocket &aSource) = 0;
+	/** @brief A reply received
+	//
+	// Reply callback occurs when a socket receives a DNS reply message from a
+	// server with an ID matching this request (in wait state). The Reply
+	// method should do some further verifications whether the reply really
+	// is for this request.
+	// If the reply matches this request, the method should process the reply
+	// and return TRUE.
+	//
+	// If the reply does not match this request, the method should return
+	// FALSE, and the DnsSocket will try another request with same id. If
+	// there are no requests that match this ID (or if all of them return
+	// FALSE, the reply message is offered to the CDnsSocket::Query method).
+	//
+	// In either return (TRUE or FALSE), the request will remain in "wait" state
+	// and queued in DnsSocket (unless removed).
+	//
+	// Reply CAN call CDnsSocket::Remove, and still return either
+	// TRUE or FALSE.
+	//
+	// @param aSource	the dns socket instance owning the request
+	// @param aBuf		the buffer containing the received reply.
+	// @param aServer	the from address of the reply message
+	//
+	// @returns
+	//	@li	TRUE,	if the reply belongs to this request and has been
+	//				processed,
+	//	@li	FALSE,	if the reply does not belong to this request, and
+	//				some other request should be asked.
+	*/
+	virtual TBool Reply(CDnsSocket &aSource, const TMsgBuf &aBuf, const TInetAddr &aServer) = 0;
+	/** @brief Request aborted
+	//
+	// Abort callback occurs when the DNS socket throws out a request
+	// that it has queued. This is NOT called, when the request is
+	// removed explicitly by CDnsSocket::Remove. The normal reason
+	// for Abort is CDnsSocket::DeactivateSocket, if called with
+	// queued requests present.
+	//
+	// There is no reason for Abort to call CDnsSocket::Remove,
+	// because the request has already been effectively removed
+	// before the Abort call.
+	//
+	// @param aSource	the dns socket instance owning the request
+	// @param aReason	the reason code for the abort
+	*/
+	virtual void Abort(CDnsSocket &aSource, const TInt aReason) = 0;
+	// Return TRUE, if request is queued
+	inline TBool IsQueued() const { return iQueueLink.IsQueued(); }
+	// Cancel request (silently remove from the queue, if any)
+	void Cancel();
+	// Return ID value
+	TInt Id() const { return iId; }
+private:
+	TDnsRequestLink iQueueLink;	//< Linking requests together
+	TUint16 iId;				//< The assigned request ID
+	};
+#endif