[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r15952 - gnunet/src/nse
From: |
gnunet |
Subject: |
[GNUnet-SVN] r15952 - gnunet/src/nse |
Date: |
Thu, 14 Jul 2011 12:51:11 +0200 |
Author: nevans
Date: 2011-07-14 12:51:11 +0200 (Thu, 14 Jul 2011)
New Revision: 15952
Modified:
gnunet/src/nse/Makefile.am
gnunet/src/nse/gnunet-service-nse.c
gnunet/src/nse/nse.h
Log:
nse changes
Modified: gnunet/src/nse/Makefile.am
===================================================================
--- gnunet/src/nse/Makefile.am 2011-07-14 09:16:58 UTC (rev 15951)
+++ gnunet/src/nse/Makefile.am 2011-07-14 10:51:11 UTC (rev 15952)
@@ -40,6 +40,7 @@
$(top_builddir)/src/nse/libgnunetnse.la \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/core/libgnunetcore.la \
+ -lm \
$(GN_LIBINTL)
gnunet_service_nse_DEPENDENCIES = \
libgnunetnse.la
Modified: gnunet/src/nse/gnunet-service-nse.c
===================================================================
--- gnunet/src/nse/gnunet-service-nse.c 2011-07-14 09:16:58 UTC (rev 15951)
+++ gnunet/src/nse/gnunet-service-nse.c 2011-07-14 10:51:11 UTC (rev 15952)
@@ -41,6 +41,7 @@
#include "gnunet_constants.h"
#include "gnunet_container_lib.h"
#include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
#include "gnunet_service_lib.h"
#include "gnunet_server_lib.h"
#include "gnunet_core_service.h"
@@ -52,7 +53,7 @@
#define DEFAULT_CORE_QUEUE_SIZE 32
-#define MILLISECONDS_PER_DAY 86400000
+#define DEFAULT_NSE_PRIORITY 0
/**
* Entry in the list of clients which
@@ -78,6 +79,37 @@
};
/**
+ * Per-peer information.
+ */
+struct NSEPeerEntry
+{
+ /**
+ * Next peer entry (DLL)
+ */
+ struct NSEPeerEntry *next;
+
+ /**
+ * Prev peer entry (DLL)
+ */
+ struct NSEPeerEntry *prev;
+
+ /**
+ * Pending message for this peer.
+ */
+ struct GNUNET_MessageHeader *pending_message;
+
+ /**
+ * Core handle for sending messages to this peer.
+ */
+ struct GNUNET_CORE_TransmitHandle *th;
+
+ /**
+ * What is the identity of the peer?
+ */
+ struct GNUNET_PeerIdentity id;
+};
+
+/**
* Handle to our current configuration.
*/
static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -85,16 +117,21 @@
/**
* Handle to the core service.
*/
-struct GNUNET_CORE_Handle *coreAPI;
+static struct GNUNET_CORE_Handle *coreAPI;
/**
- * Copy of this peer's identity.
+ * Head of global list of peers.
*/
-static struct GNUNET_PeerIdentity my_identity;
+static struct NSEPeerEntry *peers_head;
/**
* Head of global list of clients.
*/
+static struct NSEPeerEntry *peers_tail;
+
+/**
+ * Head of global list of clients.
+ */
static struct ClientListEntry *cle_head;
/**
@@ -104,6 +141,8 @@
/**
* The current network size estimate.
+ * Number of bits matching on average
+ * thus far.
*/
static double current_size_estimate;
@@ -115,16 +154,31 @@
/**
* Array of the last DEFAULT_HISTORY_SIZE
- * network size estimates.
+ * network size estimates (matching bits, actually).
*/
-//static double *size_estimates[DEFAULT_HISTORY_SIZE];
+static unsigned int size_estimates[DEFAULT_HISTORY_SIZE];
/**
+ * Array of size estimate messages.
+ */
+static struct GNUNET_NSE_FloodMessage
size_estimate_messages[DEFAULT_HISTORY_SIZE];
+
+/**
+ * Index of most recent estimate.
+ */
+static unsigned int estimate_index;
+
+/**
* Task scheduled to send flood message.
*/
static GNUNET_SCHEDULER_TaskIdentifier flood_task;
/**
+ * Task to schedule flood message and update state.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier schedule_flood_task;
+
+/**
* Notification context, simplifies client broadcasts.
*/
static struct GNUNET_SERVER_NotificationContext *nc;
@@ -132,7 +186,7 @@
/**
* The previous major time.
*/
-struct GNUNET_TIME_Absolute previous_timestamp;
+static struct GNUNET_TIME_Absolute previous_timestamp;
/**
* The next major time.
@@ -150,6 +204,26 @@
static struct GNUNET_NSE_ClientMessage current_estimate_message;
/**
+ * The public key of this peer.
+ */
+static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
+
+/**
+ * The private key of this peer.
+ */
+static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
+
+/**
+ * The peer identity of this peer.
+ */
+static struct GNUNET_PeerIdentity my_identity;
+
+/**
+ * Our flood message, updated whenever a flood is sent.
+ */
+static struct GNUNET_NSE_FloodMessage flood_message;
+
+/**
* Handler for START message from client, triggers an
* immediate current network estimate notification.
* Also, we remember the client for updates upon future
@@ -172,46 +246,276 @@
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "NSE", "Received START message
from client\n");
#endif
GNUNET_SERVER_notification_context_add (nc, client);
- GNUNET_SERVER_notification_context_unicast (nc, client,
- ¤t_estimate_message.header,
- GNUNET_NO);
GNUNET_SERVER_receive_done(client, GNUNET_OK);
}
+
/**
+ * Called when core is ready to send a message we asked for
+ * out to the destination.
+ *
+ * @param cls closure (NULL)
+ * @param size number of bytes available in buf
+ * @param buf where the callee should write the message
+ * @return number of bytes written to buf
+ */
+static size_t
+transmit_ready (void *cls, size_t size, void *buf)
+{
+ struct NSEPeerEntry *peer_entry = cls;
+ char *cbuf = buf;
+
+ size_t msize;
+ peer_entry->th = NULL;
+ if (buf == NULL) /* client disconnected */
+ return 0;
+
+ if (peer_entry->pending_message == NULL)
+ return 0;
+
+ msize = ntohs(peer_entry->pending_message->size);
+ if (msize <= size)
+ memcpy(cbuf, peer_entry->pending_message, msize);
+
+ return msize;
+}
+
+/**
+ * We sent on our flood message or one that we received
+ * which was validated and closer than ours. Update the
+ * global list of recent messages and the average. Also
+ * re-broadcast the message to any clients.
+ *
+ * @param message the network flood message
+ */
+static void update_network_size_estimate(struct GNUNET_NSE_FloodMessage
*message)
+{
+ unsigned int i;
+ unsigned int count;
+ double average;
+
+ size_estimates[estimate_index] = htons(message->distance);
+ memcpy(&size_estimate_messages[estimate_index], message, sizeof(struct
GNUNET_NSE_FloodMessage));
+
+ count = 0;
+ for (i = 0; i < DEFAULT_HISTORY_SIZE; i++)
+ {
+ if (size_estimate_messages[i].distance != 0)
+ {
+ average += 1 << htons(size_estimate_messages[i].distance);
+ count++;
+ }
+ }
+ average /= (double)count;
+ current_estimate_message.size_estimate = average;
+ /* Finally, broadcast the current estimate to all clients */
+ GNUNET_SERVER_notification_context_broadcast (nc,
+
¤t_estimate_message.header,
+ GNUNET_NO);
+}
+
+static void
+send_flood_message (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext * tc);
+
+/**
+ * Schedule a flood message to be sent.
+ *
+ * @param cls unused
+ * @param tc context for this message
+ *
+ * This should be called on startup,
+ * when a valid flood message is received (and
+ * the next send flood message hasn't been
+ * scheduled yet) and when this peer sends
+ * a valid flood message. As such, there should
+ * always be a message scheduled to be sent.
+ */
+static void
+schedule_flood_message (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_HashCode timestamp_hash;
+ struct GNUNET_TIME_Absolute curr_time;
+ struct GNUNET_TIME_Relative offset;
+ struct GNUNET_CRYPTO_RsaSignaturePurpose purpose;
+ unsigned int matching_bits;
+ double millisecond_offset;
+
+ schedule_flood_task = GNUNET_SCHEDULER_NO_TASK;
+ if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+ return;
+
+ GNUNET_assert(flood_task == GNUNET_SCHEDULER_NO_TASK);
+
+ if (0 != GNUNET_TIME_absolute_get_remaining(next_timestamp).rel_value)
+ {
+ GNUNET_break(0); /* Shouldn't ever happen! */
+ schedule_flood_task = GNUNET_SCHEDULER_add_delayed
(GNUNET_TIME_absolute_get_remaining(next_timestamp), &schedule_flood_message,
NULL);
+ }
+
+ /* Get the current UTC time */
+ curr_time = GNUNET_TIME_absolute_get();
+ /* Find the previous interval start time */
+ previous_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) *
GNUNET_NSE_INTERVAL;
+ /* Find the next interval start time */
+ next_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) *
(GNUNET_NSE_INTERVAL + 1);
+
+ GNUNET_CRYPTO_hash(&next_timestamp.abs_value, sizeof(uint64_t),
×tamp_hash);
+ matching_bits = GNUNET_CRYPTO_hash_matching_bits(×tamp_hash,
&my_identity.hashPubKey);
+
+ flood_message.timestamp = GNUNET_TIME_absolute_hton(next_timestamp);
+ flood_message.distance = htons(matching_bits);
+ flood_message.enc_type = htons(0);
+ flood_message.proof_of_work = htonl(0);
+ purpose.purpose = GNUNET_SIGNATURE_PURPOSE_NSE_SEND;
+ purpose.size = sizeof(struct GNUNET_NSE_FloodMessage) - sizeof(struct
GNUNET_MessageHeader) - sizeof(flood_message.proof_of_work) -
sizeof(flood_message.signature);
+ GNUNET_CRYPTO_rsa_sign(my_private_key, &purpose, &flood_message.signature);
+
+ /*S + f/2 - (f / pi) * (atan(x - p'))*/
+
+ // S is next_timestamp
+ // f is frequency (GNUNET_NSE_INTERVAL)
+ // x is matching_bits
+ // p' is current_size_estimate
+ millisecond_offset = ((double)GNUNET_NSE_INTERVAL / (double)2) -
((GNUNET_NSE_INTERVAL / M_PI) * atan(matching_bits - current_size_estimate));
+
+ fprintf(stderr, "my id matches %d bits, offset is %lu\n", matching_bits,
(uint64_t)millisecond_offset);
+
+ estimate_index += 1;
+
+ if (estimate_index >= DEFAULT_HISTORY_SIZE)
+ estimate_index = 0;
+
+ offset.rel_value = (uint64_t)millisecond_offset +
GNUNET_TIME_absolute_get_remaining (next_timestamp).rel_value;
+ flood_task = GNUNET_SCHEDULER_add_delayed (offset,
+ &send_flood_message, NULL);
+
+}
+
+/**
* Core handler for size estimate flooding messages.
*
- * @param cls closure
+ * @param cls closure unused
* @param message message
- * @param peer peer identity this notification is about
- * @param atsi performance data
+ * @param peer peer identity this message is from (ignored)
+ * @param atsi performance data (ignored)
*
*/
static int
-handle_p2p_size_estimate (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_MessageHeader *message,
- const struct GNUNET_TRANSPORT_ATS_Information
- *atsi)
+handle_p2p_size_estimate(void *cls, const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_TRANSPORT_ATS_Information *atsi)
{
+ struct GNUNET_NSE_FloodMessage *incoming_flood;
+ if (ntohs(message->size) != sizeof(struct GNUNET_NSE_FloodMessage))
+ return GNUNET_NO;
+
+ incoming_flood = (struct GNUNET_NSE_FloodMessage *)message;
+ if (ntohs(incoming_flood->distance) <=
ntohs(size_estimate_messages[estimate_index].distance)) /* Not closer than our
most recent message */
+ return GNUNET_OK;
+
+ /* Have a new, better size estimate! */
+ update_network_size_estimate(incoming_flood);
+
+ if (schedule_flood_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel(schedule_flood_task);
+ schedule_flood_task = GNUNET_SCHEDULER_add_delayed
(GNUNET_TIME_absolute_get_remaining(next_timestamp), &schedule_flood_message,
NULL);
+
return GNUNET_OK;
}
-
/**
- * Send a flood message containing our peer's public key
- * and the hashed current timestamp.
+ * Send a flood message.
+ *
+ * If we've gotten here, it means we haven't received
+ * a network size estimate message closer than ours.
*/
static void
send_flood_message (void *cls,
const struct GNUNET_SCHEDULER_TaskContext * tc)
{
+ struct NSEPeerEntry *peer_entry;
+
+ flood_task = GNUNET_SCHEDULER_NO_TASK;
if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
return;
+
+ peer_entry = peers_head;
+
+ while (peer_entry != NULL)
+ {
+ peer_entry->th
+ = GNUNET_CORE_notify_transmit_ready (coreAPI,
+ GNUNET_YES,
+ DEFAULT_NSE_PRIORITY,
+
GNUNET_TIME_absolute_get_remaining (
+
next_timestamp),
+ &peer_entry->id,
+ ntohs
(flood_message.header.size),
+ &transmit_ready, peer_entry);
+ peer_entry = peer_entry->next;
+ }
+
+ update_network_size_estimate(&flood_message);
+ if (schedule_flood_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel(schedule_flood_task);
+ schedule_flood_task = GNUNET_SCHEDULER_add_delayed
(GNUNET_TIME_absolute_get_remaining(next_timestamp), &schedule_flood_message,
NULL);
}
/**
+ * Method called whenever a peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ * @param atsi performance data
+ */
+static void
+handle_core_connect (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+ struct NSEPeerEntry *peer_entry;
+
+ peer_entry = GNUNET_malloc(sizeof(struct NSEPeerEntry));
+ memcpy(&peer_entry->id, peer, sizeof(struct GNUNET_PeerIdentity));
+ GNUNET_CONTAINER_DLL_insert(peers_head, peers_tail, peer_entry);
+}
+
+
+/**
+ * Method called whenever a peer disconnects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ */
+static void
+handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
+{
+ struct NSEPeerEntry *pos;
+
+ pos = peers_head;
+ while ((NULL != pos) && (0 != memcmp(&pos->id, peer, sizeof(struct
GNUNET_PeerIdentity))))
+ pos = pos->next;
+ if (pos == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received disconnect before
connect!\n");
+ GNUNET_break(0); /* Should never receive a disconnect message for a peer
we don't know about... */
+ return;
+ }
+
+ if (pos->pending_message != NULL)
+ GNUNET_free(pos->pending_message);
+
+ if (pos->th != NULL)
+ GNUNET_CORE_notify_transmit_ready_cancel(pos->th);
+ GNUNET_CONTAINER_DLL_remove(peers_head, peers_tail, pos);
+ GNUNET_free(pos);
+}
+
+
+/**
* A client disconnected. Remove it from the
* global DLL of clients.
*
@@ -254,6 +558,8 @@
{
struct ClientListEntry *cle;
+ if (flood_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel(flood_task);
GNUNET_SERVER_notification_context_destroy (nc);
nc = NULL;
while (NULL != (cle = cle_head))
@@ -275,40 +581,6 @@
/**
- * Task to schedule a flood message to be sent.
- *
- * @param cls closure
- * @param tc context information (why was this task triggered now)
- */
-static void schedule_flood_message (void *cls,
- const struct
- GNUNET_SCHEDULER_TaskContext * tc)
-{
- GNUNET_HashCode timestamp_hash;
- struct GNUNET_TIME_Absolute curr_time;
- unsigned int matching_bits;
-
- /* Get the current UTC time */
- curr_time = GNUNET_TIME_absolute_get();
- /* Find the previous interval start time */
- previous_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) *
GNUNET_NSE_INTERVAL;
- /* Find the next interval start time */
- next_timestamp.abs_value = (curr_time.abs_value / GNUNET_NSE_INTERVAL) *
(GNUNET_NSE_INTERVAL + 1);
-
- GNUNET_CRYPTO_hash(&next_timestamp.abs_value, sizeof(uint64_t),
×tamp_hash);
- matching_bits = GNUNET_CRYPTO_hash_matching_bits(×tamp_hash,
&my_identity.hashPubKey);
-
- GNUNET_SCHEDULER_add_delayed (
- GNUNET_TIME_relative_add (
-
GNUNET_TIME_relative_multiply (
-
increment,
-
matching_bits),
-
GNUNET_TIME_absolute_get_remaining (
-
next_timestamp)),
- &send_flood_message, NULL);
-}
-
-/**
* Called on core init/fail.
*
* @param cls service closure
@@ -340,8 +612,21 @@
/* Copy our identity so we can use it */
memcpy (&my_identity, identity, sizeof (struct GNUNET_PeerIdentity));
+ /* Copy our public key for inclusion in flood messages */
+ memcpy (&my_public_key, publicKey, sizeof(struct
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- flood_task = GNUNET_SCHEDULER_add_now(&schedule_flood_message, NULL);
+ flood_message.header.size = htons(sizeof(struct GNUNET_NSE_FloodMessage));
+ flood_message.header.type = htons(GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD);
+ memcpy(&flood_message.pkey, &my_public_key, sizeof(struct
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+
+ if (flood_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel(flood_task);
+
+ schedule_flood_task = GNUNET_SCHEDULER_add_now(&schedule_flood_message,
NULL);
+
+ GNUNET_SERVER_notification_context_broadcast (nc,
+
¤t_estimate_message.header,
+ GNUNET_NO);
}
/**
@@ -356,6 +641,7 @@
struct GNUNET_SERVER_Handle *server,
const struct GNUNET_CONFIGURATION_Handle *c)
{
+ char *keyfile;
static const struct GNUNET_SERVER_MessageHandler handlers[] = {
{&handle_start_message, NULL, GNUNET_MESSAGE_TYPE_NSE_START, 0},
{NULL, NULL, 0, 0}
@@ -367,19 +653,43 @@
};
cfg = c;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (c,
+ "GNUNETD",
+ "HOSTKEY", &keyfile))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _
+ ("NSE service is lacking key configuration settings.
Exiting.\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+ GNUNET_free (keyfile);
+ if (my_private_key == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("NSE Service could not access hostkey. Exiting.\n"));
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
GNUNET_SERVER_add_handlers (server, handlers);
nc = GNUNET_SERVER_notification_context_create (server, 16);
GNUNET_SERVER_disconnect_notify (server,
&handle_client_disconnect,
NULL);
+ flood_task = GNUNET_SCHEDULER_NO_TASK;
/** Connect to core service and register core handlers */
coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */
DEFAULT_CORE_QUEUE_SIZE, /* queue size
*/
NULL, /* Closure passed to functions */
&core_init, /* Call core_init once
connected */
- NULL, /* Handle connects */
- NULL, /* Handle disconnects */
+ &handle_core_connect, /* Handle connects */
+ &handle_core_disconnect, /* Handle
disconnects */
NULL, /* Do we care about "status" updates?
*/
NULL, /* Don't want notified about all
incoming messages */
GNUNET_NO, /* For header only inbound
notification */
@@ -399,9 +709,9 @@
/ (sizeof(GNUNET_HashCode)
* 8));
/* Set we have no idea defaults for network size estimate */
- current_size_estimate = NAN;
+ current_size_estimate = 0.0;
current_std_dev = NAN;
-
+ size_estimates[estimate_index] = 0;
current_estimate_message.header.size = htons(sizeof(struct
GNUNET_NSE_ClientMessage));
current_estimate_message.header.type =
htons(GNUNET_MESSAGE_TYPE_NSE_ESTIMATE);
current_estimate_message.size_estimate = current_size_estimate;
Modified: gnunet/src/nse/nse.h
===================================================================
--- gnunet/src/nse/nse.h 2011-07-14 09:16:58 UTC (rev 15951)
+++ gnunet/src/nse/nse.h 2011-07-14 10:51:11 UTC (rev 15952)
@@ -32,15 +32,7 @@
#define DEBUG_NSE GNUNET_YES
-#define SIGNED_TIMESTAMP_SIZE sizeof(struct GNUNET_TIME_Absolute)
-/** FIXME: define NSE message types here. */
-
-struct GNUNET_Signed_Timestamp
-{
- char data[SIGNED_TIMESTAMP_SIZE];
-};
-
/**
* Network size estimate sent from the service
* to clients. Contains the current size estimate
@@ -95,25 +87,45 @@
* doesn't allow us to verify that the
* public/private key pair were generated, right?
*/
-struct GNUNET_NSE_ReplyMessage
+struct GNUNET_NSE_FloodMessage
{
/**
- * Type: GNUNET_MESSAGE_TYPE_NSE_REPLY
+ * Type: GNUNET_MESSAGE_TYPE_NSE_P2P_FLOOD
*/
struct GNUNET_MessageHeader header;
/**
+ * Magic header code(?)
+ */
+ uint16_t enc_type;
+
+ /**
+ * Number of matching bits between the hash
+ * of timestamp and the initiator's public
+ * key.
+ */
+ uint16_t distance;
+
+ /**
* The current timestamp value (which all
- * peers should agree on) signed by the
- * private key of the initiating peer.
+ * peers should agree on).
*/
- struct GNUNET_Signed_Timestamp timestamp;
+ struct GNUNET_TIME_AbsoluteNBO timestamp;
/**
- * Public key of the originator, signed timestamp
- * is decrypted by this.
+ * Public key of the originator.
*/
struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
+
+ /**
+ * FIXME: use, document.
+ */
+ uint32_t proof_of_work;
+
+ /**
+ * FIXME: use, document.
+ */
+ struct GNUNET_CRYPTO_RsaSignature signature;
};
#endif
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r15952 - gnunet/src/nse,
gnunet <=