/** * Generate a new random (modern) message ID for pings. */ void guid_ping_muid(struct guid *muid) { guid_random_fill(muid); guid_flag_modern(muid); guid_flag_gtkg(muid); /* Mark as being from GTKG */ }
/** * Generate a new GUID atom that is not already conflicting with any other * GUID recorded in the supplied hikset (hash set with values pointing to * the GUID key). * * @attention * It is up to the caller to later insert the value referencing this GUID in * the hikset to prevent further duplicates. To avoid race conditions between * the checking of the hiset and the insertion, the hikset should be locked * if it is shared by multiple threads. * * @param hik the hikset against which we need to check for duplicates * @param gtkg whether to flag the GUID as being generated by GTKG. * * @return a new unique GUID atom. */ const guid_t * guid_unique_atom(const hikset_t *hik, bool gtkg) { int i; guid_t guid; entropy_harvest_time(); for (i = 0; i < 100; i++) { guid_random_fill(&guid); if (gtkg) guid_flag_gtkg(&guid); /* Mark as being from GTKG */ if (NULL == hikset_lookup(hik, &guid)) return atom_guid_get(&guid); } g_error("%s(): no luck with random number generator", G_STRFUNC); }
/** * Generate GUID for a query with OOB results delivery. * If `initial' is false, this is a requery. * * Bytes 0 to 3 if the GUID are the 4 octet bytes of the IP address. * Bytes 13 and 14 are the little endian representation of the port. * Byte 15 holds an HEC with bit 0 indicating a requery. */ void guid_query_oob_muid(struct guid *muid, const host_addr_t addr, uint16 port, bool initial) { uint32 ip; g_assert(host_addr_is_ipv4(addr)); guid_random_fill(muid); ip = host_addr_ipv4(addr); poke_be32(&muid->v[0], ip); poke_le16(&muid->v[13], port); guid_flag_oob_gtkg(muid); /* Mark as being from GTKG */ if (initial) muid->v[15] &= ~GUID_REQUERY; else muid->v[15] |= GUID_REQUERY; }
/** * Generate a new random message ID for queries. * If `initial' is false, this is a requery. */ void guid_query_muid(struct guid *muid, bool initial) { guid_random_fill(muid); /* * Since 2012-10-07, we call guid_flag_oob_gtkg() instead of * guid_flag_gtkg() to mark the MUID of the query, regardless of * whether it is sent out as an OOB query. * * That way, even if it is OOB-proxied by an ultrapeer, we will * be able to recognize the markup. */ guid_flag_oob_gtkg(muid); /* Mark as being from GTKG */ if (initial) muid->v[15] &= ~GUID_REQUERY; else muid->v[15] |= GUID_REQUERY; }
/** * Determine unique filename for `file' in `path', with optional trailing * extension `ext'. If no `ext' is wanted, one must supply an empty string. * * @param path A directory path. * @param file The basename for the resulting pathname. * @param ext An optional filename extension to be appended to the basename. * @param name_is_uniq An optional callback to decide whether a created * pathname is uniq. If omitted, the default is file_does_not_exist(). * * @returns the chosen unique complete filename as a pointer which must be * freed via hfree(). */ char * filename_unique(const char *path, const char *name, const char *ext, bool (*name_is_uniq)(const char *pathname)) { char filename_buf[FILENAME_MAXBYTES]; char name_buf[FILENAME_MAXBYTES]; char mid_buf[32]; char ext_buf[32]; const char *mid; char *pathname; size_t name_len, mid_len, ext_len; int i; g_assert(path); g_assert(name); g_assert(ext); g_assert(is_absolute_path(path)); STATIC_ASSERT(sizeof filename_buf > sizeof mid_buf + sizeof ext_buf + GUID_HEX_SIZE); /** * NOTE: The generated filename must not exceed FILENAME_MAXBYTES * because such a file cannot be created. In reality, it depends * on the filesystem as well and the limit might be even smaller. * In any case, we don't want to cut-off arbitrary bytes but * at least preserve the filename extension and the (potential) * UTF-8 encoding. */ /* Because "ext" can be an additional extension like .BAD rather than * one that indicates the filetype, try to preserve the next "extension" * as well, if there's any. */ mid = strrchr(name, '.'); if (NULL == mid || mid == name || strlen(mid) >= sizeof mid_buf) { mid = strchr(name, '\0'); } ext_len = strlen(ext); mid_len = strlen(mid); name_len = strlen(name) - mid_len; ext_len = MIN(ext_len, sizeof ext_buf - 1); mid_len = MIN(mid_len, sizeof mid_buf - 1); name_len = MIN(name_len, sizeof name_buf - 1); if (name_len + mid_len + ext_len >= sizeof filename_buf) { g_assert(name_len >= ext_len); name_len -= ext_len; } /* Truncate strings so that an UTF-8 encoding is preserved */ ext_len = utf8_truncate(ext, ext_buf, ext_len + 1); mid_len = utf8_truncate(mid, mid_buf, mid_len + 1); name_len = utf8_truncate(name, name_buf, name_len + 1); str_bprintf(filename_buf, sizeof filename_buf, "%s%s%s", name_buf, mid_buf, ext_buf); pathname = unique_pathname(path, filename_buf, name_is_uniq); if (pathname) goto finish; if (!is_directory(path)) return NULL; /* * Looks like we need to make the filename more unique. Append .00, then * .01, etc... until .99. */ while (name_len + mid_len + ext_len + 3 >= sizeof filename_buf) { g_assert(name_len > 0); name_len--; } name_len = utf8_truncate(name, name_buf, name_len + 1); for (i = 0; i < 100; i++) { str_bprintf(filename_buf, sizeof filename_buf, "%s.%02u%s%s", name_buf, i, mid_buf, ext_buf); pathname = unique_pathname(path, filename_buf, name_is_uniq); if (pathname) goto finish; } /* * OK, no luck. Try with a few random numbers then. */ while (name_len + mid_len + ext_len + 9 >= sizeof filename_buf) { g_assert(name_len > 0); name_len--; } name_len = utf8_truncate(name, name_buf, name_len + 1); for (i = 0; i < 100; i++) { str_bprintf(filename_buf, sizeof filename_buf, "%s.%x%s%s", name_buf, (unsigned) random_u32(), mid_buf, ext_buf); pathname = unique_pathname(path, filename_buf, name_is_uniq); if (pathname) goto finish; } /* * Bad luck. Allocate a random GUID then. */ while ( name_len + mid_len + ext_len + GUID_HEX_SIZE + 1 >= sizeof filename_buf ) { g_assert(name_len > 0); name_len--; } name_len = utf8_truncate(name, name_buf, name_len + 1); { struct guid guid; guid_random_fill(&guid); str_bprintf(filename_buf, sizeof filename_buf, "%s.%s%s%s", name_buf, guid_hex_str(&guid), mid_buf, ext_buf); } pathname = unique_pathname(path, filename_buf, name_is_uniq); if (pathname) goto finish; /* * This may also be the result of permission problems or inode * exhaustion. */ g_warning("%s(): no luck with random number generator", G_STRFUNC); finish: return pathname; }
/** * Generate a new random GUID, flagged as GTKG. */ void guid_random_muid(guid_t *muid) { guid_random_fill(muid); guid_flag_gtkg(muid); /* Mark as being from GTKG */ }