$(BT_TIMEOUT_TEST) \
test_transport_api_multi \
test_transport_api_monitoring \
+ test_transport_api_monitoring_validation \
test_transport_blacklisting_no_bl \
test_transport_blacklisting_outbound_bl_full \
test_transport_blacklisting_outbound_bl_plugin \
$(BT_TIMEOUT_TEST) \
test_transport_api_multi \
test_transport_api_monitoring \
+ test_transport_api_monitoring_validation \
test_transport_blacklisting_no_bl \
test_transport_blacklisting_outbound_bl_full \
test_transport_blacklisting_outbound_bl_plugin \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/transport/libgnunettransporttesting.la
-
test_transport_api_monitoring_SOURCES = \
test_transport_api_monitoring.c
test_transport_api_monitoring_LDADD = \
$(top_builddir)/src/util/libgnunetutil.la \
$(top_builddir)/src/transport/libgnunettransporttesting.la
+test_transport_api_monitoring_validation_SOURCES = \
+ test_transport_api_monitoring_validation.c
+test_transport_api_monitoring_validation_LDADD = \
+ $(top_builddir)/src/transport/libgnunettransport.la \
+ $(top_builddir)/src/hello/libgnunethello.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(top_builddir)/src/transport/libgnunettransporttesting.la
+
EXTRA_DIST = \
test_plugin_hostkey \
test_transport_api_bluetooth_peer2.conf\
test_transport_api_monitoring_peer1.conf\
test_transport_api_monitoring_peer2.conf\
+test_transport_api_monitoring_validation_peer1.conf\
+test_transport_api_monitoring_validation_peer2.conf\
test_transport_defaults.conf\
test_transport_startonly.conf\
test_transport_api_disconnect_tcp_peer1.conf\
"Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n",
GNUNET_i2s (peer),
(NULL != address) ? GST_plugins_a2s (address) : "<none>",
- GNUNET_TRANSPORT_p2s (state),
+ GNUNET_TRANSPORT_ps2s (state),
GNUNET_STRINGS_absolute_time_to_string (state_timeout));
GST_clients_broadcast_peer_notification (peer, address, state, state_timeout);
}
+/**
+ * Function called to notify transport users that a neighbour peer changed its
+ * active address.
+ *
+ * @param cls closure
+ * @param peer peer this update is about (never NULL)
+ * @param address address, NULL on disconnect
+ * @param state current state this peer is in
+ * @param state_timeout timeout for the current state of the peer
+ * @param bandwidth_in bandwidth assigned inbound
+ * @param bandwidth_out bandwidth assigned outbound
+ */
+static void
+validation_changed_notification (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_TIME_Absolute last_validation,
+ struct GNUNET_TIME_Absolute valid_until,
+ struct GNUNET_TIME_Absolute next_validation,
+ enum GNUNET_TRANSPORT_ValidationState state)
+{
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
+ "Notifying about change for for validation entry for peer `%s' with address `%s'\n",
+ GNUNET_i2s (peer),
+ (NULL != address) ? GST_plugins_a2s (address) : "<none>");
+
+ GST_clients_broadcast_validation_notification (peer, address,
+ last_validation, valid_until, next_validation, state);
+}
+
/**
* Function called when the service shuts down. Unloads our plugins
* and cancels pending validations.
&neighbours_disconnect_notification, &neighbours_changed_notification,
(max_fd / 3) * 2);
GST_clients_start (GST_server);
- GST_validation_start ((max_fd / 3));
+ GST_validation_start (&validation_changed_notification, NULL, (max_fd / 3));
}
/**
/**
* Head of linked list of monitoring clients.
*/
-static struct MonitoringClient *monitoring_clients_head;
+static struct MonitoringClient *peer_monitoring_clients_head;
/**
* Tail of linked list of monitoring clients.
*/
-static struct MonitoringClient *monitoring_clients_tail;
+static struct MonitoringClient *peer_monitoring_clients_tail;
+
+/**
+ * Head of linked list of validation monitoring clients.
+ */
+static struct MonitoringClient *val_monitoring_clients_head;
+
+/**
+ * Tail of linked list of validation monitoring clients.
+ */
+static struct MonitoringClient *val_monitoring_clients_tail;
/**
* Notification context, to send updates on changes to active addresses
* of our neighbours.
*/
-static struct GNUNET_SERVER_NotificationContext *nc;
+static struct GNUNET_SERVER_NotificationContext *peer_nc;
+/**
+ * Notification context, to send updates on changes to active addresses
+ * of our neighbours.
+ */
+static struct GNUNET_SERVER_NotificationContext *val_nc;
/**
* Find the internal handle associated with the given client handle
* @return handle to the monitoring client
*/
static struct MonitoringClient *
-lookup_monitoring_client (struct GNUNET_SERVER_Client *client)
+lookup_monitoring_client (struct MonitoringClient *head,
+ struct GNUNET_SERVER_Client *client)
{
struct MonitoringClient *mc;
- for (mc = monitoring_clients_head; NULL != mc; mc = mc->next)
+ for (mc = head; NULL != mc; mc = mc->next)
if (mc->client == client)
return mc;
return NULL;
* @return handle to the new monitoring client
*/
static struct MonitoringClient *
-setup_monitoring_client (struct GNUNET_SERVER_Client *client,
+setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client,
struct GNUNET_PeerIdentity *peer)
{
struct MonitoringClient *mc;
static struct GNUNET_PeerIdentity all_zeros;
- GNUNET_assert (lookup_monitoring_client (client) == NULL);
+ GNUNET_assert (lookup_monitoring_client (peer_monitoring_clients_head, client) == NULL);
mc = GNUNET_new (struct MonitoringClient);
mc->client = client;
mc->peer = *peer;
- GNUNET_CONTAINER_DLL_insert (monitoring_clients_head,
- monitoring_clients_tail,
- mc);
- GNUNET_SERVER_notification_context_add (nc, client);
+ GNUNET_CONTAINER_DLL_insert (peer_monitoring_clients_head, peer_monitoring_clients_tail, mc);
+ GNUNET_SERVER_notification_context_add (peer_nc, client);
if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client %p started monitoring of the peer `%s'\n",
mc, GNUNET_i2s (peer));
else
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %p started monitoring all peers\n", mc);
+ return mc;
+}
+
+/**
+ * Setup a new monitoring client using the given server client handle and
+ * the peer identity.
+ *
+ * @param client server's client handle to create our internal handle for
+ * @param peer identity of the peer to monitor the addresses of,
+ * zero to monitor all neighrours.
+ * @return handle to the new monitoring client
+ */
+static struct MonitoringClient *
+setup_val_monitoring_client (struct GNUNET_SERVER_Client *client,
+ struct GNUNET_PeerIdentity *peer)
+{
+ struct MonitoringClient *mc;
+ static struct GNUNET_PeerIdentity all_zeros;
+
+ GNUNET_assert (lookup_monitoring_client (val_monitoring_clients_head, client) == NULL);
+ mc = GNUNET_new (struct MonitoringClient);
+ mc->client = client;
+ mc->peer = *peer;
+ GNUNET_CONTAINER_DLL_insert (val_monitoring_clients_head, val_monitoring_clients_tail, mc);
+ GNUNET_SERVER_notification_context_add (val_nc, client);
+
+ if (0 != memcmp (peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Client %p started monitoring of the peer `%s'\n",
+ mc, GNUNET_i2s (peer));
+ else
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Client %p started monitoring all peers\n", mc);
return mc;
}
if (client == NULL)
return;
- mc = lookup_monitoring_client (client);
+ mc = lookup_monitoring_client (peer_monitoring_clients_head, client);
if (mc != NULL)
{
- GNUNET_CONTAINER_DLL_remove (monitoring_clients_head,
- monitoring_clients_tail,
+ GNUNET_CONTAINER_DLL_remove (peer_monitoring_clients_head,
+ peer_monitoring_clients_tail,
+ mc);
+ GNUNET_free (mc);
+ }
+ mc = lookup_monitoring_client (val_monitoring_clients_head, client);
+ if (mc != NULL)
+ {
+ GNUNET_CONTAINER_DLL_remove (val_monitoring_clients_head,
+ val_monitoring_clients_tail,
mc);
GNUNET_free (mc);
}
/**
- * Compose AddressIterateResponseMessage using the given peer and address.
+ * Compose #PeerIterateResponseMessage using the given peer and address.
*
* @param peer identity of the peer
* @param address the address, NULL on disconnect
return msg;
}
+/**
+ * Compose #PeerIterateResponseMessage using the given peer and address.
+ *
+ * @param peer identity of the peer
+ * @param address the address, NULL on disconnect
+ * @return composed message
+ */
+static struct ValidationIterateResponseMessage *
+compose_validation_iterate_response_message (const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address)
+{
+ struct ValidationIterateResponseMessage *msg;
+ size_t size;
+ size_t tlen;
+ size_t alen;
+ char *addr;
+
+ GNUNET_assert (NULL != peer);
+ if (NULL != address)
+ {
+ tlen = strlen (address->transport_name) + 1;
+ alen = address->address_length;
+ }
+ else
+ tlen = alen = 0;
+ size = (sizeof (struct ValidationIterateResponseMessage) + alen + tlen);
+ msg = GNUNET_malloc (size);
+ msg->header.size = htons (size);
+ msg->header.type =
+ htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
+ msg->reserved = htonl (0);
+ msg->peer = *peer;
+ msg->addrlen = htonl (alen);
+ msg->pluginlen = htonl (tlen);
+
+ if (NULL != address)
+ {
+ msg->local_address_info = htonl((uint32_t) address->local_info);
+ addr = (char *) &msg[1];
+ memcpy (addr, address->address, alen);
+ memcpy (&addr[alen], address->transport_name, tlen);
+ }
+ return msg;
+}
-struct PeerIterationContext
+struct IterationContext
{
struct GNUNET_SERVER_TransmitContext *tc;
int all;
};
+/**
+ * Output information of neighbours to the given client.
+ *
+ * @param cls the 'struct PeerIterationContext'
+ * @param peer identity of the neighbour
+ * @param address the address
+ * @param state current state this peer is in
+ * @param state_timeout timeout for the current state of the peer
+ * @param bandwidth_in inbound quota in NBO
+ * @param bandwidth_out outbound quota in NBO
+ */
+static void
+send_validation_information (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_TIME_Absolute last_validation,
+ struct GNUNET_TIME_Absolute valid_until,
+ struct GNUNET_TIME_Absolute next_validation,
+ enum GNUNET_TRANSPORT_ValidationState state)
+{
+ struct IterationContext *pc = cls;
+ struct ValidationIterateResponseMessage *msg;
+
+ if ( (GNUNET_YES == pc->all) ||
+ (0 == memcmp (peer, &pc->id, sizeof (pc->id))) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending information about for validation entry for peer `%s' using address `%s'\n",
+ GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
+ msg = compose_validation_iterate_response_message (peer, address);
+ msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
+ msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
+ msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
+ msg->state = htonl ((uint32_t) state);
+ GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
+ GNUNET_free (msg);
+ }
+}
+
+
/**
* Output information of neighbours to the given client.
*
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
{
- struct PeerIterationContext *pc = cls;
+ struct IterationContext *pc = cls;
struct PeerIterateResponseMessage *msg;
if ( (GNUNET_YES == pc->all) ||
"Sending information about `%s' using address `%s' in state `%s'\n",
GNUNET_i2s(peer),
(address != NULL) ? GST_plugins_a2s (address) : "<none>",
- GNUNET_TRANSPORT_p2s (state));
+ GNUNET_TRANSPORT_ps2s (state));
msg = compose_address_iterate_response_message (peer, address);
msg->state = htonl (state);
msg->state_timeout = GNUNET_TIME_absolute_hton(state_timeout);
-
/**
* Client asked to obtain information about a specific or all peers
* Process the request.
static struct GNUNET_PeerIdentity all_zeros;
struct GNUNET_SERVER_TransmitContext *tc;
struct PeerMonitorMessage *msg;
- struct PeerIterationContext pc;
+ struct IterationContext pc;
if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST)
{
}
msg = (struct PeerMonitorMessage *) message;
if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
- (NULL != lookup_monitoring_client (client)) )
+ (NULL != lookup_monitoring_client (peer_monitoring_clients_head, client)) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"ServerClient %p tried to start monitoring twice\n",
if (GNUNET_YES != ntohl (msg->one_shot))
{
- setup_monitoring_client (client, &msg->peer);
+ setup_peer_monitoring_client (client, &msg->peer);
}
else
{
}
+/**
+ * Client asked to obtain information about a specific or all validation
+ * processes
+ *
+ * @param cls unused
+ * @param client the client
+ * @param message the peer address information request
+ */
+static void
+clients_handle_monitor_validation (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ static struct GNUNET_PeerIdentity all_zeros;
+ struct GNUNET_SERVER_TransmitContext *tc;
+ struct PeerMonitorMessage *msg;
+ struct IterationContext pc;
+
+ if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST)
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ if (ntohs (message->size) != sizeof (struct ValidationMonitorMessage))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ msg = (struct PeerMonitorMessage *) message;
+ if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
+ (NULL != lookup_monitoring_client (val_monitoring_clients_head, client)) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+ "ServerClient %p tried to start monitoring twice\n",
+ client);
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ GNUNET_SERVER_disable_receive_done_warning (client);
+ pc.tc = tc = GNUNET_SERVER_transmit_context_create (client);
+
+ /* Send initial list */
+ if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity)))
+ {
+ /* iterate over all neighbours */
+ pc.all = GNUNET_YES;
+ pc.id = msg->peer;
+ }
+ else
+ {
+ /* just return one neighbour */
+ pc.all = GNUNET_NO;
+ pc.id = msg->peer;
+ }
+
+ GST_validation_iterate (&send_validation_information, &pc);
+
+ if (GNUNET_YES != ntohl (msg->one_shot))
+ {
+ GNUNET_break (0);
+ setup_val_monitoring_client (client, &msg->peer);
+ }
+ else
+ {
+ GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
+ GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
+ }
+ GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
/**
* Start handling requests from clients.
*
{&clients_handle_monitor_peers, NULL,
GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST,
sizeof (struct PeerMonitorMessage)},
+ {&clients_handle_monitor_validation, NULL,
+ GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST,
+ sizeof (struct ValidationMonitorMessage)},
{&GST_blacklist_handle_init, NULL,
GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT,
sizeof (struct GNUNET_MessageHeader)},
GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC, 0},
{NULL, NULL, 0, 0}
};
- nc = GNUNET_SERVER_notification_context_create (server, 0);
+ peer_nc = GNUNET_SERVER_notification_context_create (server, 0);
+ val_nc = GNUNET_SERVER_notification_context_create (server, 0);
GNUNET_SERVER_add_handlers (server, handlers);
GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification,
NULL);
GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, cur);
GNUNET_free (cur);
}
- if (NULL != nc)
+ if (NULL != peer_nc)
+ {
+ GNUNET_SERVER_notification_context_destroy (peer_nc);
+ peer_nc = NULL;
+ }
+ if (NULL != val_nc)
{
- GNUNET_SERVER_notification_context_destroy (nc);
- nc = NULL;
+ GNUNET_SERVER_notification_context_destroy (val_nc);
+ val_nc = NULL;
}
}
msg = compose_address_iterate_response_message (peer, address);
msg->state = htonl (state);
msg->state_timeout = GNUNET_TIME_absolute_hton (state_timeout);
- mc = monitoring_clients_head;
+ mc = peer_monitoring_clients_head;
while (mc != NULL)
{
if ((0 == memcmp (&mc->peer, &all_zeros,
(0 == memcmp (&mc->peer, peer,
sizeof (struct GNUNET_PeerIdentity))))
{
- GNUNET_SERVER_notification_context_unicast (nc, mc->client,
+ GNUNET_SERVER_notification_context_unicast (peer_nc, mc->client,
&msg->header, GNUNET_NO);
}
GNUNET_free (msg);
}
+/**
+ * Broadcast the new active address to all clients monitoring the peer.
+ *
+ * @param peer peer this update is about (never NULL)
+ * @param address address, NULL on disconnect
+ * @param state the current state of the peer
+ * @param state_timeout the time out for the state
+ */
+void
+GST_clients_broadcast_validation_notification (
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_TIME_Absolute last_validation,
+ struct GNUNET_TIME_Absolute valid_until,
+ struct GNUNET_TIME_Absolute next_validation,
+ enum GNUNET_TRANSPORT_ValidationState state)
+{
+ struct ValidationIterateResponseMessage *msg;
+ struct MonitoringClient *mc;
+ static struct GNUNET_PeerIdentity all_zeros;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending information about for validation entry for peer `%s' using address `%s'\n",
+ GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
+
+ msg = compose_validation_iterate_response_message (peer, address);
+ msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
+ msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
+ msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
+ msg->state = htonl ((uint32_t) state);
+ mc = val_monitoring_clients_head;
+ while (mc != NULL)
+ {
+ if ((0 == memcmp (&mc->peer, &all_zeros,
+ sizeof (struct GNUNET_PeerIdentity))) ||
+ (0 == memcmp (&mc->peer, peer,
+ sizeof (struct GNUNET_PeerIdentity))))
+ {
+ GNUNET_SERVER_notification_context_unicast (val_nc, mc->client,
+ &msg->header, GNUNET_NO);
+
+ }
+ mc = mc->next;
+ }
+ GNUNET_free (msg);
+}
+
/* end of file gnunet-service-transport_clients.c */
enum GNUNET_TRANSPORT_PeerState state,
struct GNUNET_TIME_Absolute state_timeout);
+void
+GST_clients_broadcast_validation_notification (
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_TIME_Absolute last_validation,
+ struct GNUNET_TIME_Absolute valid_until,
+ struct GNUNET_TIME_Absolute next_validation,
+ enum GNUNET_TRANSPORT_ValidationState state);
+
#endif
/* end of file gnunet-service-transport_clients.h */
n->state = s;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' changed state to %s\n",
GNUNET_i2s (&n->id),
- GNUNET_TRANSPORT_p2s(s));
+ GNUNET_TRANSPORT_ps2s(s));
neighbour_change_cb (callback_cls,
&n->id,
n->primary_address.address,
n->timeout = timeout;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Neighbour `%s' changed state to %s with timeout %s\n",
GNUNET_i2s (&n->id),
- GNUNET_TRANSPORT_p2s(s),
+ GNUNET_TRANSPORT_ps2s(s),
GNUNET_STRINGS_absolute_time_to_string (timeout));
neighbour_change_cb (callback_cls,
&n->id,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Disconnecting from peer %s in state %s\n",
GNUNET_i2s (&n->id),
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
/* depending on state, notify neighbour and/or upper layers of this peer
about disconnect */
switch (n->state)
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
break;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Asked to connect to peer `%s' (state: %s)\n",
GNUNET_i2s (target),
- (NULL != n) ? GNUNET_TRANSPORT_p2s(n->state) : "NEW PEER");
+ (NULL != n) ? GNUNET_TRANSPORT_ps2s(n->state) : "NEW PEER");
if (NULL != n)
{
switch (n->state)
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
free_neighbour (n, GNUNET_NO);
break;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received blacklist result for peer `%s' in state %s/%d\n",
GNUNET_i2s (peer),
- GNUNET_TRANSPORT_p2s (n->state),
+ GNUNET_TRANSPORT_ps2s (n->state),
n->send_connect_ack);
switch (n->state)
{
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
free_neighbour (n, GNUNET_NO);
break;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received SESSION_CONNECT for peer `%s' in state %s/%d\n",
GNUNET_i2s (peer),
- GNUNET_TRANSPORT_p2s (n->state),
+ GNUNET_TRANSPORT_ps2s (n->state),
n->send_connect_ack);
switch (n->state)
{
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
return GNUNET_SYSERR;
}
GST_plugins_a2s (address),
session,
GNUNET_i2s (peer),
- GNUNET_TRANSPORT_p2s (n->state),
+ GNUNET_TRANSPORT_ps2s (n->state),
n->send_connect_ack,
ntohl (bandwidth_in.value__),
ntohl (bandwidth_out.value__));
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
break;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Master task runs for neighbour `%s' in state %s with timeout in %s\n",
GNUNET_i2s (&n->id),
- GNUNET_TRANSPORT_p2s(n->state),
+ GNUNET_TRANSPORT_ps2s(n->state),
GNUNET_STRINGS_relative_time_to_string (delay,
GNUNET_YES));
switch (n->state)
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
break;
}
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
return GNUNET_SYSERR;
}
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
break;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received SESSION_ACK message from peer `%s' in state %s/%d\n",
GNUNET_i2s (peer),
- GNUNET_TRANSPORT_p2s (n->state),
+ GNUNET_TRANSPORT_ps2s (n->state),
n->send_connect_ack);
GNUNET_STATISTICS_update (GST_stats,
gettext_noop ("# unexpected SESSION_ACK messages"), 1,
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s'\n",
- GNUNET_TRANSPORT_p2s (n->state));
+ GNUNET_TRANSPORT_ps2s (n->state));
GNUNET_break (0);
break;
}
*/
struct GNUNET_TIME_Absolute send_time;
+ /**
+ * At what time do we send the next validation request (PING)?
+ */
+ struct GNUNET_TIME_Absolute next_validation;
+
/**
* Until when is this address valid?
* ZERO if it is not currently considered valid.
*/
struct GNUNET_TIME_Relative latency;
+ /**
+ * Current state of this validation entry
+ */
+ enum GNUNET_TRANSPORT_ValidationState state;
/**
* Challenge number we used.
*/
*/
static struct GNUNET_TIME_Absolute validation_next;
+static GST_ValidationChangedCallback validation_entry_changed_cb;
+static void *validation_entry_changed_cb_cls;
+
/**
* Context for the validation entry match function.
*/
return GNUNET_YES;
}
+static void
+validation_entry_changed (struct ValidationEntry *ve, enum GNUNET_TRANSPORT_ValidationState state)
+{
+ char *t_sent = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->send_time));
+ char *t_valid = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->valid_until));
+ char *t_next = GNUNET_strdup(GNUNET_STRINGS_absolute_time_to_string(ve->next_validation));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation entry changed for peer `%s' address `%s':\n\tSent: %s\n\tValid: %s\n\tNext: %s\n",
+ GNUNET_i2s(&ve->pid), GST_plugins_a2s(ve->address),
+ t_sent, t_valid, t_next);
+ ve->state = state;
+
+ GNUNET_free (t_sent);
+ GNUNET_free (t_valid);
+ GNUNET_free (t_next);
+ validation_entry_changed_cb (validation_entry_changed_cb_cls, &ve->pid,
+ ve->address, ve->send_time, ve->valid_until, ve->next_validation, state);
+}
+
/**
* Iterate over validation entries and free them.
{
struct ValidationEntry *ve = value;
+ ve->next_validation = GNUNET_TIME_absolute_get_zero_();
+ ve->valid_until = GNUNET_TIME_UNIT_ZERO_ABS;
+
+ /* Notify about deleted entry */
+ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_REMOVE);
+
if (NULL != ve->bc)
{
GST_blacklist_test_cancel (ve->bc);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Validation started, %u validation processes running\n",
validations_running);
+ /* Notify about PING sent */
+ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
}
}
GST_plugins_a2s (ve->address));
ve->revalidation_task =
GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve);
+ ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay);
return;
}
blocked_for = GNUNET_TIME_absolute_get_remaining(validation_next);
GST_plugins_a2s (ve->address));
ve->revalidation_task =
GNUNET_SCHEDULER_add_delayed (blocked_for, &revalidate_address, ve);
+ ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), blocked_for);
return;
}
ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay);
GST_plugins_a2s (ve->address));
ve->revalidation_task =
GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve);
+ ve->next_validation = GNUNET_TIME_absolute_add(GNUNET_TIME_absolute_get(), delay);
/* start PINGing by checking blacklist */
GNUNET_STATISTICS_update (GST_stats,
GNUNET_CONTAINER_multipeermap_put (validation_map, &address->peer,
ve,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_NEW);
ve->expecting_pong = GNUNET_NO;
return ve;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Starting revalidations for valid address `%s'\n",
GST_plugins_a2s (ve->address));
+ ve->next_validation = GNUNET_TIME_absolute_get();
ve->revalidation_task = GNUNET_SCHEDULER_add_now (&revalidate_address, ve);
}
+ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
ats.type = htonl (GNUNET_ATS_NETWORK_TYPE);
ats.value = htonl (ve->network);
* @param max_fds maximum number of fds to use
*/
void
-GST_validation_start (unsigned int max_fds)
+GST_validation_start (GST_ValidationChangedCallback cb, void *cb_cls, unsigned int max_fds)
{
/**
* Initialization for validation throttling
validation_delay.rel_value_us = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2);
validations_fast_start_threshold = (max_fds / 2);
validations_running = 0;
+ validation_entry_changed_cb = cb;
+ validation_entry_changed_cb_cls = cb_cls;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Validation uses a fast start threshold of %u connections and a delay between of %s\n ",
validations_fast_start_threshold,
GNUNET_STRINGS_relative_time_to_string (validation_delay,
GNUNET_break (0);
}
+ /* Notify about new validity */
+ validation_entry_changed (ve, GNUNET_TRANSPORT_VS_UPDATE);
+
/* build HELLO to store in PEERINFO */
ve->copied = GNUNET_NO;
hello = GNUNET_HELLO_create (&ve->public_key,
return ve->latency;
}
+/**
+ * Closure for the validation_entries_iterate function.
+ */
+struct ValidationIteratorContext
+{
+ /**
+ * Function to call on each validation entry
+ */
+ GST_ValidationChangedCallback cb;
+
+ /**
+ * Closure for 'cb'.
+ */
+ void *cb_cls;
+};
+
+static int
+validation_entries_iterate (void *cls,
+ const struct GNUNET_PeerIdentity *key,
+ void *value)
+{
+ struct ValidationIteratorContext *ic = cls;
+ struct ValidationEntry *ve = value;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying about validation entry for peer `%s' address `%s' \n",
+ GNUNET_i2s (&ve->pid), GST_plugins_a2s (ve->address));
+ ic->cb (ic->cb_cls, &ve->pid, ve->address, ve->send_time,
+ ve->valid_until, ve->next_validation, ve->state);
+
+ return GNUNET_OK;
+}
+
+/**
+ * Iterate over all iteration entries
+ *
+ * @param cb function to call
+ * @param cb_cls closure for cb
+ */
+void
+GST_validation_iterate (GST_ValidationChangedCallback cb, void *cb_cls)
+{
+ struct ValidationIteratorContext ic;
+
+ if (NULL == validation_map)
+ return; /* can happen during shutdown */
+ ic.cb = cb;
+ ic.cb_cls = cb_cls;
+ GNUNET_CONTAINER_multipeermap_iterate (validation_map, &validation_entries_iterate, &ic);
+}
/* end of file gnunet-service-transport_validation.c */
#include "gnunet_util_lib.h"
#include "gnunet_hello_lib.h"
+/**
+ * Function called for each address (or address status change) that
+ * the validation module is aware of (for the given target).
+ *
+ * @param cls closure
+ * @param public_key public key for the peer, never NULL
+ * @param valid_until is ZERO if we never validated the address,
+ * otherwise a time up to when we consider it (or was) valid
+ * @param validation_block is FOREVER if the address is for an unsupported plugin (from PEERINFO)
+ * is ZERO if the address is considered valid (no validation needed)
+ * otherwise a time in the future if we're currently denying re-validation
+ * @param address the address
+ */
+typedef void (*GST_ValidationChangedCallback) (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_TIME_Absolute last_validation,
+ struct GNUNET_TIME_Absolute valid_until,
+ struct GNUNET_TIME_Absolute next_validation,
+ enum GNUNET_TRANSPORT_ValidationState state);
/**
* Start the validation subsystem.
* @param max_fds maximum number of fds to use
*/
void
-GST_validation_start (unsigned int max_fds);
+GST_validation_start (GST_ValidationChangedCallback cb, void *cb_cls, unsigned int max_fds);
/**
const struct GNUNET_HELLO_Address *address,
struct Session *session);
+/**
+ * Iterate over all iteration entries
+ *
+ * @param cb function to call
+ * @param cb_cls closure for cb
+ */
+void
+GST_validation_iterate (GST_ValidationChangedCallback cb, void *cb_cls);
/**
* We've received a PING. If appropriate, generate a PONG.
*/
static int iterate_connections;
+/**
+ * Option -d.
+ */
+static int iterate_validation;
+
/**
* Option -a.
*/
/**
*
*/
-struct GNUNET_TRANSPORT_PeerMonitoringContext *pic;
+static struct GNUNET_TRANSPORT_PeerMonitoringContext *pic;
+
+static struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic;
/**
* Identity of the peer we transmit to / connect to.
GNUNET_TRANSPORT_monitor_peers_cancel (pic);
pic = NULL;
}
+ if (NULL != vic)
+ {
+ GNUNET_TRANSPORT_monitor_validation_entries_cancel (vic);
+ vic = NULL;
+ }
if (NULL != th)
{
GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
display_test_result (tstc, GNUNET_NO);
}
+void process_validation_cb (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct GNUNET_TIME_Absolute last_validation,
+ struct GNUNET_TIME_Absolute valid_until,
+ struct GNUNET_TIME_Absolute next_validation,
+ enum GNUNET_TRANSPORT_ValidationState state)
+{
+ GNUNET_break (0);
+}
+
/**
* Test our plugin's configuration (NAT traversal, etc.).
*
GNUNET_i2s (id),
(NULL == transport) ? "<none>" : transport,
(NULL == transport) ? "<none>" : addr,
- GNUNET_TRANSPORT_p2s (state),
+ GNUNET_TRANSPORT_ps2s (state),
GNUNET_STRINGS_absolute_time_to_string (state_timeout));
}
else
}
counter = benchmark_send + benchmark_receive + iterate_connections
- + monitor_connections + monitor_connects + try_connect;
+ + monitor_connections + monitor_connects + try_connect + iterate_validation;
if (1 < counter)
{
pic = GNUNET_TRANSPORT_monitor_peers (cfg, (NULL == cpid) ? NULL : &pid,
GNUNET_NO, TIMEOUT, &process_peer_monitoring_cb, (void *) cfg);
}
+ else if (iterate_validation) /* -d: Print information about validations */
+ {
+ vic = GNUNET_TRANSPORT_monitor_validation_entries (cfg, (NULL == cpid) ? NULL : &pid,
+ GNUNET_YES, TIMEOUT, &process_validation_cb, (void *) cfg);
+ }
else if (monitor_connects) /* -e : Monitor (dis)connect events continuously */
{
monitor_connect_counter = 0;
0, &GNUNET_GETOPT_set_one, &benchmark_receive }, { 'C', "connect",
NULL, gettext_noop ("connect to a peer"), 0,
&GNUNET_GETOPT_set_one, &try_connect },
+ { 'd', "validation", NULL,
+ gettext_noop ("print information for all pending validations "),
+ 0, &GNUNET_GETOPT_set_one, &iterate_validation },
{ 'i', "information", NULL,
gettext_noop ("provide information about all current connections (once)"),
0, &GNUNET_GETOPT_set_one, &iterate_connections },
"Session %p was idle for %s, disconnecting\n", s,
GNUNET_STRINGS_relative_time_to_string (UDP_SESSION_TIME_OUT, GNUNET_YES));
/* call session destroy function */
- udp_disconnect_session (s->plugin, s);
+ udp_disconnect_session (plugin, s);
}
/**
GNUNET_SCHEDULER_cancel (send_task);
if (die_task != GNUNET_SCHEDULER_NO_TASK)
+ {
GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ }
if (th != NULL)
GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
th = NULL;
- GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
+ if (NULL != p1)
+ GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
p1 = NULL;
- GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
+ if (NULL != p2)
+ GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
p2 = NULL;
if (NULL != pmc_p1)
if ((NULL == peer) || (NULL == p1))
return;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 1: %s %s %s\n",
- GNUNET_i2s (peer), GNUNET_TRANSPORT_p2s(state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Monitor 1: %s %s %s\n",
+ GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s(state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
if ((0 == memcmp (peer, &p2->id, sizeof (p2->id)) &&
(GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) &&
GNUNET_NO == p1_c) )
if ((NULL == peer) || (NULL == p2))
return;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Monitor 2: %s %s %s\n",
- GNUNET_i2s (peer), GNUNET_TRANSPORT_p2s (state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Monitor 2: %s %s %s\n",
+ GNUNET_i2s (peer), GNUNET_TRANSPORT_ps2s (state), GNUNET_STRINGS_absolute_time_to_string(state_timeout));
if ((0 == memcmp (peer, &p1->id, sizeof (p1->id)) &&
(GNUNET_YES == GNUNET_TRANSPORT_is_connected(state)) &&
GNUNET_NO == p2_c) )
¬ify_disconnect, &start_cb,
NULL);
pmc_p1 = GNUNET_TRANSPORT_monitor_peers (p1->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor1_cb, NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 started\n");
p2 = GNUNET_TRANSPORT_TESTING_start_peer (tth, cfg_file_p2, 2,
¬ify_receive, ¬ify_connect,
¬ify_disconnect, &start_cb,
NULL);
pmc_p2 = GNUNET_TRANSPORT_monitor_peers (p2->cfg, NULL, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, &monitor2_cb, NULL);
-
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 started\n");
if ((p1 == NULL) || (p2 == NULL))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Fail! Could not start peers!\n");
--- /dev/null
+@INLINE@ template_cfg_peer1.conf
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p1/
+
+[transport]
+PLUGINS=tcp
--- /dev/null
+@INLINE@ template_cfg_peer2.conf
+[PATHS]
+GNUNET_TEST_HOME = /tmp/test-transport/api-monitoring-val-p2/
+
+[TRANSPORT]
+PLUGINS=tcp
+
};
-#if 0
/**
- * Message from the library to the transport service
- * asking for human readable addresses known for a peer.
+ * Message from the transport service to the library containing information
+ * about a peer. Information contained are:
+ * - current address used to communicate with this peer
+ * - state
+ * - state timeout
+ *
+ * Memory layout:
+ * [AddressIterateResponseMessage][address[addrlen]][transportname[pluginlen]]
*/
-struct PeerLookupMessage
+struct ValidationIterateResponseMessage
{
/**
- * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_PEER_ADDRESS_LOOKUP
+ * Type is #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE
*/
struct GNUNET_MessageHeader header;
uint32_t reserved;
/**
- * timeout to give up. FIXME: remove in the future.
+ * Peer identity
*/
- struct GNUNET_TIME_RelativeNBO timeout;
+ struct GNUNET_PeerIdentity peer;
+
+ /**
+ * Local info about the address
+ */
+ uint32_t local_address_info GNUNET_PACKED;
+
+ /**
+ * Address length
+ */
+ uint32_t addrlen GNUNET_PACKED;
+
+ /**
+ * Length of the plugin name
+ */
+ uint32_t pluginlen GNUNET_PACKED;
+
+ /**
+ * State
+ */
+ uint32_t state GNUNET_PACKED;
+
+ struct GNUNET_TIME_AbsoluteNBO last_validation;
+
+ struct GNUNET_TIME_AbsoluteNBO valid_until;
+
+ struct GNUNET_TIME_AbsoluteNBO next_validation;
+};
+
+/**
+ * Message from the library to the transport service
+ * asking for binary addresses known for a peer.
+ */
+struct ValidationMonitorMessage
+{
+ /**
+ * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * One shot call or continous replies?
+ */
+ uint32_t one_shot;
/**
* The identity of the peer to look up.
*/
struct GNUNET_PeerIdentity peer;
+
};
-#endif
/**
struct PeerMonitorMessage
{
/**
- * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE
+ * Type will be #GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST
*/
struct GNUNET_MessageHeader header;
*/
uint32_t one_shot;
- /**
- * timeout to give up. FIXME: remove in the future
- */
- struct GNUNET_TIME_AbsoluteNBO timeout;
-
/**
* The identity of the peer to look up.
*/
default:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unhandled state `%s' \n",
- GNUNET_TRANSPORT_p2s (state));
+ GNUNET_TRANSPORT_ps2s (state));
GNUNET_break (0);
break;
}
}
/**
- * Convert state to human-readable string.
+ * Convert peer state to human-readable string.
*
* @param state the state value
* @return corresponding string
*/
const char *
-GNUNET_TRANSPORT_p2s (enum GNUNET_TRANSPORT_PeerState state)
+GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state)
{
switch (state)
{
}
}
+/**
+ * Convert validation state to human-readable string.
+ *
+ * @param state the state value
+ * @return corresponding string
+ */
+const char *
+GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state)
+{
+ switch (state)
+ {
+ case GNUNET_TRANSPORT_VS_NEW:
+ return "NEW";
+ case GNUNET_TRANSPORT_VS_REMOVE:
+ return "REMOVE";
+ case GNUNET_TRANSPORT_VS_TIMEOUT:
+ return "TIMEOUT";
+ case GNUNET_TRANSPORT_VS_UPDATE:
+ return "UPDATE";
+ default:
+ GNUNET_break (0);
+ return "UNDEFINED";
+ }
+}
+
/**
* Function called with responses from the service.
* message with the human-readable address
*/
static void
-peer_response_processor (void *cls,
- const struct GNUNET_MessageHeader *msg);
+peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
+/**
+ * Function called with responses from the service.
+ *
+ * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
+ * @param msg NULL on timeout or error, otherwise presumably a
+ * message with the human-readable address
+ */
+static void
+val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
+
/**
* Send our subscription request to the service.
*
* @param pal_ctx our context
*/
static void
-send_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
+send_peer_mon_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
{
struct PeerMonitorMessage msg;
msg.header.size = htons (sizeof (struct PeerMonitorMessage));
msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST);
msg.one_shot = htonl (pal_ctx->one_shot);
- msg.timeout = GNUNET_TIME_absolute_hton (pal_ctx->timeout);
msg.peer = pal_ctx->peer;
GNUNET_assert (GNUNET_OK ==
GNUNET_CLIENT_transmit_and_get_response (pal_ctx->client,
- &msg.header,
- GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
- GNUNET_YES,
- &peer_response_processor,
- pal_ctx));
+ &msg.header,
+ GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
+ GNUNET_YES,
+ &peer_response_processor,
+ pal_ctx));
}
+/**
+ * Send our subscription request to the service.
+ *
+ * @param pal_ctx our context
+ */
+static void
+send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
+{
+ struct ValidationMonitorMessage msg;
+
+ msg.header.size = htons (sizeof (struct PeerMonitorMessage));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST);
+ msg.one_shot = htonl (val_ctx->one_shot);
+ msg.peer = val_ctx->peer;
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CLIENT_transmit_and_get_response (val_ctx->client,
+ &msg.header,
+ GNUNET_TIME_absolute_get_remaining (val_ctx->timeout),
+ GNUNET_YES,
+ &val_response_processor,
+ val_ctx));
+}
+
+
/**
* Task run to re-establish the connection.
*
pal_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
pal_ctx->client = GNUNET_CLIENT_connect ("transport", pal_ctx->cfg);
GNUNET_assert (NULL != pal_ctx->client);
- send_request (pal_ctx);
+ send_peer_mon_request (pal_ctx);
}
pal_ctx);
}
+/**
+ * Function called with responses from the service.
+ *
+ * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*'
+ * @param msg NULL on timeout or error, otherwise presumably a
+ * message with the human-readable address
+ */
+static void
+val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
+{
+ struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
+ GNUNET_break (0);
+ if (msg == NULL)
+ {
+ GNUNET_break (0);
+ if (val_ctx->one_shot)
+ {
+ /* Disconnect */
+ val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+ GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+ GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
+ GNUNET_TRANSPORT_monitor_peers_cancel (val_ctx);
+ }
+ else
+ {
+ reconnect (val_ctx);
+ }
+ return;
+ }
+
+ /* expect more replies */
+ GNUNET_CLIENT_receive (val_ctx->client, &val_response_processor,
+ val_ctx, GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
+
+ return;
+
+ struct ValidationIterateResponseMessage *vir_msg;
+ struct GNUNET_HELLO_Address *address;
+ const char *addr;
+ const char *transport_name;
+ uint16_t size;
+ size_t alen;
+ size_t tlen;
+#if 0
+
+ size = ntohs (msg->size);
+ GNUNET_break (ntohs (msg->type) ==
+ GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
+ if (size == sizeof (struct GNUNET_MessageHeader))
+ {
+ /* Done! */
+ if (pal_ctx->one_shot)
+ {
+ pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+ GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+ GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+ }
+ else
+ {
+ reconnect (pal_ctx);
+ }
+ return;
+ }
+
+ if ((size < sizeof (struct PeerIterateResponseMessage)) ||
+ (ntohs (msg->type) !=
+ GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE))
+ {
+ GNUNET_break (0);
+ if (pal_ctx->one_shot)
+ {
+ pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+ GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+ GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+ }
+ else
+ {
+ reconnect (pal_ctx);
+ }
+ return;
+ }
+
+ pir_msg = (struct PeerIterateResponseMessage *) msg;
+ tlen = ntohl (pir_msg->pluginlen);
+ alen = ntohl (pir_msg->addrlen);
+
+ if (size != sizeof (struct PeerIterateResponseMessage) + tlen + alen)
+ {
+ GNUNET_break (0);
+ if (pal_ctx->one_shot)
+ {
+ pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+ GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+ GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+ }
+ else
+ {
+ reconnect (pal_ctx);
+ }
+ return;
+ }
+
+ if ( (0 == tlen) && (0 == alen) )
+ {
+ /* No address available */
+ pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, NULL,
+ ntohl(pir_msg->state),
+ GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
+ }
+ else
+ {
+ if (0 == tlen)
+ {
+ GNUNET_break (0); /* This must not happen: address without plugin */
+ return;
+ }
+ addr = (const char *) &pir_msg[1];
+ transport_name = &addr[alen];
+
+ if (transport_name[tlen - 1] != '\0')
+ {
+ /* Corrupt plugin name */
+ GNUNET_break (0);
+ if (pal_ctx->one_shot)
+ {
+ pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+ GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+ GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+ }
+ else
+ {
+ reconnect (pal_ctx);
+ }
+ return;
+ }
+
+ /* notify client */
+ address = GNUNET_HELLO_address_allocate (&pir_msg->peer,
+ transport_name, addr, alen, ntohl(pir_msg->local_address_info));
+ pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, address,
+ ntohl(pir_msg->state),
+ GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
+ GNUNET_HELLO_address_free (address);
+ }
+#endif
+
+}
+
/**
* Function called with responses from the service.
uint16_t size;
size_t alen;
size_t tlen;
-
+ GNUNET_break (0);
if (msg == NULL)
{
if (pal_ctx->one_shot)
return;
}
-
if ( (0 == tlen) && (0 == alen) )
{
/* No address available */
pal_ctx->peer = *peer;
pal_ctx->one_shot = one_shot;
pal_ctx->client = client;
- send_request (pal_ctx);
+ send_peer_mon_request (pal_ctx);
return pal_ctx;
}
GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
void *validation_callback_cls)
{
- /* Not implemented */
- return NULL;
+ struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx;
+ struct GNUNET_CLIENT_Connection *client;
+
+ client = GNUNET_CLIENT_connect ("transport", cfg);
+ if (client == NULL)
+ return NULL;
+ if (GNUNET_YES != one_shot)
+ timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+ val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext);
+ val_ctx->cb = validation_callback;
+ val_ctx->cb_cls = validation_callback_cls;
+ val_ctx->cfg = cfg;
+ val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+ if (NULL != peer)
+ val_ctx->peer = *peer;
+ val_ctx->one_shot = one_shot;
+ val_ctx->client = client;
+ send_val_mon_request (val_ctx);
+
+ return val_ctx;
}
void
GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
{
- /* Not implemented */
+ if (NULL != vic->client)
+ {
+ GNUNET_CLIENT_disconnect (vic->client);
+ vic->client = NULL;
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task)
+ {
+ GNUNET_SCHEDULER_cancel (vic->reconnect_task);
+ vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ GNUNET_free (vic);
}