};
/**
- * Message from client to GNS service to lookup records.
+ * Message from client to GNS service to shorten names.
*/
struct GNUNET_GNS_ClientShortenMessage
{
/* followed by the shortened name or '\0' for no result*/
+};
+
+/**
+ * Message from client to GNS service to lookup an authority of a name.
+ */
+struct GNUNET_GNS_ClientGetAuthMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* Followed by the name to get authority for */
+};
+
+
+/**
+ * Message from GNS service to client: authority result.
+ */
+struct GNUNET_GNS_ClientGetAuthResultMessage
+{
+ /**
+ * Header of type GNUNET_MESSAGE_TYPE_GNS_CLIENT_GET_AUTH_RESULT
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Unique identifier for this request (for key collisions).
+ */
+ uint32_t id GNUNET_PACKED;
+
+ /* followed by the authority part of the name or '\0' for no result*/
+
};
GNUNET_NETWORK_STRUCT_END
#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 24
#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN 25
#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH 27
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28
/**
* A QueueEntry.
/* processor to call on lookup result */
GNUNET_GNS_LookupResultProcessor lookup_proc;
+
+ /* processor to call on authority lookup result */
+ GNUNET_GNS_GetAuthResultProcessor auth_proc;
/* processor closure */
void *proc_cls;
*/
struct GNUNET_GNS_QueueEntry *lookup_tail;
+ /**
+ * Head of linked list of authority lookup messages we would like to transmit.
+ */
+ struct GNUNET_GNS_QueueEntry *get_auth_head;
+
+ /**
+ * Tail of linked list of authority lookup messages we would like to transmit.
+ */
+ struct GNUNET_GNS_QueueEntry *get_auth_tail;
+
/**
* Reconnect task
*/
}
+/**
+ * Process a given reply that might match the given
+ * request.
+ *
+ * @param qe the handle to the request
+ * @param msg the message to process
+ */
+static void
+process_get_auth_reply (struct GNUNET_GNS_QueueEntry *qe,
+ const struct GNUNET_GNS_ClientGetAuthResultMessage *msg)
+{
+ struct GNUNET_GNS_Handle *h = qe->gns_handle;
+ const char *auth_name;
+
+ GNUNET_CONTAINER_DLL_remove(h->get_auth_head, h->get_auth_tail, qe);
+
+ auth_name = (char*)(&msg[1]);
+
+ if (ntohs (((struct GNUNET_MessageHeader*)msg)->size) <
+ sizeof (struct GNUNET_GNS_ClientGetAuthResultMessage))
+ {
+ GNUNET_break (0);
+ force_reconnect (h);
+ return;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received GET_AUTH reply `%s' from GNS service\n",
+ auth_name);
+
+ qe->auth_proc(qe->proc_cls, auth_name);
+
+}
/**
* Process a given reply to the lookup request
*
struct GNUNET_GNS_QueueEntry *qe;
const struct GNUNET_GNS_ClientLookupResultMessage *lookup_msg;
const struct GNUNET_GNS_ClientShortenResultMessage *shorten_msg;
+ const struct GNUNET_GNS_ClientGetAuthResultMessage *get_auth_msg;
uint16_t size;
uint16_t type;
uint32_t r_id;
else if (type == GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got shorten msg\n");
+ "Got SHORTEN_RESULT msg\n");
shorten_msg = (struct GNUNET_GNS_ClientShortenResultMessage *) msg;
r_id = ntohl (shorten_msg->id);
if (qe)
process_shorten_reply(qe, shorten_msg);
}
+ else if (type == GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Got GET_AUTH_RESULT msg\n");
+ get_auth_msg = (struct GNUNET_GNS_ClientGetAuthResultMessage *) msg;
+
+ r_id = ntohl (get_auth_msg->id);
+
+ if (r_id > handle->r_id)
+ {
+ /** no request found */
+ GNUNET_break_op (0);
+ GNUNET_CLIENT_receive (handle->client, &process_message, handle,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ }
+
+ for (qe = handle->get_auth_head; qe != NULL; qe = qe->next)
+ {
+ if (qe->r_id == r_id)
+ break;
+ }
+ if (qe)
+ process_get_auth_reply(qe, get_auth_msg);
+ }
GNUNET_CLIENT_receive (handle->client, &process_message, handle,
GNUNET_TIME_UNIT_FOREVER_REL);
}
+/**
+ * Perform an authority lookup for a given name.
+ *
+ * @param handle handle to the GNS service
+ * @param name the name to look up authority for
+ * @param proc function to call on result
+ * @param proc_cls closure for processor
+ * @return handle to the operation
+ */
+struct GNUNET_GNS_QueueEntry *
+GNUNET_GNS_get_authority (struct GNUNET_GNS_Handle *handle,
+ const char * name,
+ GNUNET_GNS_GetAuthResultProcessor proc,
+ void *proc_cls)
+{
+ struct GNUNET_GNS_ClientGetAuthMessage *get_auth_msg;
+ struct GNUNET_GNS_QueueEntry *qe;
+ size_t msize;
+ struct PendingMessage *pending;
+
+ if (NULL == name)
+ {
+ return NULL;
+ }
+
+ msize = sizeof (struct GNUNET_GNS_ClientGetAuthMessage) + strlen(name) + 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to look up authority for %s in GNS\n", name);
+
+ qe = GNUNET_malloc(sizeof (struct GNUNET_GNS_QueueEntry));
+ qe->gns_handle = handle;
+ qe->shorten_proc = proc;
+ qe->proc_cls = proc_cls;
+ qe->r_id = get_request_id(handle);
+ GNUNET_CONTAINER_DLL_insert_tail(handle->get_auth_head,
+ handle->get_auth_tail, qe);
+
+ pending = GNUNET_malloc (sizeof (struct PendingMessage) + msize);
+ memset(pending, 0, (sizeof (struct PendingMessage) + msize));
+
+ pending->size = msize;
+
+ get_auth_msg = (struct GNUNET_GNS_ClientGetAuthMessage *) &pending[1];
+ get_auth_msg->header.type = htons (GNUNET_MESSAGE_TYPE_GNS_GET_AUTH);
+ get_auth_msg->header.size = htons (msize);
+ get_auth_msg->id = htonl(qe->r_id);
+
+ memcpy(&get_auth_msg[1], name, strlen(name));
+
+ GNUNET_CONTAINER_DLL_insert (handle->pending_head, handle->pending_tail,
+ pending);
+
+ process_pending_messages (handle);
+ return qe;
+}
+
/* end of gns_api.c */
#define DHT_GNS_REPLICATION_LEVEL 5
#define MAX_DNS_LABEL_LENGTH 63
-/* Ignore for now not used anyway and probably never will */
+/* FIXME move to proper header in include */
#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP 23
#define GNUNET_MESSAGE_TYPE_GNS_LOOKUP_RESULT 24
#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN 25
#define GNUNET_MESSAGE_TYPE_GNS_SHORTEN_RESULT 26
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH 27
+#define GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT 28
struct AuthorityChain
};
+
+/**
+ * Handle to a get auhtority operation from api
+ */
+struct ClientGetAuthHandle
+{
+ /* the requesting client that */
+ struct GNUNET_SERVER_Client *client;
+
+ /* request id */
+ uint64_t unique_id;
+
+ /* name to lookup authority */
+ char* name;
+
+};
+
+
/**
* Handle to a lookup operation from api
*/
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
"Our zone: Sending name as shorten result %s\n", rh->name);
- send_shorten_response(rh->name, csh); //FIXME +.gnunet!
+ send_shorten_response(result, csh); //FIXME +.gnunet!
free_resolver_handle(rh);
- GNUNET_free(csh->name);
- GNUNET_free(csh);
GNUNET_free(result);
return;
}
csh->name = GNUNET_malloc(strlen(name)
- strlen(gnunet_tld) + 1);
- memset(rh->name, 0,
+ memset(csh->name, 0,
strlen(name)-strlen(gnunet_tld) + 1);
- memcpy(rh->name, name,
+ memcpy(csh->name, name,
strlen(name)-strlen(gnunet_tld));
rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
}
+
+/**
+ * Send get authority response back to client
+ *
+ * @param name the shortened name result or NULL if cannot be shortened
+ * @param cah the handle to the get authority request
+ */
+static void
+send_get_auth_response(const char* name, struct ClientGetAuthHandle *cah)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message with %s\n",
+ "GET_AUTH_RESULT", name);
+ struct GNUNET_GNS_ClientGetAuthResultMessage *rmsg;
+
+ if (name == NULL)
+ {
+ name = "";
+ }
+
+ rmsg = GNUNET_malloc(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage)
+ + strlen(name) + 1);
+
+ rmsg->id = cah->unique_id;
+ rmsg->header.type = htons(GNUNET_MESSAGE_TYPE_GNS_GET_AUTH_RESULT);
+ rmsg->header.size =
+ htons(sizeof(struct GNUNET_GNS_ClientGetAuthResultMessage) +
+ strlen(name) + 1);
+
+ strcpy((char*)&rmsg[1], name);
+
+ GNUNET_SERVER_notification_context_unicast (nc, cah->client,
+ (const struct GNUNET_MessageHeader *) rmsg,
+ GNUNET_NO);
+ GNUNET_SERVER_receive_done (cah->client, GNUNET_OK);
+
+ GNUNET_free(rmsg);
+ GNUNET_free(cah->name);
+ GNUNET_free(cah);
+
+}
+
+/**
+ * Process result from namestore delegation lookup
+ * for get authority operation
+ *
+ * @param cls the client get auth handle
+ * @param rh the resolver handle
+ * @param rd_count number of results (0)
+ * @param rd data (NULL)
+ */
+void
+handle_get_auth_delegation_result(void* cls,
+ struct GNUNET_GNS_ResolverHandle *rh,
+ uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ struct ClientGetAuthHandle* cah = (struct ClientGetAuthHandle*) cls;
+ struct AuthorityChain *auth_chain;
+ char* result;
+ size_t answer_len;
+
+ /**
+ * At this point rh->name contains the part of the name
+ * that we do not have a PKEY in our namestore to resolve.
+ * The authority chain in the resolver handle is now
+ * useful to backtrack if needed
+ */
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "PKEY resolved as far as possible in ns up to %s!\n", rh->name);
+
+ if (is_canonical(rh->name))
+ {
+ /**
+ * We successfully resolved the authority in the ns
+ * FIXME for our purposes this is fine
+ * but maybe we want to have an api that also looks
+ * into the dht (i.e. option in message)
+ **/
+ if (strlen(rh->name) > strlen(cah->name))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Record name longer than original lookup name... odd!\n");
+ //FIXME to sth here
+ }
+
+
+ answer_len = strlen(cah->name) - strlen(rh->name);
+ result = GNUNET_malloc(answer_len);
+ memset(result, 0, answer_len);
+ strcpy(result, cah->name + strlen(rh->name) + 1);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Our zone: Sending authority result %s\n", result);
+
+ send_get_auth_response(result, cah);
+ free_resolver_handle(rh);
+ GNUNET_free(result);
+ return;
+ }
+
+ auth_chain = rh->authority_chain_head;
+ /* backtrack authorities for pseu */
+ GNUNET_NAMESTORE_zone_to_name (namestore_handle,
+ &zone_hash, //ours
+ &auth_chain->zone,
+ &handle_shorten_zone_to_name,
+ rh);
+
+}
+
+
+/**
+ * Get authority for a given name
+ *
+ * @param name the name to shorten
+ * @param csh the shorten handle of the request
+ */
+static void
+get_authority(char* name, struct ClientGetAuthHandle* cah)
+{
+
+ struct GNUNET_GNS_ResolverHandle *rh;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting authority resolution for %s (type=%d)!\n",
+ name, GNUNET_GNS_RECORD_PKEY);
+
+ rh = GNUNET_malloc(sizeof (struct GNUNET_GNS_ResolverHandle));
+ rh->authority = zone_hash;
+
+ rh->name = GNUNET_malloc(strlen(name)
+ - strlen(gnunet_tld) + 1);
+ memset(rh->name, 0,
+ strlen(name)-strlen(gnunet_tld) + 1);
+ memcpy(rh->name, name,
+ strlen(name)-strlen(gnunet_tld));
+
+ cah->name = GNUNET_malloc(strlen(name)
+ - strlen(gnunet_tld) + 1);
+ memset(cah->name, 0,
+ strlen(name)-strlen(gnunet_tld) + 1);
+ memcpy(cah->name, name,
+ strlen(name)-strlen(gnunet_tld));
+
+ rh->authority_name = GNUNET_malloc(sizeof(char)*MAX_DNS_LABEL_LENGTH);
+
+ rh->authority_chain_head = GNUNET_malloc(sizeof(struct AuthorityChain));
+ rh->authority_chain_tail = rh->authority_chain_head;
+ rh->authority_chain_head->zone = zone_hash;
+ rh->proc = &handle_get_auth_delegation_result;
+ rh->proc_cls = (void*)cah;
+
+ /* Start delegation resolution in our namestore */
+ resolve_delegation_ns(rh);
+
+}
+
+
+/**
+ * Handle a get authority message from the api
+ *
+ * @param cls the closure
+ * @param client the client
+ * @param message the message
+ */
+static void handle_get_authority(void *cls,
+ struct GNUNET_SERVER_Client * client,
+ const struct GNUNET_MessageHeader * message)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "GET_AUTH");
+
+ size_t msg_size = 0;
+ struct ClientGetAuthHandle *cah;
+
+ if (ntohs (message->size) < sizeof (struct GNUNET_GNS_ClientGetAuthMessage))
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+
+ GNUNET_SERVER_notification_context_add (nc, client);
+
+ struct GNUNET_GNS_ClientGetAuthMessage *sh_msg =
+ (struct GNUNET_GNS_ClientGetAuthMessage *) message;
+
+ msg_size = ntohs(message->size);
+
+ if (msg_size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+
+ cah = GNUNET_malloc(sizeof(struct ClientGetAuthHandle));
+ cah->client = client;
+ cah->unique_id = sh_msg->id;
+
+ get_authority((char*)&sh_msg[1], cah);
+
+}
+
+
/**
* Reply to client with the result from our lookup.
*
lookup_name((char*)&sh_msg[1], clh);
}
+
+
/**
* Process GNS requests.
*
static const struct GNUNET_SERVER_MessageHandler handlers[] = {
{&handle_shorten, NULL, GNUNET_MESSAGE_TYPE_GNS_SHORTEN, 0},
- {&handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0}
+ {&handle_lookup, NULL, GNUNET_MESSAGE_TYPE_GNS_LOOKUP, 0},
+ {&handle_get_authority, NULL, GNUNET_MESSAGE_TYPE_GNS_GET_AUTH, 0}
};
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (c, "gns",
uint32_t rd_count;
char* rd_data = NULL;
int rd_len;
+ uint32_t record_xquery;
unsigned int record_match;
if (type != GNUNET_BLOCK_TYPE_GNS_NAMERECORD)
{
struct GNUNET_NAMESTORE_RecordData rd[rd_count];
unsigned int i;
- uint32_t record_xquery = ntohl(*((uint32_t*)xquery));
+ struct GNUNET_TIME_Absolute exp = GNUNET_TIME_absolute_get_forever();
if (GNUNET_SYSERR == GNUNET_NAMESTORE_records_deserialize (rd_len,
rd_data,
"Data invalid (%d bytes, %d records)\n", rd_len, rd_count);
return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
}
+
+ if (xquery_size < sizeof(uint32_t))
+ record_xquery = 0;
+ else
+ record_xquery = ntohl(*((uint32_t*)xquery));
for (i=0; i<rd_count; i++)
{
- if (xquery_size < sizeof(uint32_t))
- continue;
- if (rd[i].record_type == record_xquery)
+ exp = GNUNET_TIME_absolute_min (exp, rd[i].expiration);
+
+ if ((record_xquery != 0)
+ && (rd[i].record_type == record_xquery))
+ {
record_match++;
+ }
}
if (GNUNET_OK != GNUNET_NAMESTORE_verify_signature (&nrb->public_key,
- GNUNET_TIME_absolute_get_forever(),
+ exp,
name,
rd_count,
rd,
}
//No record matches query
- if ((xquery_size > 0) && (record_match == 0))
+ if ((record_xquery != 0) && (record_match == 0))
return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Records match\n");
* called only once
*
* @param cls closure
- * @param name "name" of the original lookup
* @param short_name the shortened name or NULL if no result
*/
typedef void (*GNUNET_GNS_ShortenResultProcessor) (void *cls,
* @param handle handle to the GNS service
* @param name the name to shorten
* @param proc processor to call on result
- * @param iter_cls closure for processor
+ * @param cls closure for processor
*
* @return handle to the shorten operation
*/
GNUNET_GNS_shorten (struct GNUNET_GNS_Handle *handle,
const char * name,
GNUNET_GNS_ShortenResultProcessor proc,
- void *iter_cls);
+ void *cls);
+
+
+/* *************** Standard API: get authority ******************* */
+
+
+/**
+ * Processor called on for a name shortening result
+ * called only once
+ *
+ * @param cls closure
+ * @param auth_name the name of the auhtority or NULL
+ */
+typedef void (*GNUNET_GNS_GetAuthResultProcessor) (void *cls,
+ const char* short_name);
+
+
+/**
+ * Perform a shorten operation on name using the GNS.
+ *
+ * @param handle handle to the GNS service
+ * @param name the name to look up authority for
+ * @param proc processor to call on result
+ * @param cls closure for processor
+ *
+ * @return handle to the get authority operation
+ */
+struct GNUNET_GNS_QueueEntry *
+GNUNET_GNS_get_authority (struct GNUNET_GNS_Handle *handle,
+ const char * name,
+ GNUNET_GNS_GetAuthResultProcessor proc,
+ void *cls);
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif