libgnunetcore.la
libgnunetcore_la_SOURCES = \
- core_api.c core.h
+ core_api.c core.h \
+ core_api_iterate_peers.c
libgnunetcore_la_LIBADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(GN_LIBINTL) $(XLIB)
if (NULL == pr)
{
/* attempt to send to peer that is not connected */
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
+ "Attempting to send to peer `%s' from peer `%s', but not connected!\n",
+ GNUNET_i2s(target), GNUNET_h2s(&handle->me.hashPubKey));
GNUNET_break (0);
return NULL;
}
}
+#if NEW
/* ********************* GNUNET_CORE_iterate_peers *********************** */
/**
&ic);
return GNUNET_OK;
}
-
+#endif
/* end of core_api.c */
--- /dev/null
+/*
+ This file is part of GNUnet.
+ (C) 2009, 2010 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file core/core_api_iterate_peers.c
+ * @brief implementation of the peer_iterate function
+ * @author Christian Grothoff
+ * @author Nathan Evans
+ */
+#include "platform.h"
+#include "gnunet_core_service.h"
+#include "core.h"
+
+
+struct GNUNET_CORE_RequestContext
+{
+
+ /**
+ * Our connection to the service.
+ */
+ struct GNUNET_CLIENT_Connection *client;
+
+ /**
+ * Handle for transmitting a request.
+ */
+ struct GNUNET_CLIENT_TransmitHandle *th;
+
+ /**
+ * Function called with the peer.
+ */
+ GNUNET_CORE_ConnectEventHandler peer_cb;
+
+ /**
+ * Closure for peer_cb.
+ */
+ void *cb_cls;
+
+};
+
+
+/**
+ * Receive reply from core service with information about a peer.
+ *
+ * @param cls our 'struct GNUNET_CORE_RequestContext *'
+ * @param msg NULL on error or last entry
+ */
+static void
+receive_info (void *cls,
+ const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_CORE_RequestContext *request_context = cls;
+ const struct ConnectNotifyMessage *connect_message;
+
+
+ /* Handle last message or error case, disconnect and clean up */
+ if ( (msg == NULL) ||
+ ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) &&
+ (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader))) )
+ {
+ if (request_context->peer_cb != NULL)
+ request_context->peer_cb (request_context->cb_cls,
+ NULL, NULL);
+ GNUNET_CLIENT_disconnect (request_context->client, GNUNET_NO);
+ GNUNET_free (request_context);
+ return;
+ }
+
+ /* Handle incorrect message type or size, disconnect and clean up */
+ if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) ||
+ (ntohs (msg->size) != sizeof (struct ConnectNotifyMessage)) )
+ {
+ GNUNET_break (0);
+ if (request_context->peer_cb != NULL)
+ request_context->peer_cb (request_context->cb_cls,
+ NULL, NULL);
+ GNUNET_CLIENT_disconnect (request_context->client, GNUNET_NO);
+ GNUNET_free (request_context);
+ return;
+ }
+
+ /* Normal case */
+ connect_message = (const struct ConnectNotifyMessage *) msg;
+ if (request_context->peer_cb != NULL)
+ request_context->peer_cb (request_context->cb_cls,
+ &connect_message->peer,
+ NULL);
+
+ GNUNET_CLIENT_receive(request_context->client, &receive_info, request_context, GNUNET_TIME_relative_get_forever());
+}
+
+/**
+ * Function called to notify a client about the socket
+ * begin ready to queue more data. "buf" will be
+ * NULL and "size" zero if the socket was closed for
+ * writing in the meantime.
+ *
+ * @param cls closure
+ * @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_request(void *cls,
+ size_t size, void *buf)
+{
+ struct GNUNET_MessageHeader *msg;
+ if ((size < sizeof(struct GNUNET_MessageHeader)) || (buf == NULL))
+ return 0;
+
+ msg = (struct GNUNET_MessageHeader *)buf;
+ msg->size = htons (sizeof (struct GNUNET_MessageHeader));
+ msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS);
+ return sizeof(struct GNUNET_MessageHeader);
+}
+
+/**
+ * Obtain statistics and/or change preferences for the given peer.
+ *
+ * @param sched scheduler to use
+ * @param cfg configuration to use
+ * @param peer_cb function to call with the peer information
+ * @param cb_cls closure for peer_cb
+ * @return GNUNET_OK if iterating, GNUNET_SYSERR on error
+ */
+int
+GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ GNUNET_CORE_ConnectEventHandler peer_cb,
+ void *cb_cls)
+{
+ struct GNUNET_CORE_RequestContext *request_context;
+ struct GNUNET_CLIENT_Connection *client;
+
+ client = GNUNET_CLIENT_connect ("core", cfg);
+ if (client == NULL)
+ return GNUNET_SYSERR;
+ request_context = GNUNET_malloc (sizeof (struct GNUNET_CORE_RequestContext));
+ request_context->client = client;
+ request_context->peer_cb = peer_cb;
+ request_context->cb_cls = cb_cls;
+
+ request_context->th = GNUNET_CLIENT_notify_transmit_ready(client,
+ sizeof(struct GNUNET_MessageHeader),
+ GNUNET_TIME_relative_get_forever(),
+ GNUNET_YES,
+ &transmit_request,
+ NULL);
+
+ GNUNET_CLIENT_receive(client, &receive_info, request_context, GNUNET_TIME_relative_get_forever());
+ return GNUNET_OK;
+}
+
+/* end of core_api_iterate_peers.c */
}
+/**
+ * Handle CORE_ITERATE_PEERS request.
+ */
+static void
+handle_client_iterate_peers (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+
+{
+ struct Neighbour *n;
+ struct ConnectNotifyMessage cnm;
+ struct GNUNET_MessageHeader done_msg;
+ struct GNUNET_SERVER_TransmitContext *tc;
+
+ /* notify new client about existing neighbours */
+ cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
+ cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+ done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+ done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
+ tc = GNUNET_SERVER_transmit_context_create (client);
+ n = neighbours;
+ cnm.ats_count = htonl (0);
+ cnm.ats.type = htonl (0);
+ cnm.ats.value = htonl (0);
+ while (n != NULL)
+ {
+ if (n->status == PEER_STATE_KEY_CONFIRMED)
+ {
+#if DEBUG_CORE_CLIENT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending `%s' message to client.\n", "NOTIFY_CONNECT");
+#endif
+ cnm.peer = n->peer;
+ GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header);
+ }
+ n = n->next;
+ }
+ GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
+ GNUNET_SERVER_transmit_context_run (tc,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
+
/**
* Handle REQUEST_INFO request.
*/
static const struct GNUNET_SERVER_MessageHandler handlers[] = {
{&handle_client_init, NULL,
GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
+ {&handle_client_iterate_peers, NULL,
+ GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
+ sizeof (struct GNUNET_MessageHeader)},
{&handle_client_request_info, NULL,
GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
sizeof (struct RequestInfoMessage)},
buf = &data[count + 1];
}
}
-
+ GNUNET_free(data);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (cfg, "dht_testing", "malicious_getters",
&malicious_getters))
/**
* Iterate over all connected peers.
*
- * @param h core handle
+ * @param cfg configuration handle
* @param peer_cb function to call with the peer information
* @param cb_cls closure for peer_cb
* @return GNUNET_OK on success, GNUNET_SYSERR on errors
*/
int
-GNUNET_CORE_iterate_peers (struct GNUNET_CORE_Handle *h,
+GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
GNUNET_CORE_ConnectEventHandler peer_cb,
void *cb_cls);
*/
#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 77
+/**
+ * Request for peer iteration from CORE service.
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS 78
/**
* Session key exchange between peers.
-PATHS]
+[PATHS]
SERVICEHOME = /tmp/test-gnunet-testing/
-DEFAULTCONFIG = test_testing_data.conf
+DEFAULTCONFIG = test_testing_data_remote.conf
[resolver]
PORT = 2564
DEFAULTSERVICES =
[statistics]
+AUTOSTART = NO
PORT = 2567
[transport-tcp]
[testing]
CONTROL_HOST = 131.159.20.42
-HOSTS = 127.0.0.1
+HOSTFILE = remote_hosts.txt
WEAKRANDOM = YES
+NUM_PEERS = 2
[dht]
AUTOSTART = NO
#DEBUG = YES
[testing]
-NUM_PEERS = 500
+NUM_PEERS = 50
WEAKRANDOM = YES
TOPOLOGY = SCALE_FREE
F2F = YES
/* Identifier for this message, so we don't disconnect other peers! */
uint32_t uid;
+ /* Has peer1 been notified already of a connection to peer2? */
+ int peer1notified;
+
+ /* Has the core of peer2 been connected already? */
+ int peer2connected;
+
/* Task for disconnecting cores, allow task to be cancelled on shutdown */
GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
#endif
total_messages_received++;
+
#if VERBOSE > 1
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received message from `%4s', type %d.\n", GNUNET_i2s (peer),
{
struct TestMessageContext *pos = cls;
+ total_server_connections++;
+
+ pos->peer2connected = GNUNET_YES;
+ if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */
+ {
#if VERBOSE > 1
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Core connection to `%4s' established, scheduling message send\n",
- GNUNET_i2s (my_identity));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
+ GNUNET_i2s (my_identity), GNUNET_h2s(&pos->peer1->id.hashPubKey));
#endif
- total_server_connections++;
+ if (NULL == GNUNET_CORE_notify_transmit_ready (pos->peer1handle,
+ 0,
+ TIMEOUT,
+ &pos->peer2->id,
+ sizeof (struct
+ GNUNET_TestMessage),
+ &transmit_ready, pos))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
+ GNUNET_i2s (&pos->peer2->id));
+ transmit_ready_failed++;
+ }
+ else
+ {
+ transmit_ready_scheduled++;
+ }
+ }
+}
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ * @param atsi performance data for the connection
+ */
+static void connect_notify_peers (void *cls,
+ const struct
+ GNUNET_PeerIdentity *peer,
+ const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+ struct TestMessageContext *pos = cls;
- if (NULL == GNUNET_CORE_notify_transmit_ready (pos->peer1handle,
- 0,
- TIMEOUT,
- &pos->peer2->id,
- sizeof (struct
- GNUNET_TestMessage),
- &transmit_ready, pos))
+ if (0 == memcmp(peer, &pos->peer2->id, sizeof(struct GNUNET_PeerIdentity)))
{
+ pos->peer1notified = GNUNET_YES;
+#if VERBOSE > 1
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
- GNUNET_i2s (&pos->peer2->id));
- transmit_ready_failed++;
+ "Peer `%s' notified of connection to peer `%s'\n",
+ GNUNET_i2s (&pos->peer1->id), GNUNET_h2s(&peer->hashPubKey));
+#endif
}
else
+ return;
+
+ if (pos->peer2connected == GNUNET_YES) /* Already connected and notified of connection, send message! */
{
- transmit_ready_scheduled++;
+#if VERBOSE > 1
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
+ GNUNET_i2s (&pos->peer2->id), GNUNET_h2s(&pos->peer1->id.hashPubKey));
+#endif
+ if (NULL == GNUNET_CORE_notify_transmit_ready (pos->peer1handle,
+ 0,
+ TIMEOUT,
+ &pos->peer2->id,
+ sizeof (struct
+ GNUNET_TestMessage),
+ &transmit_ready, pos))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
+ GNUNET_i2s (&pos->peer2->id));
+ transmit_ready_failed++;
+ }
+ else
+ {
+ transmit_ready_scheduled++;
+ }
}
}
-
static void
init_notify_peer1 (void *cls,
struct GNUNET_CORE_Handle *server,
1,
pos,
&init_notify_peer1,
- NULL, NULL,
+ &connect_notify_peers, NULL,
NULL,
NULL,
GNUNET_NO, NULL, GNUNET_NO,
#endif
total_connections++;
#if VERBOSE > 1
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n",
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n",
first_daemon->shortname, second_daemon->shortname);
#endif
temp_context = GNUNET_malloc (sizeof (struct TestMessageContext));
ctx->max_connect_attempts + 1),
&ctx->d2->id,
&core_connect_request_cont, ctx);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+#if DEBUG_TESTING
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending connect request to CORE of %s for peer %s\n",
GNUNET_i2s (&ctx->d1->id),
GNUNET_h2s (&ctx->d2->id.hashPubKey));
+#endif
ctx->timeout_hello =
GNUNET_TIME_relative_add (ctx->timeout_hello,
GNUNET_TIME_relative_multiply
outstanding_connects);
#endif
topology_context->connected++;
+
if (GNUNET_OK !=
- GNUNET_CORE_iterate_peers (core_context->daemon->server,
+ GNUNET_CORE_iterate_peers (core_context->daemon->cfg,
&internal_topology_callback,
core_context))
- internal_topology_callback (core_context, NULL, NULL);
-
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Topology iteration failed.\n");
+ internal_topology_callback (core_context, NULL, NULL);
+ }
}
}
GNUNET_SERVER_disconnect_notify (plugin->server,
&disconnect_notify,
plugin);
- GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-tcp", "BINDTO", &plugin->bind_address);
+
+ if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-tcp", "BINDTO", &plugin->bind_address))
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Binding tcp plugin to specific address: `%s'\n", plugin->bind_address);
if (plugin->behind_nat == GNUNET_NO)
{
plugin->service = service;
- GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO", &plugin->bind_address);
-
- GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO6", &plugin->bind6_address);
+ if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO", &plugin->bind_address))
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", plugin->bind_address);
+ if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO6", &plugin->bind6_address))
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", plugin->bind6_address);
if (plugin->behind_nat == GNUNET_NO)
{
snprintf (lsof, sizeof (lsof), "lsof -p %d", getpid());
close (1);
dup2 (2, 1);
- system (lsof);
+ ret = system (lsof);
#endif
#endif
abort ();