/** * Handle request connect message * * @param cls closure (always NULL) * @param client identification of the client * @param message the actual message */ static void clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct TransportRequestConnectMessage *trcm = (const struct TransportRequestConnectMessage *) message; GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# REQUEST CONNECT messages received"), 1, GNUNET_NO); if (0 == memcmp (&trcm->peer, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received a request connect message myself `%s'\n", GNUNET_i2s (&trcm->peer)); } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a request connect message for peer `%s'\n", GNUNET_i2s (&trcm->peer)); (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed, NULL); } GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Do address validation again to keep address valid. * * @param cls the 'struct ValidationEntry' * @param tc scheduler context (unused) */ static void revalidate_address (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ValidationEntry *ve = cls; struct GNUNET_TIME_Relative canonical_delay; struct GNUNET_TIME_Relative delay; struct GST_BlacklistCheck *bc; uint32_t rdelay; ve->revalidation_task = GNUNET_SCHEDULER_NO_TASK; delay = GNUNET_TIME_absolute_get_remaining (ve->revalidation_block); /* How long until we can possibly permit the next PING? */ canonical_delay = (ve->in_use == GNUNET_YES) ? CONNECTED_PING_FREQUENCY : ((GNUNET_TIME_absolute_get_remaining (ve->valid_until).rel_value > 0) ? VALIDATED_PING_FREQUENCY : UNVALIDATED_PING_KEEPALIVE); if (delay.rel_value > canonical_delay.rel_value * 2) { /* situation changed, recalculate delay */ delay = canonical_delay; ve->revalidation_block = GNUNET_TIME_relative_to_absolute (delay); } if (delay.rel_value > 0) { /* should wait a bit longer */ ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); return; } ve->revalidation_block = GNUNET_TIME_relative_to_absolute (canonical_delay); /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */ rdelay = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, canonical_delay.rel_value); delay = GNUNET_TIME_relative_add (canonical_delay, GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rdelay)); ve->revalidation_task = GNUNET_SCHEDULER_add_delayed (delay, &revalidate_address, ve); /* start PINGing by checking blacklist */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# address revalidations started"), 1, GNUNET_NO); bc = GST_blacklist_test_allowed (&ve->pid, ve->address->transport_name, &transmit_ping_if_allowed, ve); if (NULL != bc) ve->bc = bc; /* only set 'bc' if 'transmit_ping_if_allowed' was not already * called... */ }
/** * Plugin tells transport service about a new inbound session * * @param cls unused * @param address the address * @param session the new session * @param scope network scope information */ static void plugin_env_session_start (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, enum GNUNET_ATS_Network_Type scope) { struct GNUNET_ATS_Properties prop; if (NULL == address) { GNUNET_break(0); return; } if (NULL == session) { GNUNET_break(0); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Notification from plugin `%s' about new session from peer `%s' address `%s'\n", address->transport_name, GNUNET_i2s (&address->peer), GST_plugins_a2s (address)); if (GNUNET_YES == GNUNET_HELLO_address_check_option (address, GNUNET_HELLO_ADDRESS_INFO_INBOUND)) { /* inbound is always new, but outbound MAY already be known, but for example for UNIX, we have symmetric connections and thus we may not know the address yet; add if necessary! */ /* FIXME: maybe change API here so we just pass scope? */ memset (&prop, 0, sizeof (prop)); GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != scope); prop.scope = scope; GST_ats_add_inbound_address (address, session, &prop); } /* Do blacklist check if communication with this peer is allowed */ (void) GST_blacklist_test_allowed (&address->peer, address->transport_name, &plugin_env_session_start_bl_check_cont, NULL, address, session); }
/** * Function called by the transport for each received message. * * @param cls closure, const char* with the name of the plugin we received the message from * @param address address and (claimed) identity of the other peer * @param message the message, NULL if we only care about * learning about the delay until we should receive again * @param session identifier used for this session (NULL for plugins * that do not offer bi-directional communication to the sender * using the same "connection") * @return how long the plugin should wait until receiving more data * (plugins that do not support this, can ignore the return value) */ struct GNUNET_TIME_Relative GST_receive_callback (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, const struct GNUNET_MessageHeader *message) { const char *plugin_name = cls; struct GNUNET_TIME_Relative ret; uint16_t type; ret = GNUNET_TIME_UNIT_ZERO; if (NULL == message) goto end; type = ntohs (message->type); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message with type %u from peer `%s'\n", type, GNUNET_i2s (&address->peer)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes total received"), ntohs (message->size), GNUNET_NO); GST_neighbours_notify_data_recv (address, message); switch (type) { case GNUNET_MESSAGE_TYPE_HELLO_LEGACY: /* Legacy HELLO message, discard */ return ret; case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != GST_validation_handle_hello (message)) { GNUNET_break_op (0); GST_blacklist_abort_matching (address, session); } return ret; case GNUNET_MESSAGE_TYPE_TRANSPORT_PING: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Processing PING from `%s'\n", GST_plugins_a2s (address)); if (GNUNET_OK != GST_validation_handle_ping (&address->peer, message, address, session)) { GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG: GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Processing PONG from `%s'\n", GST_plugins_a2s (address)); if (GNUNET_OK != GST_validation_handle_pong (&address->peer, message)) { GNUNET_break_op (0); GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN: /* Do blacklist check if communication with this peer is allowed */ (void) GST_blacklist_test_allowed (&address->peer, NULL, &connect_bl_check_cont, GNUNET_copy_message (message), address, session); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_SYN_ACK: if (GNUNET_OK != GST_neighbours_handle_session_syn_ack (message, address, session)) { GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK: if (GNUNET_OK != GST_neighbours_handle_session_ack (message, address, session)) { GNUNET_break_op(0); GST_blacklist_abort_matching (address, session); kill_session (plugin_name, session); } break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT: GST_neighbours_handle_disconnect_message (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA: GST_neighbours_handle_quota_message (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE: GST_neighbours_keepalive (&address->peer, message); break; case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE: GST_neighbours_keepalive_response (&address->peer, message); break; default: /* should be payload */ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes payload received"), ntohs (message->size), GNUNET_NO); ret = process_payload (address, session, message); break; } end: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Allowing receive from peer %s to continue in %s\n", GNUNET_i2s (&address->peer), GNUNET_STRINGS_relative_time_to_string (ret, GNUNET_YES)); return ret; }