tcpiputils/dnd/inc/dns_sock.h
changeset 0 af10295192d8
child 53 7e41d162e158
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // dns_sock.h - Domain Name resolver socket
       
    15 //
       
    16 
       
    17 #ifndef __DNS_SOCK_H__
       
    18 #define __DNS_SOCK_H__
       
    19 
       
    20 /**
       
    21 @file dns_sock.h
       
    22 Basic class for sending and receiving DNS protocol packets
       
    23 @internalComponent	Domain Name Resolver
       
    24 */
       
    25 
       
    26 
       
    27 #include <e32std.h>
       
    28 class TMsgBuf;
       
    29 class CDnsSocketWriter;
       
    30 class TDnsRequest;
       
    31 
       
    32 
       
    33 class CDnsSocket : public CBase
       
    34 /**
       
    35 Manage sending and receiving of DNS protocol packets on a socket
       
    36 
       
    37   @internalComponent	Domain Name Resolver
       
    38 
       
    39   Class contains the basic control mechanisms for reading and
       
    40   writing the socket. A number of send requests (TDnsRequest) can
       
    41   be queued into the "system" and they will be processed one
       
    42   after another as socket becomes available for a new send.
       
    43   At same time, any incoming packets are received and offered
       
    44   for processing.
       
    45 */
       
    46     {
       
    47 	friend class CDnsSocketWriter;
       
    48 protected:
       
    49 	CDnsSocket(TUint aMaxDnsMessage = 0);
       
    50 	virtual ~CDnsSocket();
       
    51 	void ConstructL();
       
    52 	/**
       
    53 	Open and activate the UDP socket for DNS traffic (unless already done).
       
    54 	
       
    55 	The CDnsSocket has private memory for local address and port, which
       
    56 	both are initialized to unspecified. However, if the
       
    57 	ActivateSocketL(const TInetAddr &) has been called, then the last
       
    58 	such call defines the local address and port for this method also.
       
    59 	The aNetworkId parameter is used to pickup the correct RConnection
       
    60  	handle when the EXPLICIT_SOCKET_BINDING option and NON_SEAMLESS_
       
    61 	BEARER mobility is enabled.
       
    62 	*/
       
    63 	void ActivateSocketL(TUint aNetworkId=0);
       
    64 
       
    65 	/**
       
    66 	Open and activate the UDP socket for DNS traffic (unless already done).
       
    67 	
       
    68 	@param aBind
       
    69 		defines the local port and addres for the socket. Address
       
    70 		and port can be unspecified (the default, if nothing is specified).
       
    71 	*/
       
    72 	void ActivateSocketL(const TInetAddr &aBind);
       
    73 	/**
       
    74 	Open and activate the TCP listen socket for DNS traffic.
       
    75 	
       
    76 	@param aBind
       
    77 		defines the local port and addres for the socket. Address
       
    78 		and port can be unspecified (the default, if nothing is specified).
       
    79 	*/
       
    80 	void ActivateListenL(const TInetAddr &aBind, TInt aTTL);
       
    81 	// Close and deactivate the UDP socket for DNS traffic
       
    82 	void DeactivateSocket(TInt aReason = KErrCancel);
       
    83 	void SetHoplimit(const TInt aTTL);
       
    84 	/**
       
    85 	(Re)Queue the request for processing.
       
    86 	
       
    87 	@param aRequest to be queued
       
    88 	@param aId of the request, if >= 0. If < 0, then a new random ID is generated
       
    89 	*/
       
    90 	void Queue(TDnsRequest &aRequest, const TInt aId = -1);
       
    91 	/**
       
    92 	(Re)Queue the request for processing.
       
    93 	
       
    94 	@param aRequest to be queued
       
    95 	@param aSocket identifies a specific active socket within the
       
    96 			CDnsSocket to be used (see CDnsSocket::Query).
       
    97 	@param aId of the request, if >= 0. If < 0, then a new random ID is generated
       
    98 	@return
       
    99 		@li KErrNone, if queued successfully,
       
   100 		@li KErrNotFound, if the socket does not exist (not queued)
       
   101 	*/
       
   102 	TInt Queue(TDnsRequest &aRequest, const RSocket &aSocket, const TInt aId = -1);
       
   103 	/**
       
   104 	(Re)Queue the request for processing using connected socket (TCP)
       
   105 	
       
   106 	@param aRequest to be queued
       
   107 	@param aServer The address and port of the DNS server
       
   108 	@param aId of the request, if >= 0. If < 0, then a new random ID is generated
       
   109 	@param aTTL of the connection (= -1, the default, requests the system default)
       
   110 	
       
   111 	@return KErrNone, if queued successfully, or error code if failed.
       
   112 	*/
       
   113 	TInt Queue(TDnsRequest &aRequest, const TInetAddr &aServer, const TInt aId = -1, const TInt aTTL = -1);
       
   114 	/**
       
   115 	Reque the request for a resend with same ID (if was queued).
       
   116 	
       
   117 	If the request is not already queued, action defaults to
       
   118 	normal Queue().
       
   119 	
       
   120 	@param aRequest to be queued
       
   121 	*/
       
   122 	void ReSend(TDnsRequest &aRequest);
       
   123 
       
   124 	/**
       
   125 	Received a Query or unmatched Reply packet
       
   126 	
       
   127 	The Query method must be implemented by the derived class. The
       
   128 	Query is called when a DNS protocol message containing a query
       
   129 	or a reply which is not accepted by any of the current requests,
       
   130 	is received.
       
   131 	
       
   132 	@param aBuf		the received message
       
   133 	@param aServer	from which the messsage came
       
   134 	@parma aSocket
       
   135 		identify originating socket. Note that this
       
   136 		"const", you cannot do any socket oprartions with
       
   137 		this. It is only provided for the special Queue
       
   138 		function, which queues a request to a specific
       
   139 		socket.
       
   140 	*/
       
   141 	virtual void Query(const TMsgBuf &aBuf, const TInetAddr &aServer, const RSocket &aSocket) = 0;
       
   142 	/**
       
   143 	Communication error with a destination
       
   144 
       
   145     The Error method can be implemented by the derived class. The
       
   146 	Error is called when DNS socket receives an ICMP error notification
       
   147 	when communicating with this target.
       
   148 
       
   149 	@param aServer for which the error relates
       
   150 	@param the error from the socket
       
   151 	*/
       
   152 	virtual void Error(const TInetAddr &aServer, TInt aError) { (void)aServer; (void)aError; };
       
   153 
       
   154 private:
       
   155 	TInt AddSecondaryWriter(CDnsSocketWriter *aWriter);
       
   156 	void DeleteWriter(CDnsSocketWriter *aWriter, TInt aReason);
       
   157 	CDnsSocketWriter *iWriter;	//< Primary Socket Reader/Writer
       
   158 protected:
       
   159 	const TUint iMaxDnsMessage;	//< Max DNS message length.
       
   160 	/**
       
   161 	Get the primary RSocket
       
   162 	
       
   163 	@return a reference to primary RSocket (UDP)
       
   164 	*/
       
   165 	RSocket& Socket();
       
   166 	TBool IsOpened() const;
       
   167 
       
   168 	RSocketServ iSS;			//< Keep own Socket Server Session
       
   169 	RSocket iListener;			//< Used for listening incoming TCP connections, if enabled.
       
   170 	TUint iConnected:1;			//< = 1, if Socket Server Session is connected.
       
   171 	TUint iListening:1;			//< = 1, if iListener is open
       
   172 
       
   173 private:
       
   174 	TUint iNetworkId;           		//< = network id fetched from the request
       
   175 	};
       
   176 
       
   177 class TDnsRequestLink : public TDblQueLink
       
   178 /**
       
   179 Link field of requests.
       
   180 
       
   181 This object is ONLY used as a member of TDnsRequest to maintain
       
   182 the links when the request is queued for processing.
       
   183 */
       
   184 	{
       
   185 	friend class TDnsRequest;
       
   186 	friend class CDnsSocketWriter;
       
   187 public:
       
   188 	inline TDnsRequestLink() : iWriter(NULL) {}
       
   189 	// @return TRUE, if request is currently queued
       
   190 	inline TBool IsQueued() const { return iWriter != NULL; }
       
   191 private:
       
   192 	// @return The current socket object, or NULL if not queued
       
   193 	inline CDnsSocketWriter *Writer() { return iWriter; }
       
   194 	/**
       
   195 	Set new DNS socket object.
       
   196 	@param	aWriter	The new socket object
       
   197 	*/
       
   198 	inline void SetWriter(CDnsSocketWriter *aWriter) { iWriter = aWriter; }
       
   199 	/**
       
   200 	Identifies the queued status and handler for the request.
       
   201 	@li == NULL,
       
   202 		when the request is not queued.
       
   203 	@li != NULL,
       
   204 		a pointer to the internal socket handling object, which
       
   205 		is currently assigned to handle the request.			
       
   206 	*/
       
   207 	CDnsSocketWriter *iWriter;
       
   208 	};
       
   209 
       
   210 	
       
   211 class TDnsRequest
       
   212 /**
       
   213 // The base class for the DNS query request.
       
   214 //
       
   215 // The request is controlled by three CDnsScoket methods:
       
   216 //
       
   217 // @li CDnsSocket::Queue, (re)enter request into CDnsSocket
       
   218 // @li CDnsSocket::ReSend, (re)enter request into CDnsSocket
       
   219 // @li CDnsSocket::Remove, remove request from CDnsSocket
       
   220 //
       
   221 // While request is "active in the system" (inside CDnsSocket),
       
   222 // it's state and progress is reported by the following callbacks:
       
   223 //
       
   224 // @li TDnsRequest::Build, ready to send a packet
       
   225 // @li TDnsRequest::Sent, packet sent
       
   226 // @li TDnsRequest::Reply, possible reply received
       
   227 // @li TDnsRequest::Abort, request aborted
       
   228 //
       
   229 // The main life cycle of a request is as follows:
       
   230 @verbatim
       
   231     .----->.
       
   232    /        \
       
   233 Remove      Queue
       
   234  ^           |
       
   235  |___        |
       
   236  ^   \       V 
       
   237  |  ReSend   /
       
   238  |      \   /
       
   239  |       \ /
       
   240  |< - - - |
       
   241  |   wait for send
       
   242  |     possible
       
   243  |< - - - |-------> Build()
       
   244  |    send packet
       
   245  |     to socket
       
   246  |   and wait for
       
   247  |    completion
       
   248  |< - - - |-------> Sent()
       
   249  |        .
       
   250  |        .
       
   251  |        |
       
   252  |   reply matching
       
   253  |   the request id
       
   254  |     arrives
       
   255   < - - - |-------> Reply()
       
   256 
       
   257 @endverbatim
       
   258 
       
   259   In addition to above, at any point in the lifetime, TDnsRequest::Abort()
       
   260   could be called, if the request cannot be processed. For example,
       
   261   deactivation of the socket will cause Abort call to all requests.
       
   262 
       
   263   At any point, the owner of the request can ReSend, Queue or Remove it
       
   264   from the system, regardless of the current state of the request. If
       
   265   ReSend is called with request that is not already in the system, the
       
   266   Queue action happens instead. Remove does nothing, if request is not
       
   267   in the system.
       
   268 
       
   269   Note that, when a request is queued, it is only a kind of <em>token</em>
       
   270   that is placed into queue to wait for its turn on sending socket.
       
   271   Nothing about the actual packet to be sent needs to be present, until
       
   272   the DnsRequest::Build is called.
       
   273 */
       
   274 	{
       
   275 	friend class TRequestQueue;
       
   276 	friend class CDnsSocketWriter;
       
   277 public:
       
   278 	/** @brief Build the DNS packet for the request into buffer
       
   279 	//
       
   280 	// Build callback occurs just before the socket is ready to send a message
       
   281 	// corresponding this request. This method should build the desired
       
   282 	// message into aBuf, determine the actual destination address (aServer)
       
   283 	// return TRUE (= 1). The DnsSocket will start a socket send for the
       
   284 	// message. TDnsRequest::Sent will be called, when the socket send
       
   285 	// operation completes.
       
   286 	//
       
   287 	// If message cannot be build (or should not be sent), return FALSE (= 0)
       
   288 	//
       
   289 	// In either case, the request will remain queued in DnsSocket (unless
       
   290 	// removed).
       
   291 	//
       
   292 	// Build CAN call CDnsSocket::Remove, even if it returns TRUE (in which
       
   293 	// case the message will be sent, but there will not be any Sent callback).
       
   294 	//
       
   295 	// @param aSource	the dns socket instance owning the request
       
   296 	// @retval aBuf		the buffer to be initialized (it has already been preinitialized
       
   297 	//					using the TDndHeader::Init method). Build method can
       
   298 	//					either ignore this or use it as a base.
       
   299 	// @retval aServer	must be initialized with the destination address and port
       
   300 	//					of the message (if return is TRUE). If the request is
       
   301 	//					using TCP, this is ignored.
       
   302 	// @param aRecvLength
       
   303 	//				the current size of the receive buffer
       
   304 	//
       
   305 	// @returns
       
   306 	//	@li	TRUE,	if message and server has been set, and socket should send the
       
   307 	//				message out, request is moved into "wait" state.
       
   308 	//	@li	FALSE,	if socket should not send any message from this request. This
       
   309 	//				causes the request to be moved into "wait" state.
       
   310 	*/
       
   311 	virtual TBool Build(CDnsSocket &aSource, TMsgBuf &aBuf, TInetAddr &aServer, TInt aRecvLength) = 0;
       
   312 	/** @brief A packet has been sent to the server
       
   313 	//
       
   314 	// Sent callback occurs when the "send" of the message completes on the socket.
       
   315 	// This is a notification only. The request remains queued (unless removed).
       
   316 	//
       
   317 	// Sent CAN call CDnsSocket::Remove.
       
   318 	//
       
   319 	// @param aSource	the dns socket instance owning the request
       
   320 	*/
       
   321 	virtual void Sent(CDnsSocket &aSource) = 0;
       
   322 	/** @brief A reply received
       
   323 	//
       
   324 	// Reply callback occurs when a socket receives a DNS reply message from a
       
   325 	// server with an ID matching this request (in wait state). The Reply
       
   326 	// method should do some further verifications whether the reply really
       
   327 	// is for this request.
       
   328 	// If the reply matches this request, the method should process the reply
       
   329 	// and return TRUE.
       
   330 	//
       
   331 	// If the reply does not match this request, the method should return
       
   332 	// FALSE, and the DnsSocket will try another request with same id. If
       
   333 	// there are no requests that match this ID (or if all of them return
       
   334 	// FALSE, the reply message is offered to the CDnsSocket::Query method).
       
   335 	//
       
   336 	// In either return (TRUE or FALSE), the request will remain in "wait" state
       
   337 	// and queued in DnsSocket (unless removed).
       
   338 	//
       
   339 	// Reply CAN call CDnsSocket::Remove, and still return either
       
   340 	// TRUE or FALSE.
       
   341 	//
       
   342 	// @param aSource	the dns socket instance owning the request
       
   343 	// @param aBuf		the buffer containing the received reply.
       
   344 	// @param aServer	the from address of the reply message
       
   345 	//
       
   346 	// @returns
       
   347 	//	@li	TRUE,	if the reply belongs to this request and has been
       
   348 	//				processed,
       
   349 	//	@li	FALSE,	if the reply does not belong to this request, and
       
   350 	//				some other request should be asked.
       
   351 	*/
       
   352 	virtual TBool Reply(CDnsSocket &aSource, const TMsgBuf &aBuf, const TInetAddr &aServer) = 0;
       
   353 	/** @brief Request aborted
       
   354 	//
       
   355 	// Abort callback occurs when the DNS socket throws out a request
       
   356 	// that it has queued. This is NOT called, when the request is
       
   357 	// removed explicitly by CDnsSocket::Remove. The normal reason
       
   358 	// for Abort is CDnsSocket::DeactivateSocket, if called with
       
   359 	// queued requests present.
       
   360 	//
       
   361 	// There is no reason for Abort to call CDnsSocket::Remove,
       
   362 	// because the request has already been effectively removed
       
   363 	// before the Abort call.
       
   364 	//
       
   365 	// @param aSource	the dns socket instance owning the request
       
   366 	// @param aReason	the reason code for the abort
       
   367 	*/
       
   368 	virtual void Abort(CDnsSocket &aSource, const TInt aReason) = 0;
       
   369 	// Return TRUE, if request is queued
       
   370 	inline TBool IsQueued() const { return iQueueLink.IsQueued(); }
       
   371 	// Cancel request (silently remove from the queue, if any)
       
   372 	void Cancel();
       
   373 	// Return ID value
       
   374 	TInt Id() const { return iId; }
       
   375 private:
       
   376 	TDnsRequestLink iQueueLink;	//< Linking requests together
       
   377 	TUint16 iId;				//< The assigned request ID
       
   378 	};
       
   379 #endif