/** * Attach meta information to supplied message block, returning a possibly * new message block to use. */ static pmsg_t * mq_udp_attach_metadata(pmsg_t *mb, const gnet_host_t *to) { pmsg_t *result; if (pmsg_is_extended(mb)) { struct mq_udp_info_extended *mi; WALLOC(mi); gnet_host_copy(&mi->to, to); result = mb; /* * Replace original free routine with the new one, saving the original * metadata and its free routine in the new metadata for later * transparent dispatching at free time. */ mi->orig_free = pmsg_replace_ext(mb, mq_udp_pmsg_free_extended, mi, &mi->orig_arg); } else { struct mq_udp_info *mi; WALLOC(mi); gnet_host_copy(&mi->to, to); result = pmsg_clone_extend(mb, mq_udp_pmsg_free, mi); pmsg_free(mb); } g_assert(pmsg_is_extended(result)); return result; }
/** * Insert `key' into the list. * * It is safe to call this routine whilst iterating although there is no * guarantee as to whether the iteration will see the new item. */ void hash_list_insert_sorted(hash_list_t *hl, const void *key, cmp_fn_t func) { link_t *lk; hash_list_check(hl); g_assert(NULL != func); g_assert(!hikset_contains(hl->ht, key)); for (lk = elist_first(&hl->list); lk != NULL; lk = elist_next(lk)) { struct hash_list_item *item = ITEM(lk); if ((*func)(key, item->key) <= 0) break; } if (NULL == lk) { hash_list_append(hl, key); } else { struct hash_list_item *item; WALLOC(item); item->key = key; /* Inserting ``item'' before ``lk'' */ elist_link_insert_before(&hl->list, lk, &item->lnk); hash_list_insert_item(hl, item); } }
/** * Adds the given node to the gui. */ void nodes_gui_add_node(gnet_node_info_t *info) { static const struct node_data zero_data; struct node_data *data; gnet_node_flags_t flags; g_return_if_fail(info); g_return_if_fail(!htable_contains(nodes_handles, info->node_id)); WALLOC(data); *data = zero_data; data->node_id = nid_ref(info->node_id); data->user_agent = info->vendor ? atom_str_get(info->vendor) : NULL; data->country = info->country; data->host_size = w_concat_strings(&data->host, host_addr_port_to_string(info->addr, info->port), (void *) 0); str_bprintf(data->version, sizeof data->version, "%u.%u", info->proto_major, info->proto_minor); guc_node_fill_flags(data->node_id, &flags); nodes_gui_update_node_flags(data, &flags); htable_insert(nodes_handles, data->node_id, data); gtk_list_store_append(nodes_model, &data->iter); gtk_list_store_set(nodes_model, &data->iter, 0, data, (-1)); }
/** * Process returned value from GetConnectionTypeInfo(). * * @return walloc()'ed structure (whose size is written in lenp) containing * the decompiled arguments, or NULL if the returned arguments cannot be * processed. */ static void * upnp_ctrl_ret_GetConnectionTypeInfo(nv_table_t *ret, size_t *lenp) { struct upnp_GetConnectionTypeInfo *r; const char *type, *possible; type = nv_table_lookup_str(ret, "NewConnectionType"); if (NULL == type) return NULL; possible = nv_table_lookup_str(ret, "NewPossibleConnectionTypes"); if (NULL == possible) return NULL; /* * We can freely reference the memory from the name/value table since * that table will remain alive until we are done with user notification. */ WALLOC(r); r->connection_type = type; r->possible_types = possible; *lenp = sizeof *r; return r; }
/** * Initialize the driver. * * Always succeeds, so never returns NULL. */ static gpointer tx_link_init(txdrv_t *tx, gpointer args) { struct tx_link_args *targs = args; struct attr *attr; g_assert(tx); g_assert(targs->cb != NULL); WALLOC(attr); /* * Because we handle servicing of the upper layers explicitely within * the TX stack (i.e. upper layers detect that we were unable to comply * with the whole write and enable us), there is no I/O callback attached * to the I/O source: we only create it to benefit from bandwidth limiting * through calls to bio_write() and bio_writev(). */ attr->cb = targs->cb; attr->wio = targs->wio; attr->bio = bsched_source_add(targs->bws, attr->wio, BIO_F_WRITE, NULL, NULL); tx->opaque = attr; g_assert(attr->wio->write != NULL); g_assert(attr->wio->writev != NULL); return tx; /* OK */ }
/** * Replace a key/value pair in the table. * * If the key already existed, the old key/values are replaced by the new ones, * at the same position. Otherwise, the key is appended. * * @return TRUE when replacement occurred (the key existed). */ bool ohash_table_replace(ohash_table_t *oh, const void *key, const void *value) { struct ohash_pair pk; struct ohash_pair *op; const void *hkey; void *pos = NULL; ohash_table_check(oh); pk.oh = oh; pk.key = key; if (hash_list_find(oh->hl, &pk, &hkey)) { op = deconstify_pointer(hkey); g_assert(op->oh == oh); pos = hash_list_remove_position(oh->hl, &pk); } else { WALLOC(op); op->oh = oh; op->key = key; } op->value = value; if (pos != NULL) { hash_list_insert_position(oh->hl, op, pos); } else { hash_list_append(oh->hl, op); } return pos != NULL; }
/** * Insert a new event in the callout queue and return an opaque handle that * can be used to cancel the event. * * The event is specified to occur in some "delay" amount of time, at which * time we shall call fn(cq, arg), where cq is the callout queue from * where we triggered, and arg is an additional argument. * * @param cq The callout queue * @param delay The delay, expressed in cq's "virtual time" (see cq_clock) * @param fn The callback function * @param arg The argument to be passed to the callback function * * @returns the handle, or NULL on error. */ cevent_t * cq_insert(cqueue_t *cq, int delay, cq_service_t fn, void *arg) { cevent_t *ev; /* Event to insert */ cqueue_check(cq); g_assert(fn); g_assert(delay >= 0); WALLOC(ev); ev->ce_magic = CEVENT_MAGIC; ev->ce_time = cq->cq_time + delay; ev->ce_fn = fn; ev->ce_arg = arg; ev->ce_cq = cq; /* * For performance reasons, use hidden locks: we know the ev_link() * routine is not going to take locks, so it is safe. */ CQ_LOCK(cq); ev_link(ev); CQ_UNLOCK(cq); return ev; }
static gboolean spam_add_name_and_size(const char *name, filesize_t min_size, filesize_t max_size) { struct namesize_item *item; int error; g_return_val_if_fail(name, TRUE); g_return_val_if_fail(min_size <= max_size, TRUE); WALLOC(item); error = regcomp(&item->pattern, name, REG_EXTENDED | REG_NOSUB); if (error) { char buf[1024]; regerror(error, &item->pattern, buf, sizeof buf); g_warning("spam_add_name_and_size(): regcomp() failed: %s", buf); regfree(&item->pattern); WFREE(item); return TRUE; } else { item->min_size = min_size; item->max_size = max_size; spam_lut.sl_names = g_slist_prepend(spam_lut.sl_names, item); return FALSE; } }
static void upload_stats_add(const char *pathname, filesize_t size, const char *name, guint32 attempts, guint32 complete, guint64 ul_bytes, time_t rtime, time_t dtime, const struct sha1 *sha1) { static const struct ul_stats zero_stats; struct ul_stats *s; g_assert(pathname != NULL); g_assert(name != NULL); WALLOC(s); *s = zero_stats; s->pathname = atom_str_get(pathname); s->filename = atom_str_get(name); s->size = size; s->attempts = attempts; s->complete = complete; s->norm = size > 0 ? 1.0 * ul_bytes / size : 0.0; s->bytes_sent = ul_bytes; s->rtime = rtime; s->dtime = dtime; s->sha1 = sha1 ? atom_sha1_get(sha1) : NULL; if (!upload_stats_list) { g_assert(!upload_stats_by_sha1); upload_stats_list = hash_list_new(ul_stats_hash, ul_stats_eq); upload_stats_by_sha1 = g_hash_table_new(sha1_hash, sha1_eq); } hash_list_append(upload_stats_list, s); if (s->sha1) gm_hash_table_insert_const(upload_stats_by_sha1, s->sha1, s); gcu_upload_stats_gui_add(s); }
/** * Create a new search queue. */ squeue_t * sq_make(struct gnutella_node *node) { squeue_t *sq; /* * By initializing `last_sent' to the current time and not to `0', we * ensure that we won't send the query to the node during the first * "search_queue_spacing" seconds of its connection. This prevent * useless traffic on Gnet, because if the connection is held for that * long, chances are it will hold until we get some results back. * * --RAM, 01/05/2002 */ WALLOC(sq); sq->count = 0; sq->last_sent = tm_time(); sq->searches = NULL; sq->n_sent = 0; sq->n_dropped = 0; sq->node = node; sq->handles = hset_create(HASH_KEY_SELF, 0); return sq; }
/** * Creates an incremental zlib deflater for `len' bytes starting at `data', * with specified compression `level'. * * @param data data to compress; if NULL, will be incrementally given * @param len length of data to compress (if data not NULL) or estimation * @param dest where compressed data should go, or NULL if allocated * @param destlen length of supplied output buffer, if dest != NULL * @param level compression level, between 0 and 9. * * @return new deflater, or NULL if error. */ static zlib_deflater_t * zlib_deflater_alloc( const void *data, size_t len, void *dest, size_t destlen, int level) { zlib_deflater_t *zd; z_streamp outz; int ret; g_assert(size_is_non_negative(len)); g_assert(size_is_non_negative(destlen)); g_assert(level == Z_DEFAULT_COMPRESSION || (level >= 0 && level <= 9)); WALLOC(outz); outz->zalloc = zlib_alloc_func; outz->zfree = zlib_free_func; outz->opaque = NULL; ret = deflateInit(outz, level); if (ret != Z_OK) { WFREE(outz); g_carp("%s(): unable to initialize compressor: %s", G_STRFUNC, zlib_strerror(ret)); return NULL; } WALLOC0(zd); zd->zs.magic = ZLIB_DEFLATER_MAGIC; zd->zs.z = outz; zd->zs.closed = FALSE; zlib_stream_init(&zd->zs, data, len, dest, destlen); return zd; }
/** * Request asynchronous DNS resolution for item, prior to inserting to * the whitelist or updating the existing host address (when revalidating). */ static void whitelist_dns_resolve(struct whitelist *item, bool revalidate) { struct whitelist_dns *ctx; char *host; g_assert(item != NULL); g_assert(revalidate || !is_host_addr(item->addr)); g_assert(item->host != NULL); /* * Since resolution is normally going to happen asynchronously, we must * keep track of the generation at which the resolution was requested. */ WALLOC(ctx); ctx->item = item; ctx->generation = whitelist_generation; ctx->revalidate = revalidate; host = item->host->name; if (adns_resolve(host, settings_dns_net(), whitelist_dns_cb, ctx)) { /* Asynchronous resolution */ if (GNET_PROPERTY(whitelist_debug) > 1) log_whitelist_item(item, "asynchronously resolving"); } else { /* Synchronous resolution, whitelist_dns_cb() already called */ } }
/** * Send time synchronization request to specified node. * * When node_id is non-zero, it refers to the connected node to which * we're sending the time synchronization request. */ void tsync_send(struct gnutella_node *n, const struct nid *node_id) { struct tsync *ts; g_return_if_fail(n->port != 0); if (!NODE_IS_WRITABLE(n)) return; WALLOC(ts); ts->magic = TSYNC_MAGIC; tm_now_exact(&ts->sent); ts->sent.tv_sec = clock_loc2gmt(ts->sent.tv_sec); ts->node_id = nid_ref(node_id); ts->udp = booleanize(NODE_IS_UDP(n)); /* * As far as time synchronization goes, we must get the reply within * the next TSYNC_EXPIRE_MS millisecs. */ ts->expire_ev = cq_main_insert(TSYNC_EXPIRE_MS, tsync_expire, ts); hevset_insert(tsync_by_time, ts); vmsg_send_time_sync_req(n, GNET_PROPERTY(ntp_detected), &ts->sent); }
/** * Allocate a new descriptor for managing large keys and values. */ DBMBIG * big_alloc(const char *datname, int flags, int mode) { DBMBIG *dbg; struct datfile *file; WALLOC0(dbg); dbg->fd = -1; dbg->bitbno = -1; WALLOC(file); file->datname = h_strdup(datname); file->flags = flags; file->mode = mode; dbg->file = file; /* * If the .dat file exists and O_TRUNC was given in the flags and the * database is opened for writing, then the database is re-initialized: * unlink the .dat file, which will be re-created on-demand. */ if ((flags & (O_RDWR | O_WRONLY)) && (flags & O_TRUNC)) { unlink(datname); } return dbg; }
void hsep_connection_init(struct gnutella_node *n, uint8 major, uint8 minor) { static const hsep_ctx_t zero_hsep; time_t now = tm_time(); uint i; g_assert(n); if (GNET_PROPERTY(hsep_debug) > 1) printf("HSEP: Initializing node %s\n", host_addr_port_to_string(n->addr, n->port)); WALLOC(n->hsep); *n->hsep = zero_hsep; /* Initializes everything to 0 */ n->hsep->last_sent = now; n->hsep->major = major; n->hsep->minor = minor; /* this is what we know before receiving the first message */ for (i = 1; i < G_N_ELEMENTS(hsep_global_table); i++) { n->hsep->table[i][HSEP_IDX_NODES] = 1; hsep_global_table[i][HSEP_IDX_NODES]++; } hsep_sanity_check(); hsep_fire_global_table_changed(now); }
/** * Remove `data' from the list but remembers the item's position so that * re-insertion can happen at the same place using the supplied token. * * If no re-insertion is required, the token must be freed with * hash_list_forget_position(). * * @return a token that can be used to re-insert the key at the same * position in the list via hash_list_insert_position(), or NULL if * the data was not found. */ void * hash_list_remove_position(hash_list_t *hl, const void *key) { struct hash_list_item *item; struct hash_list_position *pt; hash_list_check(hl); g_assert(1 == hl->refcount); item = hikset_lookup(hl->ht, key); if (NULL == item) return NULL; /* * Record position in the list so that re-insertion can happen after * the predecessor of the item. For sanity checks, we save the hash_list_t * object as well to make sure items are re-inserted in the proper list! * * No unsafe update (moving / deletion) must happen between the removal and * the re-insertion, and this is checked by the saved stamp. */ WALLOC(pt); pt->magic = HASH_LIST_POSITION_MAGIC; pt->hl = hl; pt->prev = elist_prev(&item->lnk); pt->stamp = hl->stamp; hash_list_remove_item(hl, item); return pt; }
static struct file_object * file_object_alloc(const int fd, const char * const pathname, int accmode) { static const struct file_object zero_fo; struct file_object *fo; hikset_t *ht; g_return_val_if_fail(fd >= 0, NULL); g_return_val_if_fail(pathname, NULL); g_return_val_if_fail(is_absolute_path(pathname), NULL); g_return_val_if_fail(!file_object_find(pathname, accmode), NULL); ht = file_object_mode_get_table(accmode); g_return_val_if_fail(ht, NULL); WALLOC(fo); *fo = zero_fo; fo->magic = FILE_OBJECT_MAGIC; fo->ref_count = 1; fo->fd = fd; fo->accmode = accmode; fo->pathname = atom_str_get(pathname); file_object_check(fo); g_assert(is_valid_fd(fo->fd)); hikset_insert(ht, fo); return fo; }
/** * @return a pointer to a newly allocated GtkTreeIter. Must be freed * with w_tree_iter_free(). */ GtkTreeIter * w_tree_iter_new(void) { GtkTreeIter *iter; WALLOC(iter); return iter; }
/** * Creates a new THEX upload context. The context must be freed with * thex_upload_close(). * * @param owner the owner of the TX stack (the upload) * @param host the host to which we're talking to * @param writable no document * @param link_cb callbacks for the link layer * @param wio no document * @param flags opening flags * * @return An initialized THEX upload context. */ struct special_upload * thex_upload_open( void *owner, const struct gnutella_host *host, const shared_file_t *sf, special_upload_writable_t writable, const struct tx_link_cb *link_cb, struct wrap_io *wio, int flags) { struct thex_upload *ctx; WALLOC(ctx); ctx->special_upload.read = thex_upload_read; ctx->special_upload.write = thex_upload_write; ctx->special_upload.flush = thex_upload_flush; ctx->special_upload.close = thex_upload_close; ctx->tth = atom_tth_get(shared_file_tth(sf)); ctx->filesize = shared_file_size(sf); ctx->data = NULL; ctx->size = 0; ctx->offset = 0; ctx->state = THEX_STATE_INITIAL; /* * Instantiate the TX stack. */ { struct tx_link_args args; args.cb = link_cb; args.wio = wio; args.bws = bsched_out_select_by_addr(gnet_host_get_addr(host)); ctx->tx = tx_make(owner, host, tx_link_get_ops(), &args); } if (flags & THEX_UPLOAD_F_CHUNKED) { ctx->tx = tx_make_above(ctx->tx, tx_chunk_get_ops(), 0); } /* * Put stack in "eager" mode: we want to be notified whenever * we can write something. */ tx_srv_register(ctx->tx, writable, owner); tx_eager_mode(ctx->tx, TRUE); /* * Update statistics. */ gnet_prop_incr_guint32(PROP_THEX_FILES_REQUESTED); return &ctx->special_upload; }
static struct html_node * html_node_alloc(void) { struct html_node *node; WALLOC(node); *node = zero_html_node; return node; }
/** * Allocate a bin. */ static struct st_bin * bin_allocate(void) { struct st_bin *bin; WALLOC(bin); bin_initialize(bin, ST_MIN_BIN_SIZE); return bin; }
/** * Same as gtk_tree_iter_copy() but uses walloc(). Use w_tree_iter_free() * to free the returned GtkTreeIter. */ GtkTreeIter * w_tree_iter_copy(GtkTreeIter *iter) { GtkTreeIter *copy; WALLOC(copy); *copy = *iter; /* Struct copy */ return copy; }
static struct html_view * html_view_alloc(void) { static const struct html_view zero_html_view; struct html_view *ctx; WALLOC(ctx); *ctx = zero_html_view; return ctx; }
static struct html_context * html_context_alloc(void) { static const struct html_context zero_html_context; struct html_context *ctx; WALLOC(ctx); *ctx = zero_html_context; return ctx; }
struct dime_record * dime_record_alloc(void) { static const struct dime_record zero_record; struct dime_record *record; WALLOC(record); *record = zero_record; return record; }
struct html_output * html_output_alloc(void) { static const struct html_output zero_output; struct html_output *output; WALLOC(output); *output = zero_output; return output; }
/** * Create a new attribute table. */ xattr_table_t * xattr_table_make(void) { xattr_table_t *xat; WALLOC(xat); xat->magic = XATTR_TABLE_MAGIC; xat->hl = hash_list_new(xattr_hash, xattr_eq); return xat; }
/** * Create a new namesize structure. */ namesize_t * namesize_make(const char *name, filesize_t size) { namesize_t *ns; WALLOC(ns); ns->name = atom_str_get(name); ns->size = size; return ns; }
/** * Allocate a remote security token. */ sectoken_remote_t * sectoken_remote_alloc(uint8 length) { sectoken_remote_t *token; WALLOC(token); token->length = length; token->v = length ? walloc(length) : NULL; return token; }
static struct bgtask * bg_task_alloc(void) { static const struct bgtask zero_bt; struct bgtask *bt; WALLOC(bt); *bt = zero_bt; bt->magic = BGTASK_MAGIC; return bt; }