/*
    GSK - a library to write servers
    Copyright (C) 2001 Dave Benson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

    Contact:
        daveb@ffem.org <Dave Benson>
*/

#ifndef __GSK_DNS_INTERFACES_H_
#define __GSK_DNS_INTERFACES_H_

typedef struct _GskDnsResolverHints GskDnsResolverHints;
typedef struct _GskDnsResolverTask GskDnsResolverTask;
typedef struct _GskDnsResolver GskDnsResolver;
typedef struct _GskDnsResolverIface GskDnsResolverIface;
typedef struct _GskDnsTransmitter GskDnsTransmitter;
typedef struct _GskDnsTransmitterIface GskDnsTransmitterIface;
typedef struct _GskDnsReceiver GskDnsReceiver;
typedef struct _GskDnsReceiverIface GskDnsReceiverIface;

#include "../gskinterface.h"
#include "../gsksocketaddress.h"
#include "gskdns.h"

GskInterfaceType gsk_dns_resolver_iface_get_type ();
GskInterfaceType gsk_dns_transmitter_iface_get_type ();
GskInterfaceType gsk_dns_receiver_iface_get_type ();

#define GSK_TYPE_DNS_RESOLVER_IFACE 	(gsk_dns_resolver_iface_get_type ())
#define GSK_IS_DNS_RESOLVER(obj)	GSK_INTERFACE_TEST (obj, GSK_TYPE_DNS_RESOLVER_IFACE)
#define GSK_DNS_RESOLVER(obj)		GSK_INTERFACE_CAST (GskDnsResolver, obj, GSK_TYPE_DNS_RESOLVER_IFACE)
#define GSK_DNS_RESOLVER_GET_IFACE(obj)	GSK_INTERFACE_GET_IFACE (GskDnsResolverIface, obj, GSK_TYPE_DNS_RESOLVER_IFACE)

#define GSK_TYPE_DNS_TRANSMITTER_IFACE 		(gsk_dns_transmitter_iface_get_type ())
#define GSK_IS_DNS_TRANSMITTER(obj)		GSK_INTERFACE_TEST (obj, GSK_TYPE_DNS_TRANSMITTER_IFACE)
#define GSK_DNS_TRANSMITTER(obj)		GSK_INTERFACE_CAST (GskDnsTransmitter, obj, GSK_TYPE_DNS_TRANSMITTER_IFACE)
#define GSK_DNS_TRANSMITTER_GET_IFACE(obj)	GSK_INTERFACE_GET_IFACE (GskDnsTransmitterIface, obj, GSK_TYPE_DNS_TRANSMITTER_IFACE)

#define GSK_TYPE_DNS_RECEIVER_IFACE 		(gsk_dns_receiver_iface_get_type ())
#define GSK_IS_DNS_RECEIVER(obj)		GSK_INTERFACE_TEST (obj, GSK_TYPE_DNS_RECEIVER_IFACE)
#define GSK_DNS_RECEIVER(obj)		GSK_INTERFACE_CAST (GskDnsReceiver, obj, GSK_TYPE_DNS_RECEIVER_IFACE)
#define GSK_DNS_RECEIVER_GET_IFACE(obj)	GSK_INTERFACE_GET_IFACE (GskDnsReceiverIface, obj, GSK_TYPE_DNS_RECEIVER_IFACE)

/* --- resolver interface --- */
typedef enum
{
  GSK_DNS_RESOLVER_ERR_NO_NAME_SERVERS,
  GSK_DNS_RESOLVER_ERR_TOO_MANY_FAILURES,
  GSK_DNS_RESOLVER_ERR_NO_DATA,
  GSK_DNS_RESOLVER_ERR_ACCESS
} GskDnsResolverError;

typedef void (*GskDnsResolverLookupFunc)   (GskSocketAddress   *address,
				            gpointer            func_data);
typedef void (*GskDnsResolverRevLookupFunc)(const char         *name,
				            gpointer            func_data);
typedef void (*GskDnsResolverResponseFunc) (GSList             *answers,
					    GSList             *authority,
					    GSList             *additional,
					    gpointer            func_data);
typedef void (*GskDnsReceiverFunc)         (GskDnsMessage      *message,
					    GskSocketAddress   *recvd_from,
					    gpointer            user_data);
typedef void (*GskDnsResolverFailFunc)     (GskDnsResolverError err_code,
				            gpointer            func_data);

struct _GskDnsResolverHints
{
  GskSocketAddress       *address;
};

struct _GskDnsResolverIface
{
  GskDnsResolverTask *(*resolve) (GskDnsResolver               *resolver,
				  gboolean                      recursive,
				  GSList                       *dns_questions,
				  GskDnsResolverResponseFunc    func,
				  GskDnsResolverFailFunc        on_fail,
				  gpointer                      func_data,
				  GDestroyNotify                destroy,
				  GskDnsResolverHints          *optional_hints);
  void                (*cancel)  (GskDnsResolver               *resolver,
				  GskDnsResolverTask           *task);
};

struct _GskDnsTransmitterIface
{
  void   (*transmit)     (GskDnsTransmitter   *transmitter,
			  GskSocketAddress    *dest,
			  GskDnsMessage       *message);
};

struct _GskDnsReceiverIface
{
  GHook *(*trap_messages)(GskDnsReceiver      *receiver,
			  GskDnsReceiverFunc   func,
			  gpointer             user_data,
			  GDestroyNotify       destroy);
  void   (*untrap)       (GskDnsReceiver      *receiver,
			  GHook               *hook);
};


/* --- public accessor functions --- */

GskDnsResolverTask *gsk_dns_resolver_resolve (GskDnsResolver        *client,
					      gboolean               recursive,
				              GSList                *questions,
				              GskDnsResolverResponseFunc func,
				              GskDnsResolverFailFunc on_fail,
				              gpointer               func_data,
                                              GDestroyNotify         notify,
					      GskDnsResolverHints   *hints);


void                gsk_dns_resolver_cancel  (GskDnsResolver        *resolver,
					      GskDnsResolverTask    *task);
                   
void                gsk_dns_transmitter_transmit
                                             (GskDnsTransmitter     *trans,
                                              GskSocketAddress      *dest,
                                              GskDnsMessage         *message);
GHook              *gsk_dns_receiver_trap_messages
                                             (GskDnsReceiver        *receiver,
                                              GskDnsReceiverFunc     func,
                                              gpointer               user_data,
                                              GDestroyNotify         destroy);
void                gsk_dns_receiver_untrap  (GskDnsReceiver        *receiver,
                                              GHook                 *hook);

/* helper functions to use this interface to do simple DNS lookups */
GskDnsResolverTask *gsk_dns_resolver_lookup  (GskDnsResolver        *client,
				              const char            *name,
				              GskDnsResolverLookupFunc func,
				              GHookFunc              on_fail,
				              gpointer               func_data,
				              GDestroyNotify         notify);
GskDnsResolverTask *gsk_dns_resolver_rev_lookup 
                                             (GskDnsResolver        *client,
				              const char            *name,
				              GskDnsResolverRevLookupFunc func,
				              GHookFunc              on_fail,
				              gpointer               func_data,
				              GDestroyNotify         notify);

#endif
