diff -r 000000000000 -r af10295192d8 tcpiputils/dnd/inc/dns_sock.h --- /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 +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 token + 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