gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r18958 - in gnunet/src: dns include


From: gnunet
Subject: [GNUnet-SVN] r18958 - in gnunet/src: dns include
Date: Tue, 3 Jan 2012 21:30:07 +0100

Author: grothoff
Date: 2012-01-03 21:30:07 +0100 (Tue, 03 Jan 2012)
New Revision: 18958

Modified:
   gnunet/src/dns/dns_api_new.c
   gnunet/src/dns/dns_new.h
   gnunet/src/dns/gnunet-service-dns_new.c
   gnunet/src/include/gnunet_dns_service-new.h
Log:
-more DNS service hacking

Modified: gnunet/src/dns/dns_api_new.c
===================================================================
--- gnunet/src/dns/dns_api_new.c        2012-01-03 14:31:30 UTC (rev 18957)
+++ gnunet/src/dns/dns_api_new.c        2012-01-03 20:30:07 UTC (rev 18958)
@@ -125,6 +125,11 @@
    * Re-connect counter, to make sure we did not reconnect in the meantime.
    */
   uint32_t generation;
+  
+  /**
+   * Flags for events we care about.
+   */
+  enum GNUNET_DNS_Flags flags;
 
   /**
    * Did we start the receive loop yet?
@@ -162,7 +167,7 @@
 {
   struct GNUNET_DNS_Handle *dh = cls;
   struct ReplyQueueEntry *qe;
-  struct GNUNET_MessageHeader *msg;
+  struct GNUNET_DNS_Register *msg;
 
   dh->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
   dh->dns_connection = GNUNET_CLIENT_connect ("dns", dh->cfg);
@@ -170,11 +175,12 @@
     return;
   dh->generation++;
   qe = GNUNET_malloc (sizeof (struct ReplyQueueEntry) +
-                     sizeof (struct GNUNET_MessageHeader));
-  msg = (struct GNUNET_MessageHeader*) &qe[1];
-  qe->msg = msg;
-  msg->size = htons (sizeof (struct GNUNET_MessageHeader));
-  msg->type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT);
+                     sizeof (struct GNUNET_DNS_Register));
+  msg = (struct GNUNET_DNS_Register*) &qe[1];
+  qe->msg = &msg->header;
+  msg->header.size = htons (sizeof (struct GNUNET_DNS_Register));
+  msg->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT);
+  msg->flags = htonl (dh->flags);
   queue_reply (dh, qe);
 }
 
@@ -471,12 +477,14 @@
  * Connect to the service-dns
  *
  * @param cfg configuration to use
+ * @param flags when to call rh
  * @param rh function to call with DNS requests
  * @param rh_cls closure to pass to rh
  * @return DNS handle 
  */
 struct GNUNET_DNS_Handle *
 GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                   enum GNUNET_DNS_Flags flags,
                    GNUNET_DNS_RequestHandler rh,
                    void *rh_cls)
 {
@@ -484,6 +492,7 @@
   
   dh = GNUNET_malloc (sizeof (struct GNUNET_DNS_Handle));
   dh->cfg = cfg;
+  dh->flags = flags;
   dh->rh = rh;
   dh->rh_cls = rh_cls;
   dh->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, dh);

Modified: gnunet/src/dns/dns_new.h
===================================================================
--- gnunet/src/dns/dns_new.h    2012-01-03 14:31:30 UTC (rev 18957)
+++ gnunet/src/dns/dns_new.h    2012-01-03 20:30:07 UTC (rev 18958)
@@ -28,7 +28,25 @@
 
 GNUNET_NETWORK_STRUCT_BEGIN
 
+
 /**
+ * Message from client to DNS service to register itself.
+ */
+struct GNUNET_DNS_Register
+{
+  /**
+    * Header of type GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * NBO encoding of 'enum GNUNET_DNS_Flags' for the client.
+   */
+  uint32_t flags;
+};
+
+
+/**
  * Message from DNS service to client: please handle a request.
  */
 struct GNUNET_DNS_Request

Modified: gnunet/src/dns/gnunet-service-dns_new.c
===================================================================
--- gnunet/src/dns/gnunet-service-dns_new.c     2012-01-03 14:31:30 UTC (rev 
18957)
+++ gnunet/src/dns/gnunet-service-dns_new.c     2012-01-03 20:30:07 UTC (rev 
18958)
@@ -22,27 +22,13 @@
  * @file dns/gnunet-service-dns_new.c
  * @author Christian Grothoff
  */
-// current thoughts:
-// - for full compatibility to DNS and to avoid going insane here 
parsing/generating DNS packets,
-//   how about literally attaching the "original" DNS packet 
(request/response) to the IPC traffic?
-//   that way, clients can literally do arbitrary modifications and we are 
done with that issue here.
-//   All we'd do in here is add the IP/UDP headers and be DONE with it.
-// => minor modifications to API and IPC protocol
-// => minor modifications to our data structures
-// => major gains in terms of simplicity here and what can (at least 
theoretically) be done with the service
-// => can test much more quickly
-// => but: need to really write a good libgnunetdnsparse to avoid making MANY 
clients really complicated
-//    (not the worst of worlds either, other than deferring this mess some...)
-//    -> also positive: can be tested independently of the rest of the mess
-
-
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_constants.h"
 #include "gnunet_protocols.h"
-//#include "gnunet_dnsparser_lib.h"
 #include "gnunet_signatures.h"
 #include "dns_new.h"
+#include "gnunet_dns_service-new.h"
 
 GNUNET_NETWORK_STRUCT_BEGIN
 struct ip4_hdr
@@ -86,45 +72,58 @@
   uint16_t crc GNUNET_PACKED;
 };
 
-struct dns_pkt
+
+struct dns_hdr
 {
   uint16_t id GNUNET_PACKED;
+  uint16_t flags GNUNET_PACKED;
+  uint16_t qdcount GNUNET_PACKED;
+  uint16_t ancount GNUNET_PACKED;
+  uint16_t nscount GNUNET_PACKED;
+  uint16_t arcount GNUNET_PACKED;
+};
+GNUNET_NETWORK_STRUCT_END
 
-  unsigned rd:1 GNUNET_PACKED;  // recursion desired (client -> server)
-  unsigned tc:1 GNUNET_PACKED;  // message is truncated
-  unsigned aa:1 GNUNET_PACKED;  // authoritative answer
-  unsigned op:4 GNUNET_PACKED;  // query:0, inverse q.:1, status: 2
-  unsigned qr:1 GNUNET_PACKED;  // query:0, response:1
 
-  unsigned rcode:4 GNUNET_PACKED;       // 0 No error
-  // 1 Format error
-  // 2 Server failure
-  // 3 Name Error
-  // 4 Not Implemented
-  // 5 Refused
-  unsigned z:3 GNUNET_PACKED;   // reserved
-  unsigned ra:1 GNUNET_PACKED;  // recursion available (server -> client)
+/**
+ * Phases each request goes through.
+ */
+enum RequestPhase
+{
+  /**
+   * Request has just been received.
+   */
+  RP_INIT,
 
-  uint16_t qdcount GNUNET_PACKED;       // number of questions
-  uint16_t ancount GNUNET_PACKED;       // number of answers
-  uint16_t nscount GNUNET_PACKED;       // number of authority-records
-  uint16_t arcount GNUNET_PACKED;       // number of additional records
-};
+  /**
+   * Showing the request to all monitor clients.  If
+   * client list is empty, will enter QUERY phase.
+   */
+  RP_MONITOR,
 
-struct dns_query_line
-{
-  uint16_t type;
-  uint16_t class;
-};
+  /**
+   * Showing the request to PRE-RESOLUTION clients to find an answer.
+   * If client list is empty, will trigger global DNS request.
+   */
+  RP_QUERY,
 
-struct dns_record_line
-{
-  uint16_t type;
-  uint16_t class;
-  uint32_t ttl;
-  uint16_t data_len;
+  /**
+   * Global Internet query is now pending.
+   */
+  RP_INTERNET_DNS,
+  
+  /**
+   * Client (or global DNS request) has resulted in a response.
+   * Forward to all POST-RESOLUTION clients.  If client list is empty,
+   * give the result to the hijacker (and be done).
+   */
+  RP_MODIFY,
+
+  /**
+   * Some client has told us to drop the request.
+   */
+  RP_DROP
 };
-GNUNET_NETWORK_STRUCT_END
 
 
 /**
@@ -147,6 +146,11 @@
    */ 
   struct GNUNET_SERVER_Client *client;
 
+  /**
+   * Flags for the client.
+   */
+  enum GNUNET_DNS_Flags flags;
+
 };
 
 
@@ -157,25 +161,16 @@
 {
 
   /**
-   * Name for the request.
-   */
-  char *name;
-
-  /**
-   * Response data, or NULL if not known.
-   */ 
-  char *rdata;
-
-  /**
    * List of clients that still need to see this request (each entry
    * is set to NULL when the client is done).
    */
   struct ClientRecord **client_wait_list;
 
   /**
-   * Length of the client wait list.
+   * Payload of the UDP packet (the UDP payload), can be either query
+   * or already the response.
    */
-  unsigned int client_wait_list_length;
+  char *payload;
 
   /**
    * Source address of the original request (for sending response).
@@ -195,35 +190,20 @@
   uint64_t request_id;
 
   /**
-   * TTL if we know it, or 0.
-   */
-  uint32_t dns_ttl;
-
-  /**
-   * Number of bytes in rdata.
+   * Number of bytes in payload.
    */ 
-  uint16_t rdata_length;
+  size_t payload_length;
 
   /**
-   * Length of the 'name' string, including 0-terminator.
+   * Length of the client wait list.
    */
-  uint16_t name_length;
+  unsigned int client_wait_list_length;
 
   /**
-   * The DNS type (i.e. 1 == 'A').
+   * In which phase this this request?
    */
-  uint16_t dns_type;
+  enum RequestPhase phase;
 
-  /**
-   * The DNS class (i.e. 1 == Internet)
-   */
-  uint16_t dns_class;
-
-  /**
-   * Original DNS Id we got from the client.
-   */
-  uint16_t original_dns_id;
-
 };
 
 
@@ -281,6 +261,11 @@
 static struct ClientRecord *clients_tail;
 
 /**
+ * Our notification context.
+ */
+static struct GNUNET_SERVER_NotificationContext *nc;
+
+/**
  * Array of all open requests.
  */
 static struct RequestRecord requests[UINT16_MAX];
@@ -292,6 +277,23 @@
 
 
 /**
+ * We're done processing a DNS request, free associated memory.
+ *
+ * @param rr request to clean up
+ */
+static void
+cleanup_rr (struct RequestRecord *rr)
+{
+  GNUNET_free (rr->payload);
+  rr->payload = NULL;
+  rr->payload_length = 0;
+  GNUNET_array_grow (rr->client_wait_list,
+                    rr->client_wait_list_length,
+                    0);
+}
+
+
+/**
  * Task run during shutdown.
  *
  * @param cls unused
@@ -302,7 +304,6 @@
               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   unsigned int i;
-  struct RequestRecord *rr;
 
   GNUNET_HELPER_stop (hijacker);
   hijacker = NULL;
@@ -329,19 +330,16 @@
     read6_task = GNUNET_SCHEDULER_NO_TASK;
   }
   for (i=0;i<65536;i++)
-  {
-    rr = &requests[i];
-    GNUNET_free (rr->name);
-    GNUNET_free_non_null (rr->rdata);
-    GNUNET_array_grow (rr->client_wait_list,
-                      rr->client_wait_list_length,
-                      0);
-  }
+    cleanup_rr (&requests[i]);
+  GNUNET_SERVER_notification_context_destroy (nc);
+  nc = NULL;
 }
 
 
 /**
  * We're done with some request, finish processing.
+ *
+ * @param rr request send to the network or just clean up.
  */
 static void
 request_done (struct RequestRecord *rr)
@@ -354,11 +352,10 @@
   GNUNET_array_grow (rr->client_wait_list,
                     rr->client_wait_list_length,
                     0); 
-  if (NULL == rr->rdata)
+  if (RP_MODIFY != rr->phase)
   {
     /* no response, drop */
-    GNUNET_free (rr->name);
-    rr->name = NULL;
+    cleanup_rr (rr);
     return;
   }
   
@@ -374,21 +371,16 @@
     break;
   default:
     GNUNET_break (0);
-    GNUNET_free (rr->name);
-    rr->name = NULL;
+    cleanup_rr (rr);
     return;   
   }
   reply_len += sizeof (struct udp_pkt);
-  reply_len += sizeof (struct dns_pkt);
-  reply_len += rr->name_length;
-  reply_len += sizeof (struct dns_record_line);
-  reply_len += rr->rdata_length;
+  reply_len += rr->payload_length;
   if (reply_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
   {
     /* response too big, drop */
     GNUNET_break (0); /* how can this be? */
-    GNUNET_free (rr->name);
-    rr->name = NULL;
+    cleanup_rr(rr);
     return;    
   }
   {
@@ -433,6 +425,7 @@
     default:
       GNUNET_assert (0);
     }
+
     /* now UDP header */
     {
       struct udp_pkt udp;
@@ -444,52 +437,11 @@
       memcpy (&buf[off], &udp, sizeof (udp));
       off += sizeof (udp);
     }
-
-    /* now DNS header */
+        /* now DNS header */
     {
-      struct dns_pkt dns;
-
-      dns.id = rr->original_dns_id;
-      dns.rd = 1; /* recursion desired / supported */
-      dns.tc = 0; /* not truncated */
-      dns.aa = 1; /* are we authoritative!? I say yes. */
-      dns.op = 0; /* standard query */
-      dns.qr = 1; /* this is a response */
-      dns.rcode = 0; /* no error */
-      dns.z = 0; /* reserved */
-      dns.ra = 1; /* recursion available */
-      dns.qdcount = htons (0); /* no queries */
-      dns.ancount = htons (1); /* one answer */
-      dns.nscount = htons (0); /* no authorities yet (fixme) */
-      dns.arcount = htons (0); /* no additinal records yet (fixme) */
-      memcpy (&buf[off], &dns, sizeof (dns));
-      off += sizeof (dns);
+      memcpy (&buf[off], rr->payload, rr->payload_length);
+      off += rr->payload_length;
     }
-
-    /* now DNS name */
-    {
-      // FIXME: fill in DNS name!
-      off += rr->name_length;
-    }
-
-
-    /* now DNS record line */
-    {
-      struct dns_record_line drl;
-      
-      drl.type = htons (rr->dns_type);
-      drl.class = htons (rr->dns_class);
-      drl.ttl = htonl (rr->dns_ttl);
-      drl.data_len = htons (rr->rdata_length);
-      memcpy (&buf[off], &drl, sizeof (drl));
-      off += sizeof (drl);
-    }
-
-    /* now DNS rdata */
-    {
-      memcpy (&buf[off], rr->rdata, rr->rdata_length);
-      off += rr->rdata_length;
-    }
     
     /* final checks & sending */
     GNUNET_assert (off == reply_len);
@@ -499,12 +451,151 @@
                        NULL, NULL);
   }
   /* clean up, we're done */
-  GNUNET_free (rr->name);
-  rr->name = NULL;
+  cleanup_rr (rr);
 }
 
 
 /**
+ * Show the payload of the given request record to the client
+ * (and wait for a response).
+ *
+ * @param rr request to send to client
+ * @param client client to send the response to
+ */
+static void
+send_request_to_client (struct RequestRecord *rr,
+                       struct GNUNET_SERVER_Client *client)
+{
+  char buf[sizeof (struct GNUNET_DNS_Request) + rr->payload_length];
+  struct GNUNET_DNS_Request *req;
+
+  if (sizeof (buf) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+  {
+    GNUNET_break (0);
+    cleanup_rr (rr);
+    return;
+  }
+  req = (struct GNUNET_DNS_Request*) buf;
+  req->header.type = htons (GNUNET_MESSAGE_TYPE_DNS_CLIENT_REQUEST);
+  req->header.size = htons (sizeof (buf));
+  req->reserved = htonl (0);
+  req->request_id = rr->request_id;
+  memcpy (&req[1], rr->payload, rr->payload_length);
+  GNUNET_SERVER_notification_context_unicast (nc, 
+                                             client,
+                                             &req->header,
+                                             GNUNET_NO);
+}
+
+
+/**
+ * A client has completed its processing for this
+ * request.  Move on.
+ *
+ * @param rr request to process further
+ */
+static void
+next_phase (struct RequestRecord *rr)
+{
+  struct ClientRecord *cr;
+  int nz;
+  unsigned int j;
+  struct GNUNET_NETWORK_Handle *dnsout;
+  socklen_t salen;
+
+  if (rr->phase == RP_DROP)
+  {
+    cleanup_rr (rr);
+    return;
+  }
+  nz = -1;
+  for (j=0;j<rr->client_wait_list_length;j++)
+  {
+    if (NULL != rr->client_wait_list[j])
+    {
+      nz = (int) j;
+      break;
+    }
+  }  
+  if (-1 != nz) 
+  {
+    send_request_to_client (rr, rr->client_wait_list[nz]->client);
+    return;
+  }
+  /* done with current phase, advance! */
+  switch (rr->phase)
+  {
+  case RP_INIT:
+    rr->phase = RP_MONITOR;
+    for (cr = clients_head; NULL != cr; cr = cr->next)
+    {
+      if (0 != (cr->flags & GNUNET_DNS_FLAG_REQUEST_MONITOR))
+       GNUNET_array_append (rr->client_wait_list,
+                            rr->client_wait_list_length,
+                            cr);
+    }
+    next_phase (rr);
+    return;
+  case RP_MONITOR:
+    rr->phase = RP_QUERY;
+    for (cr = clients_head; NULL != cr; cr = cr->next)
+    {
+      if (0 != (cr->flags & GNUNET_DNS_FLAG_PRE_RESOLUTION))
+       GNUNET_array_append (rr->client_wait_list,
+                            rr->client_wait_list_length,
+                            cr);
+    }
+    next_phase (rr);
+    return;
+  case RP_QUERY:
+    rr->phase = RP_INTERNET_DNS;
+    switch (rr->dst_addr.ss_family)
+    {
+    case AF_INET:
+      dnsout = dnsout4;
+      salen = sizeof (struct ip4_hdr);
+      break;
+    case AF_INET6:
+      dnsout = dnsout6;
+      salen = sizeof (struct ip6_hdr);
+      break;
+    default:
+      GNUNET_break (0);
+      cleanup_rr (rr);
+      return;   
+    }
+    GNUNET_NETWORK_socket_sendto (dnsout,
+                                 rr->payload,
+                                 rr->payload_length,
+                                 (struct sockaddr*) &rr->dst_addr,
+                                 salen);
+    return;
+  case RP_INTERNET_DNS:
+    rr->phase = RP_MODIFY;
+    for (cr = clients_head; NULL != cr; cr = cr->next)
+    {
+      if (0 != (cr->flags & GNUNET_DNS_FLAG_POST_RESOLUTION))
+       GNUNET_array_append (rr->client_wait_list,
+                            rr->client_wait_list_length,
+                            cr);
+    }
+    next_phase (rr);
+    return;
+  case RP_MODIFY:
+    request_done (rr);
+    break;
+  case RP_DROP:
+    cleanup_rr (rr);
+    break;
+  default:
+    GNUNET_break (0);
+    cleanup_rr (rr);
+    break;
+  }
+}
+
+
+/**
  * A client disconnected, clean up after it.
  *
  * @param cls unused
@@ -517,7 +608,6 @@
   struct RequestRecord *rr;
   unsigned int i;
   unsigned int j;
-  int az;
 
   for (cr = clients_head; NULL != cr; cr = cr->next)
   {
@@ -532,16 +622,14 @@
        rr = &requests[i];
        if (0 == rr->client_wait_list_length)
          continue; /* not in use */
-       az = 1;
        for (j=0;j<rr->client_wait_list_length;j++)
        {
          if (rr->client_wait_list[j] == cr)
+         {
            rr->client_wait_list[j] = NULL;
-         if (rr->client_wait_list[j] != NULL)
-           az = 0;
+           next_phase (rr); 
+         }
        }
-       if (1 == az)
-         request_done (rr); /* this was the last client... */
       }
       GNUNET_free (cr);
       return;
@@ -564,7 +652,9 @@
   struct sockaddr_in addr4;
   struct sockaddr_in6 addr6;
   struct sockaddr *addr;
+  struct dns_hdr *dns;
   socklen_t addrlen;
+  struct RequestRecord *rr;
   ssize_t r;
   int len;
 
@@ -612,9 +702,26 @@
       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
       return;
     }
-    // NOTE: struct dns_pkt *dns = (struct dns_pkt *) buf;
-    // FIXME: handle_response (buf, r, addr, addrlen);
-  }
+    if (sizeof (struct dns_hdr) > r)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
+                 _("Received DNS response that is too small (%u bytes)"),
+                 r);
+      return;
+    }
+    dns = (struct dns_hdr *) buf;
+    rr = &requests[dns->id];
+    if (rr->phase != RP_INTERNET_DNS) 
+    {
+      /* FIXME: case for statistics */
+      /* unexpected / bogus reply */
+      return; 
+    }
+    GNUNET_free_non_null (rr->payload);
+    rr->payload = GNUNET_malloc (len);
+    memcpy (rr->payload, buf, len);
+    next_phase (rr);
+  }  
 }
 
 
@@ -744,16 +851,19 @@
 static void
 handle_client_init (void *cls GNUNET_UNUSED, 
                    struct GNUNET_SERVER_Client *client,
-                   const struct GNUNET_MessageHeader *message GNUNET_UNUSED)
+                   const struct GNUNET_MessageHeader *message)
 {
   struct ClientRecord *cr;
+  const struct GNUNET_DNS_Register *reg = (const struct GNUNET_DNS_Register*) 
message;
 
   cr = GNUNET_malloc (sizeof (struct ClientRecord));
   cr->client = client;
+  cr->flags = (enum GNUNET_DNS_Flags) ntohl (reg->flags);  
   GNUNET_SERVER_client_keep (client);
   GNUNET_CONTAINER_DLL_insert (clients_head,
                               clients_tail,
                               cr);
+  GNUNET_SERVER_notification_context_add (nc, client);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
@@ -768,10 +878,73 @@
 static void
 handle_client_response (void *cls GNUNET_UNUSED, 
                        struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message 
GNUNET_UNUSED)
+                       const struct GNUNET_MessageHeader *message)
 {
-  // FIXME: validate and parse response, process response
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  const struct GNUNET_DNS_Response *resp;
+  struct RequestRecord *rr;
+  unsigned int i;
+  uint16_t msize;
+  uint16_t off;
+
+  msize = ntohs (message->size);
+  if (msize < sizeof (struct GNUNET_DNS_Response))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  resp = (const struct GNUNET_DNS_Response*) message;
+  off = (uint16_t) resp->request_id;
+  rr = &requests[off];
+  if (rr->request_id != resp->request_id)
+  {
+    // FIXME: this is a case for calling statistics...
+    // (client is answering a request that we've lost
+    // track of -- more than 64k requests ago or so...)
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    return;
+  }
+  for (i=0;i<rr->client_wait_list_length;i++)
+  {
+    if (rr->client_wait_list[i]->client != client)
+      continue;
+    rr->client_wait_list[i] = NULL;
+    switch (ntohl (resp->drop_flag))
+    {
+    case 0: /* drop */
+      rr->phase = RP_DROP;
+      break;
+    case 1: /* no change */
+      break;
+    case 2: /* update */
+      msize -= sizeof (struct GNUNET_DNS_Response);
+      if ( (sizeof (struct dns_hdr) > msize) ||
+          (RP_MONITOR == rr->phase) )
+      {
+       GNUNET_break (0);
+       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+       next_phase (rr); 
+       return;
+      }
+      GNUNET_free_non_null (rr->payload);
+      rr->payload = GNUNET_malloc (msize);
+      memcpy (rr->payload, &resp[1], msize);
+      if (rr->phase == RP_QUERY)
+      {
+       /* clear wait list, we're moving to MODIFY phase next */
+       GNUNET_array_grow (rr->client_wait_list,
+                          rr->client_wait_list_length,
+                          0);
+      }
+      next_phase (rr); 
+      GNUNET_SERVER_receive_done (client, GNUNET_OK);
+      return;
+    }  
+  }
+  /* odd, client was not on our list for the request, that ought
+     to be an error */
+  GNUNET_break (0);
+  GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
 }
 
 
@@ -784,12 +957,14 @@
  * @param message the actual message, a DNS request we should handle
  */
 static void
-process_helper_messages (void *cls, void *client,
+process_helper_messages (void *cls GNUNET_UNUSED, void *client,
                         const struct GNUNET_MessageHeader *message)
 {
+  struct RequestRecord *rr = NULL;
   /* FIXME: parse message, create record, start processing! */
   /* FIXME: put request into queue for clients / system DNS */
   request_id_gen++;
+  next_phase (rr);
 }
 
 
@@ -804,7 +979,8 @@
 {
   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
     /* callback, cls, type, size */
-    {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, sizeof 
(struct GNUNET_MessageHeader)},
+    {&handle_client_init, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_INIT, 
+     sizeof (struct GNUNET_DNS_Register)},
     {&handle_client_response, NULL, GNUNET_MESSAGE_TYPE_DNS_CLIENT_RESPONSE, 
0},
     {NULL, NULL, 0, 0}
   };
@@ -816,6 +992,7 @@
   char *ipv6prefix;
 
   cfg = cfg_;
+  nc = GNUNET_SERVER_notification_context_create (server, 1);
   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
                                 cls);
   if (GNUNET_YES ==

Modified: gnunet/src/include/gnunet_dns_service-new.h
===================================================================
--- gnunet/src/include/gnunet_dns_service-new.h 2012-01-03 14:31:30 UTC (rev 
18957)
+++ gnunet/src/include/gnunet_dns_service-new.h 2012-01-03 20:30:07 UTC (rev 
18958)
@@ -40,7 +40,50 @@
  */
 struct GNUNET_DNS_RequestHandle;
 
+/**
+ * Flags that specify when to call the client's handler.
+ */ 
+enum GNUNET_DNS_Flags
+{
 
+  /**
+   * Useless option: never call the client.
+   */
+  GNUNET_DNS_FLAG_NEVER = 0,
+
+  /**
+   * Set this flag to see all requests first prior to resolution
+   * (for monitoring).  Clients that set this flag must then
+   * call "GNUNET_DNS_request_forward" when they process a request
+   * for the first time.  Caling "GNUNET_DNS_request_answer" is
+   * not allowed for MONITOR peers.
+   */
+  GNUNET_DNS_FLAG_REQUEST_MONITOR = 1,
+
+  /**
+   * This client should be called on requests that have not
+   * yet been resolved as this client provides a resolution
+   * service.  Note that this does not guarantee that the
+   * client will see all requests as another client might be
+   * called first and that client might have already done the
+   * resolution, in which case other pre-resolution clients
+   * won't see the request anymore.
+   */
+  GNUNET_DNS_FLAG_PRE_RESOLUTION = 2,
+
+  /**
+   * This client wants to be called on the results of a DNS resolution
+   * (either resolved by PRE-RESOLUTION clients or the global DNS).
+   * The client then has a chance to modify the answer (or cause it to
+   * be dropped).  There is no guarantee that other POST-RESOLUTION
+   * client's won't modify (or drop) the answer afterwards.
+   */
+  GNUNET_DNS_FLAG_POST_RESOLUTION = 4
+
+};
+
+
+
 /**
  * Signature of a function that is called whenever the DNS service
  * encounters a DNS request and needs to do something with it.  The
@@ -71,12 +114,9 @@
 
 
 /**
- * If a GNUNET_DNS_RequestHandler calls this function, the request is
- * given to other clients or the global DNS for resolution.  Once a
- * global response has been obtained, the request handler is AGAIN
- * called to give it a chance to observe and modify the response after
- * the "normal" resolution.  It is not legal for the request handler
- * to call this function if a response is already present.
+ * If a GNUNET_DNS_RequestHandler calls this function, the client
+ * has no desire to interfer with the request and it should
+ * continue to be processed normally.
  *
  * @param rh request that should now be forwarded
  */
@@ -97,7 +137,8 @@
 /**
  * If a GNUNET_DNS_RequestHandler calls this function, the request is
  * supposed to be answered with the data provided to this call (with
- * the modifications the function might have made).
+ * the modifications the function might have made).  The reply given
+ * must always be a valid DNS reply and not a mutated DNS request.
  *
  * @param rh request that should now be answered
  * @param reply_length size of reply (uint16_t to force sane size)
@@ -113,12 +154,14 @@
  * Connect to the service-dns
  *
  * @param cfg configuration to use
+ * @param flags when to call rh
  * @param rh function to call with DNS requests
  * @param rh_cls closure to pass to rh
  * @return DNS handle 
  */
 struct GNUNET_DNS_Handle *
 GNUNET_DNS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                   enum GNUNET_DNS_Flags flags,
                    GNUNET_DNS_RequestHandler rh,
                    void *rh_cls);
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]