/** * Construct our HELLO message from all of the addresses of * all of the transports. * * @param cls unused * @param tc scheduler context */ static void refresh_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GeneratorContext gc; int friend_only; hello_task = GNUNET_SCHEDULER_NO_TASK; gc.addr_pos = oal_head; gc.expiration = GNUNET_TIME_relative_to_absolute (hello_expiration); friend_only = GNUNET_HELLO_is_friend_only (our_hello); GNUNET_free (our_hello); our_hello = GNUNET_HELLO_create (&GST_my_public_key, &address_generator, &gc, friend_only); GNUNET_assert (NULL != our_hello); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Refreshed my %s `%s', new size is %d\n", (GNUNET_YES == GNUNET_HELLO_is_friend_only (our_hello)) ? "friend-only" : "public", "HELLO", GNUNET_HELLO_size (our_hello)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# refreshed my HELLO"), 1, GNUNET_NO); if (NULL != hello_cb) hello_cb (hello_cb_cls, GST_hello_get ()); GNUNET_PEERINFO_add_peer (GST_peerinfo, our_hello, NULL, NULL); hello_task = GNUNET_SCHEDULER_add_delayed (HELLO_REFRESH_PERIOD, &refresh_hello_task, NULL); }
/** * Initialize a normal client. We got a start message from this * client, add him to the list of clients for broadcasting of inbound * messages. * * @param cls unused * @param client the client * @param message the start message that was sent */ static void clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { const struct StartMessage *start; struct TransportClient *tc; uint32_t options; tc = lookup_client (client); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "Client %p sent START\n", tc); if (tc != NULL) { /* got 'start' twice from the same client, not allowed */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, "TransportClient %p ServerClient %p sent multiple START messages\n", tc, tc->client); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } start = (const struct StartMessage *) message; options = ntohl (start->options); if ((0 != (1 & options)) && (0 != memcmp (&start->self, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity)))) { /* client thinks this is a different peer, reject */ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Rejecting control connection from peer `%s', which is not me!\n"), GNUNET_i2s (&start->self)); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } tc = setup_client (client); tc->send_payload = (0 != (2 & options)); unicast (tc, GST_hello_get (), GNUNET_NO); GST_neighbours_iterate (¬ify_client_about_neighbour, tc); GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, tc); GNUNET_SERVER_receive_done (client, GNUNET_OK); }
/** * Initiate transport service. * * @param cls closure * @param server the initialized server * @param c configuration to use */ static void run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { char *keyfile; struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded tmp; /* setup globals */ GST_cfg = c; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", &keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Transport service is lacking key configuration settings. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } GST_my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); GNUNET_free (keyfile); if (GST_my_private_key == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Transport service could not access hostkey. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } GST_stats = GNUNET_STATISTICS_create ("transport", c); GST_peerinfo = GNUNET_PEERINFO_connect (c); memset (&GST_my_public_key, '\0', sizeof (GST_my_public_key)); memset (&tmp, '\0', sizeof (tmp)); GNUNET_CRYPTO_rsa_key_get_public (GST_my_private_key, &GST_my_public_key); GNUNET_CRYPTO_hash (&GST_my_public_key, sizeof (GST_my_public_key), &GST_my_identity.hashPubKey); GNUNET_assert (NULL != GST_my_private_key); GNUNET_assert (0 != memcmp (&GST_my_public_key, &tmp, sizeof (GST_my_public_key))); GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); if (GST_peerinfo == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not access PEERINFO service. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); return; } /* start subsystems */ GST_hello_start (&process_hello_update, NULL); GNUNET_assert (NULL != GST_hello_get()); GST_blacklist_start (server); GST_ats = GNUNET_ATS_scheduling_init (GST_cfg, &ats_request_address_change, NULL); GST_plugins_load (&plugin_env_receive_callback, &plugin_env_address_change_notification, &plugin_env_session_end, &plugin_env_address_to_type); GST_neighbours_start (NULL, &neighbours_connect_notification, &neighbours_disconnect_notification, &neighbours_address_notification); GST_clients_start (server); GST_validation_start (); }
/** * Function called with the result from blacklisting. * Send a PING to the other peer if a communication is allowed. * * @param cls our 'struct ValidationEntry' * @param pid identity of the other peer * @param result GNUNET_OK if the connection is allowed, GNUNET_NO if not */ static void transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid, int result) { struct ValidationEntry *ve = cls; struct TransportPingMessage ping; struct GNUNET_TRANSPORT_PluginFunctions *papi; const struct GNUNET_MessageHeader *hello; ssize_t ret; size_t tsize; size_t slen; uint16_t hsize; ve->bc = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitting plain PING to `%s' %s\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address)); slen = strlen (ve->address->transport_name) + 1; hello = GST_hello_get (); hsize = ntohs (hello->size); tsize = sizeof (struct TransportPingMessage) + ve->address->address_length + slen + hsize; ping.header.size = htons (sizeof (struct TransportPingMessage) + ve->address->address_length + slen); ping.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING); ping.challenge = htonl (ve->challenge); ping.target = *pid; if (tsize >= GNUNET_SERVER_MAX_MESSAGE_SIZE) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Not transmitting `%s' with `%s', message too big (%u bytes!). This should not happen.\n"), "HELLO", "PING", (unsigned int) tsize); /* message too big (!?), get rid of HELLO */ hsize = 0; tsize = sizeof (struct TransportPingMessage) + ve->address->address_length + slen + hsize; } { char message_buf[tsize]; /* build message with structure: * [HELLO][TransportPingMessage][Transport name][Address] */ memcpy (message_buf, hello, hsize); memcpy (&message_buf[hsize], &ping, sizeof (struct TransportPingMessage)); memcpy (&message_buf[sizeof (struct TransportPingMessage) + hsize], ve->address->transport_name, slen); memcpy (&message_buf[sizeof (struct TransportPingMessage) + slen + hsize], ve->address, ve->address->address_length); papi = GST_plugins_find (ve->address->transport_name); if (papi == NULL) ret = -1; else { GNUNET_assert (papi->send != NULL); GNUNET_assert (papi->get_session != NULL); struct Session * session = papi->get_session(papi->cls, ve->address); if (session != NULL) { ret = papi->send (papi->cls, session, message_buf, tsize, PING_PRIORITY, ACCEPTABLE_PING_DELAY, NULL, NULL); } else { /* Could not get a valid session */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Could not get a valid session for `%s' %s\n", GNUNET_i2s (pid), GST_plugins_a2s (ve->address)); ret = -1; } } } if (-1 != ret) { ve->send_time = GNUNET_TIME_absolute_get (); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# PING without HELLO messages sent"), 1, GNUNET_NO); ve->expecting_pong = GNUNET_YES; } }