Beispiel #1
0
/**
 * 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;
}
Beispiel #2
0
/**
 * 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);
	}
}
Beispiel #3
0
/**
 * 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));

}
Beispiel #4
0
/**
 * 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;
}
Beispiel #5
0
/**
 * 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;
}
Beispiel #7
0
/**
 * 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;
}
Beispiel #8
0
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;
	}
}
Beispiel #9
0
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);
}
Beispiel #10
0
/**
 * 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;
}
Beispiel #11
0
/**
 * 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;
}
Beispiel #12
0
/**
 * 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 */
	}
}
Beispiel #13
0
/**
 * 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);
}
Beispiel #14
0
/**
 * 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;
}
Beispiel #15
0
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);
}
Beispiel #16
0
/**
 * 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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
/**
 * @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;
}
Beispiel #19
0
/**
 * 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;
}
Beispiel #20
0
static struct html_node *
html_node_alloc(void)
{
	struct html_node *node;

	WALLOC(node);
	*node = zero_html_node;
	return node;
}
Beispiel #21
0
/**
 * 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;
}
Beispiel #22
0
/**
 * 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;
}
Beispiel #23
0
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;
}
Beispiel #24
0
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;
}
Beispiel #25
0
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;
}
Beispiel #26
0
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;
}
Beispiel #27
0
/**
 * 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;
}
Beispiel #28
0
/**
 * 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;
}
Beispiel #29
0
/**
 * 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;
}
Beispiel #30
0
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;
}