--- /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