/** * Read the friends file. */ static void read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg) { char *fn; char *data; size_t pos; struct GNUNET_PeerIdentity pid; uint64_t fsize; struct GNUNET_CRYPTO_HashAsciiEncoded enc; unsigned int entries_found; struct Peer *fl; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "TOPOLOGY", "FRIENDS", &fn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "topology", "FRIENDS"); return; } if (GNUNET_OK != GNUNET_DISK_file_test (fn)) GNUNET_DISK_fn_write (fn, NULL, 0, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if (GNUNET_OK != GNUNET_DISK_file_size (fn, &fsize, GNUNET_NO, GNUNET_YES)) { if ((friends_only) || (minimum_friend_count > 0)) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not read friends list `%s'\n"), fn); GNUNET_free (fn); return; } if (fsize == 0) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Friends file `%s' is empty.\n"), fn); GNUNET_free (fn); return; } data = GNUNET_malloc_large (fsize); if (data == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read friends list from `%s': out of memory\n"), fn); GNUNET_free (fn); return; } if (fsize != GNUNET_DISK_fn_read (fn, data, fsize)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read friends list from `%s'\n"), fn); GNUNET_free (fn); GNUNET_free (data); return; } entries_found = 0; pos = 0; while ((pos < fsize) && isspace ((unsigned char) data[pos])) pos++; while ((fsize >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) && (pos <= fsize - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded))) { memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)); if (!isspace ((unsigned char) enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1])) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Syntax error in topology specification at offset %llu, skipping bytes.\n"), (unsigned long long) pos); pos++; while ((pos < fsize) && (!isspace ((unsigned char) data[pos]))) pos++; continue; } enc.encoding[sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1] = '\0'; if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string ((char *) &enc, &pid.hashPubKey)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Syntax error in topology specification at offset %llu, skipping bytes `%s'.\n"), (unsigned long long) pos, &enc); } else { if (0 != memcmp (&pid, &my_identity, sizeof (struct GNUNET_PeerIdentity))) { entries_found++; fl = make_peer (&pid, NULL, GNUNET_YES); GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Found friend `%s' in configuration\n"), GNUNET_i2s (&fl->pid)); } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Found myself `%s' in friend list (useless, ignored)\n"), GNUNET_i2s (&pid)); } } pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded); while ((pos < fsize) && isspace ((unsigned char) data[pos])) pos++; } GNUNET_free (data); GNUNET_free (fn); GNUNET_STATISTICS_update (stats, gettext_noop ("# friends in configuration"), entries_found, GNUNET_NO); if ((minimum_friend_count > entries_found) && (friends_only == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("Fewer friends specified than required by minimum friend count. Will only connect to friends.\n")); } if ((minimum_friend_count > target_connection_count) && (friends_only == GNUNET_NO)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ ("More friendly connections required than target total number of connections.\n")); } }
/** * Try to read the HELLOs in the given filename and discard expired * addresses. Removes the file if one the HELLO is malformed. If all * addresses are expired, the HELLO is also removed (but the HELLO * with the public key is still returned if it was found and valid). * The file can contain multiple HELLO messages. * * @param fn name of the file * @param unlink_garbage if #GNUNET_YES, try to remove useless files * @param r ReadHostFileContext to store the resutl */ static void read_host_file (const char *fn, int unlink_garbage, struct ReadHostFileContext *r) { char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN; unsigned int size_total; struct GNUNET_TIME_Absolute now; unsigned int left; const struct GNUNET_HELLO_Message *hello; struct GNUNET_HELLO_Message *hello_clean; unsigned read_pos; int size_hello; r->friend_only_hello = NULL; r->hello = NULL; if (GNUNET_YES != GNUNET_DISK_file_test (fn)) return; size_total = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %u bytes from `%s'\n", size_total, fn); if (size_total < sizeof (struct GNUNET_MessageHeader)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO in file `%s': %s\n"), fn, "Fail has invalid size"); if ( (GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); return; } read_pos = 0; while (read_pos < size_total) { hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos]; size_hello = GNUNET_HELLO_size (hello); if (0 == size_hello) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO in file `%s'\n"), fn); if ((GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); return; } now = GNUNET_TIME_absolute_get (); hello_clean = GNUNET_HELLO_iterate_addresses (hello, GNUNET_YES, &discard_expired, &now); if (NULL == hello_clean) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to parse HELLO in file `%s'\n"), fn); if ((GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) && (ENOENT != errno) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); return; } left = 0; (void) GNUNET_HELLO_iterate_addresses (hello_clean, GNUNET_NO, &count_addresses, &left); if (0 == left) { GNUNET_free (hello_clean); break; } if (GNUNET_NO == GNUNET_HELLO_is_friend_only (hello_clean)) { if (NULL == r->hello) r->hello = hello_clean; else { GNUNET_break (0); GNUNET_free (r->hello); r->hello = hello_clean; } } else { if (NULL == r->friend_only_hello) r->friend_only_hello = hello_clean; else { GNUNET_break (0); GNUNET_free (r->friend_only_hello); r->friend_only_hello = hello_clean; } } read_pos += size_hello; } if (0 == left) { /* no addresses left, remove from disk */ if ( (GNUNET_YES == unlink_garbage) && (0 != UNLINK (fn)) ) GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", fn); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found `%s' and `%s' HELLO message in file\n", (NULL != r->hello) ? "public" : "NON-public", (NULL != r->friend_only_hello) ? "friend only" : "NO friend only"); }
/** * Load a set of hosts from a configuration file. * * @param filename file with the host specification * @param cfg the configuration to use as a template while starting a controller * on any of the loaded hosts. Operation queue sizes specific to a host * are also read from this configuration handle * @param hosts set to the hosts found in the file; caller must free this if * number of hosts returned is greater than 0 * @return number of hosts returned in 'hosts', 0 on error */ unsigned int GNUNET_TESTBED_hosts_load_from_file (const char *filename, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTBED_Host ***hosts) { struct GNUNET_TESTBED_Host *starting_host; char *data; char *buf; char *username; char *hostname; regex_t rex; regmatch_t pmatch[6]; uint64_t fs; short int port; unsigned int offset; unsigned int count; GNUNET_assert (NULL != filename); if (GNUNET_YES != GNUNET_DISK_file_test (filename)) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Hosts file %s not found\n"), filename); return 0; } if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES)) fs = 0; if (0 == fs) { LOG (GNUNET_ERROR_TYPE_WARNING, _("Hosts file %s has no data\n"), filename); return 0; } data = GNUNET_malloc (fs); if (fs != GNUNET_DISK_fn_read (filename, data, fs)) { GNUNET_free (data); LOG (GNUNET_ERROR_TYPE_WARNING, _("Hosts file %s cannot be read\n"), filename); return 0; } buf = data; offset = 0; starting_host = NULL; count = 0; /* refer RFC 952 and RFC 1123 for valid hostnames */ GNUNET_assert (0 == regcomp (&rex, "^(([[:alnum:]]+)@)?" /* username */ "([[:alnum:]]+[-[:alnum:]_\\.]+)" /* hostname */ "(:([[:digit:]]{1,5}))?", /* port */ REG_EXTENDED | REG_ICASE)); while (offset < (fs - 1)) { offset++; if (((data[offset] == '\n')) && (buf != &data[offset])) { unsigned int size; data[offset] = '\0'; username = NULL; hostname = NULL; port = 0; if ((REG_NOMATCH == regexec (&rex, buf, 6, pmatch, 0)) || (-1 == pmatch[3].rm_so)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Error reading line `%s' in hostfile\n", buf); buf = &data[offset + 1]; continue; } if (-1 != pmatch[2].rm_so) { size = pmatch[2].rm_eo - pmatch[2].rm_so; username = GNUNET_malloc (size + 1); username[size] = '\0'; GNUNET_assert (NULL != strncpy (username, buf + pmatch[2].rm_so, size)); } if (-1 != pmatch[5].rm_so) { (void) SSCANF (buf + pmatch[5].rm_so, "%5hd", &port); } size = pmatch[3].rm_eo - pmatch[3].rm_so; hostname = GNUNET_malloc (size + 1); hostname[size] = '\0'; GNUNET_assert (NULL != strncpy (hostname, buf + pmatch[3].rm_so, size)); LOG (GNUNET_ERROR_TYPE_DEBUG, "Successfully read host %s, port %d and user %s from file\n", (NULL == hostname) ? "NULL" : hostname, port, (NULL == username) ? "NULL" : username); /* We store hosts in a static list; hence we only require the starting * host pointer in that list to access the newly created list of hosts */ if (NULL == starting_host) starting_host = GNUNET_TESTBED_host_create (hostname, username, cfg, port); else (void) GNUNET_TESTBED_host_create (hostname, username, cfg, port); count++; GNUNET_free_non_null (username); GNUNET_free (hostname); buf = &data[offset + 1]; } else if ((data[offset] == '\n') || (data[offset] == '\0')) buf = &data[offset + 1]; } regfree (&rex); GNUNET_free (data); if (NULL == starting_host) return 0; *hosts = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host *) * count); GNUNET_memcpy (*hosts, &host_list[GNUNET_TESTBED_host_get_id_ (starting_host)], sizeof (struct GNUNET_TESTBED_Host *) * count); return count; }
static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct GNUNET_TESTING_Host *hosts; struct GNUNET_TESTING_Host *hostpos; struct GNUNET_TESTING_Host *temphost; char *hostfile; struct stat frstat; char *buf; char *data; int count; int ret; ok = 1; #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n"); #endif if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers", &num_peers)) num_peers = DEFAULT_NUM_PEERS; GNUNET_assert (num_peers > 0 && num_peers < (unsigned long long) -1); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "hostfile", &hostfile)) hostfile = NULL; hosts = NULL; data = NULL; if (hostfile != NULL) { if (GNUNET_OK != GNUNET_DISK_file_test (hostfile)) GNUNET_DISK_fn_write (hostfile, NULL, 0, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not open file specified for host list, ending test!"); ok = 1119; GNUNET_free (hostfile); return; } data = GNUNET_malloc_large (frstat.st_size); GNUNET_assert (data != NULL); if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not read file %s specified for host list, ending test!", hostfile); GNUNET_free (hostfile); GNUNET_free (data); return; } GNUNET_free_non_null (hostfile); buf = data; count = 0; while (count < frstat.st_size) { count++; if (count >= frstat.st_size) break; /* if (((data[count] == '\n') || (data[count] == '\0')) && (buf != &data[count])) */ if (((data[count] == '\n')) && (buf != &data[count])) { data[count] = '\0'; temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host)); ret = SSCANF (buf, "%a[a-zA-Z0-9]@%a[a-zA-Z0-9.]:%hd", &temphost->username, &temphost->hostname, &temphost->port); if (3 == ret) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Successfully read host %s, port %d and user %s from file\n", temphost->hostname, temphost->port, temphost->username); } else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Error reading line `%s' in hostfile\n", buf); GNUNET_free (temphost); buf = &data[count + 1]; continue; } /* temphost->hostname = buf; */ temphost->next = hosts; hosts = temphost; buf = &data[count + 1]; } else if ((data[count] == '\n') || (data[count] == '\0')) buf = &data[count + 1]; } } peers_left = num_peers; pg = GNUNET_TESTING_daemons_start (cfg, peers_left, /* Total number of peers */ peers_left, /* Number of outstanding connections */ peers_left, /* Number of parallel ssh connections, or peers being started at once */ TIMEOUT, NULL, NULL, &my_cb, NULL, NULL, NULL, hosts); hostpos = hosts; while (hostpos != NULL) { temphost = hostpos->next; GNUNET_free (hostpos->hostname); GNUNET_free (hostpos->username); GNUNET_free (hostpos); hostpos = temphost; } GNUNET_free_non_null (data); GNUNET_assert (pg != NULL); }