//swaps a with b void swap(char worldA_[hsize][wsize], char worldB_[hsize][wsize]) { char wtemp[hsize][wsize]; wcopy(wtemp, worldA_); wcopy(worldA_, worldB_); wcopy(worldB_, wtemp); }
/** * Fill cache entry structure with value data, marking it dirty and present. */ static void fill_entry(const dbmw_t *dw, struct cached *entry, gpointer value, size_t length) { /* * Try to reuse old entry arena if same size. * * Also handle case where value points to the cached entry data, since * that is likely to be the case when invoked from dbmw_write() (they * issued a dbmw_read() before and changed the deserialized value from * the cache). */ if (length != (size_t) entry->len) { gpointer arena = NULL; if (length) arena = wcopy(value, length); free_value(dw, entry, TRUE); entry->data = arena; entry->len = length; } else if (value != entry->data && length) { free_value(dw, entry, FALSE); memcpy(entry->data, value, length); } entry->dirty = TRUE; entry->absent = FALSE; g_assert(!entry->len == !entry->data); }
static inline void update_row(const void *key, void *value, void *user_data) { struct node_data *data = value; time_t *now_ptr = user_data, now = *now_ptr; gnet_node_status_t status; g_assert(NULL != data); g_assert(data->node_id == key); if (!guc_node_get_status(data->node_id, &status)) return; /* * Update additional info too if it has recorded changes. */ if (remove_item(ht_node_info_changed, data->node_id)) { gnet_node_info_t info; if (guc_node_fill_info(data->node_id, &info)) { nodes_gui_update_node_info(data, &info); guc_node_clear_info(&info); } } if (remove_item(ht_node_flags_changed, data->node_id)) { gnet_node_flags_t flags; if (guc_node_fill_flags(data->node_id, &flags)) { nodes_gui_update_node_flags(data, &flags); } } if (status.connect_date) data->connected = delta_time(now, status.connect_date); if (status.up_date) data->uptime = delta_time(now, status.up_date); /* Update the status line */ { const gchar *s; size_t size; s = nodes_gui_common_status_str(&status); size = 1 + strlen(s); if (size > data->info_size) { WFREE_NULL(data->info, data->info_size); data->info = wcopy(s, size); data->info_size = size; } else { memcpy(data->info, s, size); } } tree_model_iter_changed(GTK_TREE_MODEL(nodes_model), &data->iter); }
/** * Attempt Gnutella host connection. * @return TRUE if OK, FALSE if attempt was throttled */ static gboolean host_gnutella_connect(host_addr_t addr, guint16 port) { if (aging_lookup(node_connects, &addr)) return FALSE; node_add_socket(NULL, addr, port, 0); aging_insert(node_connects, wcopy(&addr, sizeof addr), GUINT_TO_POINTER(1)); return TRUE; }
static GSList * resolve_hostname(const char *host, enum net_type net) #ifdef HAS_GETADDRINFO { static const struct addrinfo zero_hints; struct addrinfo hints, *ai, *ai0 = NULL; hset_t *hs; GSList *sl_addr; int error; g_assert(host); hints = zero_hints; hints.ai_family = net_type_to_pf(net); error = getaddrinfo(host, NULL, &hints, &ai0); if (error) { g_message("getaddrinfo() failed for \"%s\": %s", host, gai_strerror(error)); return NULL; } sl_addr = NULL; hs = hset_create_any(host_addr_hash_func, NULL, host_addr_eq_func); for (ai = ai0; ai; ai = ai->ai_next) { host_addr_t addr; if (!ai->ai_addr) continue; addr = addrinfo_to_addr(ai); if (is_host_addr(addr) && !hset_contains(hs, &addr)) { host_addr_t *addr_copy; addr_copy = wcopy(&addr, sizeof addr); sl_addr = g_slist_prepend(sl_addr, addr_copy); hset_insert(hs, addr_copy); } } hset_free_null(&hs); if (ai0) freeaddrinfo(ai0); return g_slist_reverse(sl_addr); }
/** * Allocate a new entry in the cache to hold the deserialized value. * * @param dw the DBM wrapper * @param key key we want a cache entry for * @param filled optionally, a new cache entry already filled with the data * * @attention * An older cache entry structure can be returned, and it will still * point to the previous data. Caller should normally invoke fill_entry() * immediately to make sure these stale data are not associated wrongly * with the new key, or supply his own filled structure directly. * * @return a cache entry object that can be filled with the value. */ static struct cached * allocate_entry(dbmw_t *dw, gconstpointer key, struct cached *filled) { struct cached *entry; gpointer saved_key; g_assert(!hash_list_contains(dw->keys, key)); g_assert(!map_contains(dw->values, key)); g_assert(!filled || (!filled->len == !filled->data)); saved_key = wcopy(key, dbmw_keylen(dw, key)); /* * If we have less keys cached than our maximum, add it. * Otherwise evict the least recently used key, at the head. */ if (hash_list_length(dw->keys) < dw->max_cached) { if (filled) entry = filled; else WALLOC0(entry); } else { gpointer head; g_assert(hash_list_length(dw->keys) == dw->max_cached); head = hash_list_head(dw->keys); entry = remove_entry(dw, head, filled != NULL, TRUE); g_assert(filled != NULL || entry != NULL); if (filled) entry = filled; } /* * Add entry into cache. */ g_assert(entry); hash_list_append(dw->keys, saved_key); map_insert(dw->values, saved_key, entry); return entry; }
/** * Allocate a "spill" buffer of size `size'. */ static adns_async_write_t * adns_async_write_alloc(const struct adns_request *req, const void *buf, size_t size) { adns_async_write_t *remain; g_assert(req); g_assert(buf); g_assert(size > 0); WALLOC(remain); remain->req = *req; remain->size = size; remain->buf = wcopy(buf, remain->size); remain->pos = 0; return remain; }
/** * Send a Gnutella ping message to the specified host. * * @param m the Ping message to send * @param size size of the Ping message, in bytes * @param addr address to which ping should be sent * @param port port number * @param cb if non-NULL, callback to invoke on reply or timeout * @param arg additional callback argument * @param multiple whether multiple replies (Pongs) are expected * * @return TRUE if we sent the ping, FALSE it we throttled it. */ static bool udp_send_ping_with_callback( gnutella_msg_init_t *m, uint32 size, const host_addr_t addr, uint16 port, udp_ping_cb_t cb, void *arg, bool multiple) { struct gnutella_node *n = node_udp_get_addr_port(addr, port); if (n != NULL) { const guid_t *muid = gnutella_header_get_muid(m); if (udp_ping_register(muid, addr, port, cb, arg, multiple)) { aging_insert(udp_aging_pings, wcopy(&addr, sizeof addr), GUINT_TO_POINTER(1)); udp_send_msg(n, m, size); return TRUE; } } return FALSE; }
/** * Count a word that has been seen. */ static void search_stats_tally(const word_vec_t *vec) { struct term_counts *val; if (vec->word[1] == '\0' || vec->word[2] == '\0') return; val = htable_lookup(stat_hash, vec->word); if (val) { val->period_cnt++; } else { const char *key; WALLOC0(val); val->period_cnt = vec->amount; key = wcopy(vec->word, 1 + strlen(vec->word)); htable_insert(stat_hash, key, val); } }
wchar_t * qStringToWideChar(const QString &str) { if (str.isNull()) { return NULL; } wchar_t *result = new wchar_t[str.length() + 1]; if (result) { #if __STDC_WANT_SECURE_LIB__ wcopy_s(result, str.length() + 1, (const wchar_t *)str.unicode(), str.length()); #else wcopy(result, (const wchar_t *) str.unicode(), str.length()); #endif return result; } else { return NULL; } }
/** * Map iterator to record security tokens in the database. */ static void record_token(void *key, void *value, void *unused_u) { kuid_t *id = key; lookup_token_t *ltok = value; struct tokdata td; (void) unused_u; td.last_update = ltok->retrieved; td.length = ltok->token->length; td.token = td.length ? wcopy(ltok->token->v, td.length) : NULL; if (GNET_PROPERTY(dht_tcache_debug) > 4) { char buf[80]; bin_to_hex_buf(td.token, td.length, buf, sizeof buf); g_debug("DHT TCACHE adding security token for %s: %u-byte \"%s\"", kuid_to_hex_string(id), td.length, buf); } /* * Data is put in the DBMW cache and the dynamically allocated token * will be freed via free_tokdata() when the cached entry is released. */ if (!dbmw_exists(db_tokdata, id->v)) gnet_stats_inc_general(GNR_DHT_CACHED_TOKENS_HELD); dbmw_write(db_tokdata, id->v, &td, sizeof td); if (GNET_PROPERTY(dht_tcache_debug_flags) & DBG_DSF_USR1) { g_debug("DHT TCACHE %s: stats=%s, count=%zu, id=%s", G_STRFUNC, uint64_to_string( gnet_stats_get_general(GNR_DHT_CACHED_TOKENS_HELD)), dbmw_count(db_tokdata), kuid_to_hex_string(id)); } }
static struct magnet_source * magnet_parse_path(const char *path, const char **error_str) { static const struct magnet_source zero_ms; struct magnet_source ms; const char *p, *endptr; clear_error_str(&error_str); g_return_val_if_fail(path, NULL); ms = zero_ms; p = path; if ('/' != *p) { *error_str = "Expected path starting with '/'"; /* Skip this parameter */ return NULL; } g_assert(*p == '/'); endptr = is_strprefix(p, "/uri-res/N2R?"); if (endptr) { struct sha1 sha1; p = endptr; if (!urn_get_sha1(p, &sha1)) { *error_str = "Bad SHA1 in MAGNET URI"; return NULL; } ms.sha1 = atom_sha1_get(&sha1); } else { ms.path = atom_str_get(p); } return wcopy(&ms, sizeof ms); }
struct magnet_source * magnet_source_new(void) { static const struct magnet_source zero_source; return wcopy(&zero_source, sizeof zero_source); }
/** * Read value from database file, returning a pointer to the allocated * deserialized data. These data can be modified freely and stored back, * but their lifetime will not exceed that of the next call to a dbmw * operation on the same descriptor. * * User code does not need to bother with freeing the allocated data, this * is managed directly by the DBM wrapper. * * @param dw the DBM wrapper * @param key the key (constant-width, determined at open time) * @param lenptr if non-NULL, writes length of (deserialized) value * * @return pointer to value, or NULL if it was either not found or the * deserialization failed. */ G_GNUC_HOT gpointer dbmw_read(dbmw_t *dw, gconstpointer key, size_t *lenptr) { struct cached *entry; dbmap_datum_t dval; dbmw_check(dw); g_assert(key); dw->r_access++; entry = map_lookup(dw->values, key); if (entry) { dw->r_hits++; if (lenptr) *lenptr = entry->len; return entry->data; } /* * Not cached, must read from DB. */ dw->ioerr = FALSE; dval = dbmap_lookup(dw->dm, key); if (dbmap_has_ioerr(dw->dm)) { dw->ioerr = TRUE; dw->error = errno; g_warning("DBMW \"%s\" I/O error whilst reading entry: %s", dw->name, dbmap_strerror(dw->dm)); return NULL; } else if (NULL == dval.data) return NULL; /* Not found in DB */ /* * Value was found, allocate a cache entry object for it. */ WALLOC0(entry); /* * Deserialize data if needed. */ if (dw->unpack) { /* * Allocate cache entry arena to hold the deserialized version. */ entry->data = walloc(dw->value_size); entry->len = dw->value_size; bstr_reset(dw->bs, dval.data, dval.len, BSTR_F_ERROR); if (!dbmw_deserialize(dw, dw->bs, entry->data, dw->value_size)) { g_carp("DBMW \"%s\" deserialization error in %s(): %s", dw->name, stacktrace_routine_name(func_to_pointer(dw->unpack), FALSE), bstr_error(dw->bs)); /* Not calling value free routine on deserialization failures */ wfree(entry->data, dw->value_size); WFREE(entry); return NULL; } if (lenptr) *lenptr = dw->value_size; } else { g_assert(dw->value_size >= dval.len); if (dval.len) { entry->len = dval.len; entry->data = wcopy(dval.data, dval.len); } else { entry->data = NULL; entry->len = 0; } if (lenptr) *lenptr = dval.len; } g_assert((entry->len != 0) == (entry->data != NULL)); /* * Insert into cache. */ (void) allocate_entry(dw, key, entry); return entry->data; }
/** * Read value from database file, returning a pointer to the allocated * deserialized data. These data can be modified freely and stored back, * but their lifetime will not exceed that of the next call to a dbmw * operation on the same descriptor. * * User code does not need to bother with freeing the allocated data, this * is managed directly by the DBM wrapper. * * @param dw the DBM wrapper * @param key the key (constant-width, determined at open time) * @param lenptr if non-NULL, writes length of (deserialized) value * * @return pointer to value, or NULL if it was either not found or the * deserialization failed. */ G_GNUC_HOT void * dbmw_read(dbmw_t *dw, const void *key, size_t *lenptr) { struct cached *entry; dbmap_datum_t dval; dbmw_check(dw); g_assert(key); dw->r_access++; entry = map_lookup(dw->values, key); if (entry) { if (dbg_ds_debugging(dw->dbg, 5, DBG_DSF_CACHING | DBG_DSF_ACCESS)) { dbg_ds_log(dw->dbg, dw, "%s: read cache hit on %s key=%s%s", G_STRFUNC, entry->dirty ? "dirty" : "clean", dbg_ds_keystr(dw->dbg, key, (size_t) -1), entry->absent ? " (absent)" : ""); } dw->r_hits++; if (lenptr) *lenptr = entry->len; return entry->data; } /* * Not cached, must read from DB. */ dw->ioerr = FALSE; dval = dbmap_lookup(dw->dm, key); if (dbmap_has_ioerr(dw->dm)) { dw->ioerr = TRUE; dw->error = errno; s_warning_once_per(LOG_PERIOD_SECOND, "DBMW \"%s\" I/O error whilst reading entry: %s", dw->name, dbmap_strerror(dw->dm)); return NULL; } else if (NULL == dval.data) return NULL; /* Not found in DB */ /* * Value was found, allocate a cache entry object for it. */ WALLOC0(entry); /* * Deserialize data if needed. */ if (dw->unpack) { /* * Allocate cache entry arena to hold the deserialized version. */ entry->data = walloc(dw->value_size); entry->len = dw->value_size; bstr_reset(dw->bs, dval.data, dval.len, BSTR_F_ERROR); if (!dbmw_deserialize(dw, dw->bs, entry->data, dw->value_size)) { s_critical("DBMW \"%s\" deserialization error in %s(): %s", dw->name, stacktrace_function_name(dw->unpack), bstr_error(dw->bs)); /* Not calling value free routine on deserialization failures */ wfree(entry->data, dw->value_size); WFREE(entry); return NULL; } if (lenptr) *lenptr = dw->value_size; } else { g_assert(dw->value_size >= dval.len); if (dval.len) { entry->len = dval.len; entry->data = wcopy(dval.data, dval.len); } else { entry->data = NULL; entry->len = 0; } if (lenptr) *lenptr = dval.len; } g_assert((entry->len != 0) == (entry->data != NULL)); /* * Insert into cache. */ (void) allocate_entry(dw, key, entry); if (dbg_ds_debugging(dw->dbg, 4, DBG_DSF_CACHING)) { dbg_ds_log(dw->dbg, dw, "%s: cached %s key=%s%s", G_STRFUNC, entry->dirty ? "dirty" : "clean", dbg_ds_keystr(dw->dbg, key, (size_t) -1), entry->absent ? " (absent)" : ""); } return entry->data; }
/** * Return a duplicate of given host. */ gnet_host_t * gnet_host_dup(const gnet_host_t *h) { return wcopy(h, gnet_host_length(h)); }
void wcat(wchar_t *dest, const wchar_t *src, size_t pos) { wchar_t *dpos = dest + pos; wcopy(dpos, src, wcslen(src)); }
struct magnet_resource * magnet_parse(const char *url, const char **error_str) { static const struct magnet_resource zero_resource; struct magnet_resource res; const char *p, *next; res = zero_resource; clear_error_str(&error_str); p = is_strcaseprefix(url, "magnet:"); if (!p) { *error_str = "Not a MAGNET URI"; return NULL; } if ('?' != p[0]) { *error_str = "Invalid MAGNET URI"; return NULL; } p++; for (/* NOTHING */; p && '\0' != p[0]; p = next) { enum magnet_key key; const char *endptr; char name[16]; /* Large enough to hold longest key we know */ name[0] = '\0'; endptr = strchr(p, '='); if (endptr && p != endptr) { size_t name_len; name_len = endptr - p; g_assert(size_is_positive(name_len)); if (name_len < sizeof name) { /* Ignore overlong key */ strncat(name, p, name_len); } p = &endptr[1]; /* Point behind the '=' */ } endptr = strchr(p, '&'); if (!endptr) { endptr = strchr(p, '\0'); } key = magnet_key_get(name); if (MAGNET_KEY_NONE == key) { g_message("skipping unknown key \"%s\" in MAGNET URI", name); } else { char *value; size_t value_len; value_len = endptr - p; value = h_strndup(p, value_len); plus_to_space(value); if (url_unescape(value, TRUE)) { magnet_handle_key(&res, name, value); } else { g_message("badly encoded value in MAGNET URI: \"%s\"", value); } HFREE_NULL(value); } while ('&' == endptr[0]) { endptr++; } next = endptr; } res.sources = g_slist_reverse(res.sources); res.searches = g_slist_reverse(res.searches); return wcopy(&res, sizeof res); }