示例#1
0
const char *
bitzi_fj_to_string(bitzi_fj_t fj)
{
	STATIC_ASSERT(NUM_BITZI_FJ == G_N_ELEMENTS(bitzi_fj_table));
	g_assert(UNSIGNED(fj) < G_N_ELEMENTS(bitzi_fj_table));
	return Q_(bitzi_fj_table[UNSIGNED(fj)]);
}
示例#2
0
文件: ctl.c 项目: MrJoe/gtk-gnutella
/**
 * Compare two characters.
 */
static int
charcmp(char a, char b)
{
	return
		a == b ? 0 :
		UNSIGNED(a) < UNSIGNED(b) ? -1 : +1;
}
示例#3
0
/**
 * Get the type of message intuited from the start of a G2 packet.
 *
 * @param start		start of message
 * @param len		amount of consecutive bytes we have so far
 *
 * @return the message type if we can intuit it, G2_MSG_MAX otherwise.
 */
enum g2_msg
g2_msg_type(const void *start, size_t len)
{
	const char *name;
	size_t namelen;
	bool known;
	void *val;
	int type;

	g2_msg_init();

	name = g2_frame_name(start, len, &namelen);
	if (NULL == name)
		return G2_MSG_MAX;

	known = patricia_lookup_extended_k(g2_msg_pt, name, namelen*8, NULL, &val);

	if (!known)
		return G2_MSG_MAX;

	type = pointer_to_int(val);

	g_assert((uint) type < UNSIGNED(G2_MSG_MAX));

	return type;
}
示例#4
0
void
gnet_stats_count_flowc(const void *head, bool head_only)
{
	uint t;
	uint16 size = gmsg_size(head) + GTA_HEADER_SIZE;
	uint8 function = gnutella_header_get_function(head);
	uint8 ttl = gnutella_header_get_ttl(head);
	uint8 hops = gnutella_header_get_hops(head);

	g_assert(thread_is_main());

	if (GNET_PROPERTY(node_debug) > 3)
		g_debug("FLOWC function=%d ttl=%d hops=%d", function, ttl, hops);

	/*
	 * Adjust for Kademlia messages.
	 */

	if (GTA_MSG_DHT == function && size >= KDA_HEADER_SIZE && !head_only) {
		uint8 opcode = kademlia_header_get_function(head);

		if (UNSIGNED(opcode + MSG_DHT_BASE) < G_N_ELEMENTS(stats_lut)) {
			t = stats_lut[opcode + MSG_DHT_BASE];
		} else {
			t = stats_lut[function];		/* Invalid opcode? */
		}
		hops = 0;
		ttl = 0;
	} else {
		t = stats_lut[function];
	}

	gnet_stats_flowc_internal(t, function, ttl, hops, size);
}
示例#5
0
/**
 * Write data to stream.
 *
 * @param os		the output stream
 * @param data		start of data to write
 * @param len		length of data to write
 *
 * @return size of data written, -1 on error.
 */
ssize_t
ostream_write(ostream_t *os, const void *data, size_t len)
{
	ssize_t w = (ssize_t) -1;

	ostream_check(os);
	len = MIN(len, MAX_INT_VAL(ssize_t));

	switch (os->type) {
	case OSTREAM_T_FILE:
		{
			size_t n = fwrite(data, len, 1, os->u.f);
			w = (0 == n) ? -1 : (ssize_t) len;
		}
		break;
	case OSTREAM_T_FD:
		w = write(os->u.fd, data, len);
		break;
	case OSTREAM_T_MEM:
		pmsg_slist_append(os->u.sl, data, len);
		w = len;
		break;
	case OSTREAM_T_PMSG:
		w = pmsg_write(os->u.mb, data, len);
		w = (len == UNSIGNED(w)) ? w : -1;
		break;
	case OSTREAM_T_MAX:
		g_assert_not_reached();
	}

	if (-1 == w)
		os->ioerr = TRUE;

	return w;
}
示例#6
0
/**
 * Grab random data from file and feed them to the specified routine.
 *
 * @param path		pathname where random data are expected
 * @param rfd		random filling routine to feed data
 * @param len		amount of random bytes to read
 *
 * @return the amount of bytes fed if OK, a short count or -1 on error,
 * with errno set.
 */
ssize_t
frand_restore(const char *path, feed_fn_t rfd, size_t len)
{
    char buf[256];
    int fd;
    ssize_t bytes_read = 0;

    fd = file_open_missing(path, O_RDONLY);

    if (-1 == fd)
        return -1;

    while (len != 0) {
        size_t n = MIN(len, sizeof buf);
        ssize_t r;

        r = read(fd, buf, n);
        if (-1 == r)
            break;
        bytes_read += r;
        (*rfd)(buf, r);
        if (UNSIGNED(r) != n)
            break;
        len -= n;
    }

    ZERO(buf);		/* Leave no memory trail */
    close(fd);
    return bytes_read;
}
示例#7
0
/**
 * Use specified random filler to create a file full of random bytes.
 *
 * @param path		pathname where random data should be generated
 * @param rfn		random number buffer-filling routine to use
 * @param len		amount of random bytes to generate
 *
 * @return the amount of bytes generated if OK, a short count or -1 on error,
 * with errno set.
 */
ssize_t
frand_save(const char *path, randfill_fn_t rfn, size_t len)
{
    char buf[256];
    int fd;
    ssize_t written = 0;

    fd = file_create(path, O_WRONLY, S_IRUSR | S_IWUSR);

    if (-1 == fd)
        return -1;

    while (len != 0) {
        size_t n = MIN(len, sizeof buf);
        ssize_t w;

        (*rfn)(buf, n);
        w = write(fd, buf, n);
        if (-1 == w)
            break;
        written += w;
        if (UNSIGNED(w) != n)
            break;
        len -= n;
    }

    ZERO(buf);		/* Leave no memory trail */
    close(fd);
    return written;
}
示例#8
0
void
bdump(int datf)
{
	int i;
	unsigned char dat[DBM_BBLKSIZ];
	filestat_t buf;
	unsigned long b;
	unsigned long used = 0;
	unsigned long total;

	if (-1 == fstat(datf, &buf))
		return;

	for (b = 0; b < UNSIGNED(buf.st_size); b += DBM_BBLKSIZ * DBM_BBLKSIZ * 8) {
		if ((fileoffset_t) -1 == lseek(datf, b, SEEK_SET))
			oops("seek failed: offset %lu", b);
		if (-1 == read(datf, dat, sizeof dat))
			oops("read failed: offset %lu", b);
		for (i = 0; i < DBM_BBLKSIZ; i++)
			used += bits_set(dat[i]);
	}

	total = buf.st_size / DBM_BBLKSIZ;
	if (buf.st_size % DBM_BBLKSIZ)
		total++;

	printf("%lu blocks used / %lu total (%.2f%% used)\n",
		used, total, used * 100.0 / (total ? total : 1));
}
示例#9
0
文件: keys.c 项目: lucab/gtk-gnutella
/**
 * @return key decimation factor for expiration
 */
double
keys_decimation_factor(const kuid_t *key)
{
	size_t common;
	int delta;
	uint8 frontier;

	common = kuid_common_prefix(get_our_kuid(), key);

	/*
	 * The furthest frontier is important because it determines whether
	 * we need to apply timing decimation on published keys.
	 * Relying solely on the exploration of our subtree is not enough
	 * since there can be some aberration in the vincinity of our KUID.
	 *
	 * Correct it with the theoretical furthest bit value, determined
	 * from the estimated DHT size, putting the frontier as further away
	 * as possible.
	 */

	frontier = MIN(kball.furthest_bits, kball.theoretical_bits);

	/*
	 * If key falls within our k-ball, no decimation.
	 */

	if (common >= frontier || !kball.seeded)
		return 1.0;

	delta = kball.furthest_bits - common;

	g_assert(delta > 0 && UNSIGNED(delta) < G_N_ELEMENTS(decimation_factor));

	return decimation_factor[delta];
}
示例#10
0
/**
 * Retry publishing after some delay.
 *
 * @param pe		the entry to publish
 * @param delay		delay in seconds
 * @param msg		if non-NULL, logging message explaining the delay
 */
static void
publisher_retry(struct publisher_entry *pe, int delay, const char *msg)
{
	struct pubdata *pd;

	publisher_check(pe);
	g_assert(NULL == pe->publish_ev);
	g_assert(delay > 0);

	pd = get_pubdata(pe->sha1);
	if (pd != NULL) {
		pd->next_enqueue = time_advance(tm_time(), UNSIGNED(delay));
		dbmw_write(db_pubdata, pe->sha1, pd, sizeof *pd);
	}

	pe->publish_ev = cq_insert(publish_cq, delay * 1000, handle_entry, pe);
	pe->last_delayed = tm_time();

	if (GNET_PROPERTY(publisher_debug) > 3) {
		shared_file_t *sf = shared_file_by_sha1(pe->sha1);
		g_debug("PUBLISHER will retry SHA-1 %s %s\"%s\" in %s: %s",
			sha1_to_string(pe->sha1),
			(sf && sf != SHARE_REBUILDING && shared_file_is_partial(sf)) ?
				"partial " : "",
			(sf && sf != SHARE_REBUILDING) ? shared_file_name_nfc(sf) : "",
			compact_time(delay), msg != NULL ? msg : "<no reason>");
		shared_file_unref(&sf);
	}
}
示例#11
0
void
gnet_stats_count_sent(const gnutella_node_t *n,
	uint8 type, const void *base, uint32 size)
{
	uint t = stats_lut[type];
	gnet_stats_t *stats;
	uint8 hops;

	g_assert(t != MSG_UNKNOWN);
	g_assert(thread_is_main());
	g_assert(!NODE_TALKS_G2(n));

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	/*
	 * Adjust for Kademlia messages.
	 */

	if (GTA_MSG_DHT == type && size >= KDA_HEADER_SIZE) {
		uint8 opcode = kademlia_header_get_function(base);

		if (UNSIGNED(opcode + MSG_DHT_BASE) < G_N_ELEMENTS(stats_lut)) {
			t = stats_lut[opcode + MSG_DHT_BASE];
		}
		hops = 0;
	} else {
		hops = gnutella_header_get_hops(base);
	}

	gnet_stats_count_sent_internal(n, t, hops, size, stats);
}
示例#12
0
/**
 * Write new value in-place for the pair at index ``i'' on the page.
 *
 * @return 0 if OK, -1 on error with errno set.
 */
int
replpair(DBM *db, char *pag, int i, datum val)
{
	unsigned koff;
	unsigned voff;
	unsigned short *ino = (unsigned short *) pag;

	g_assert(UNSIGNED(i) + 1 <= ino[0]);

	voff = offset(ino[i + 1]);

#ifdef BIGDATA
	if (is_big(ino[i + 1]))
		return big_replace(db, pag + voff, val.dptr, val.dsize);
#else
	(void) db;		/* Parameter unused if no BIGDATA */
#endif

	koff = offset(ino[i]);

	g_assert(koff - voff == val.dsize);

	memcpy(pag + voff, val.dptr, val.dsize);
	return 0;
}
示例#13
0
/**
 * Convert a message type to a symbolic name.
 *
 * @param type		the G2 message type
 *
 * @return the message symbolic name if we can intuit it, "UNKNOWN" otherwise.
 */
const char *
g2_msg_type_name(const enum g2_msg type)
{
	if G_UNLIKELY((uint) type >= UNSIGNED(G2_MSG_MAX))
		return "UNKNOWN";

	return g2_msg_symbolic_names[type];
}
示例#14
0
/**
 * Initialize internal state for our incremental zlib stream.
 *
 * @param zs		the zlib stream structure to initialize
 * @param data		input data to process; if NULL, will be incrementally given
 * @param len		length of data to process (if data not NULL) or estimation
 * @param dest		where processed data should go, or NULL if allocated
 * @param destlen	length of supplied output buffer, if dest != NULL
 */
static void
zlib_stream_init(zlib_stream_t *zs,
                 const void *data, size_t len, void *dest, size_t destlen)
{
    z_streamp z;

    g_assert(size_is_non_negative(len));
    g_assert(size_is_non_negative(destlen));

    zs->in = data;
    zs->inlen = data ? len : 0;
    zs->inlen_total = zs->inlen;

    /*
     * When deflating zlib requires normally 0.1% more + 12 bytes, we use
     * 0.5% to be safe.
     *
     * When inflating, assume we'll double the input at least.
     */

    if (NULL == dest) {
        /* Processed data go to a dynamically allocated buffer */
        if (!zs->allocated) {
            if (data == NULL && len == 0)
                len = 512;

            if (ZLIB_DEFLATER_MAGIC == zs->magic) {
                zs->outlen = (len * 1.005 + 12.0);
                g_assert(zs->outlen > len);
                g_assert(zs->outlen - len >= 12);
            } else {
                zs->outlen = UNSIGNED(len) * 2;
            }

            zs->out = halloc(zs->outlen);
            zs->allocated = TRUE;
        }
    } else {
        /* Processed data go to a supplied buffer, not-resizable */
        if (zs->allocated)
            hfree(zs->out);
        zs->out = dest;
        zs->outlen = destlen;
        zs->allocated = FALSE;
    }

    /*
     * Initialize Z stream.
     */

    z = zs->z;
    g_assert(z != NULL);			/* Stream not closed yet */

    z->next_out = zs->out;
    z->avail_out = zs->outlen;
    z->next_in = deconstify_pointer(zs->in);
    z->avail_in = 0;			/* Will be set by zlib_xxx_step() */
}
示例#15
0
文件: adns.c 项目: MrJoe/gtk-gnutella
/**
 * Callback function for inputevt_add(). This function pipes the query to
 * the server using the pipe in non-blocking mode, partial writes are handled
 * appropriately. In case of an unrecoverable error the query pipe will be
 * closed and the blocking adns_fallback() will be invoked.
 */
static void
adns_query_callback(void *data, int dest, inputevt_cond_t condition)
{
	adns_async_write_t *remain = data;

	g_assert(NULL != remain);
	g_assert(NULL != remain->buf);
	g_assert(remain->pos < remain->size);
	g_assert(dest == adns_query_fd);
	g_assert(0 != adns_query_event_id);

	if (condition & INPUT_EVENT_EXCEPTION) {
		g_warning("%s: write exception", G_STRFUNC);
		goto abort;
	}

	while (remain->pos < remain->size) {
		ssize_t ret;
		size_t n;

		n = remain->size - remain->pos;
		ret = write(dest, &remain->buf[remain->pos], n);

		if (0 == ret) {
			errno = ECONNRESET;
			ret = (ssize_t) -1;
		}
		/* FALL THROUGH */
		if ((ssize_t) -1 == ret) {
			if (!is_temporary_error(errno))
				goto error;
			return;
		}

		g_assert(ret > 0);
		g_assert(UNSIGNED(ret) <= n);
		remain->pos += (size_t) ret;
	}
	g_assert(remain->pos == remain->size);

	inputevt_remove(&adns_query_event_id);

	goto done;	


error:
	g_warning("%s: write() failed: %m", G_STRFUNC);
abort:
	g_warning("%s: removed myself", G_STRFUNC);
	inputevt_remove(&adns_query_event_id);
	fd_close(&adns_query_fd);
	g_warning("%s: using fallback", G_STRFUNC);
	adns_fallback(&remain->req);
done:
	adns_async_write_free(remain);
	return;
}
示例#16
0
static inline void
tls_log_function(int level, const char *text)
{
    if (GNET_PROPERTY(tls_debug) > UNSIGNED(level)) {
        char *str = h_strdup(text);
        strchomp(str, 0);
        g_debug("TLS(%d): %s", level, str);
        hfree(str);
    }
}
示例#17
0
/**
 * @return human-readable error string for given error code.
 */
const char *
iprange_strerror(iprange_err_t errnum)
{
	STATIC_ASSERT(IPR_ERROR_COUNT == G_N_ELEMENTS(iprange_errstr));

	if (UNSIGNED(errnum) >= G_N_ELEMENTS(iprange_errstr))
		return "Invalid error code";

	return iprange_errstr[errnum];
}
示例#18
0
static inline ALWAYS_INLINE void
PIO_LOCK(int fd)
{
	ONCE_FLAG_RUN(pio_inited, pio_init_once);

	g_assert(fd >= 0);
	g_assert(UNSIGNED(fd) < pio_capacity);

	spinlock(&pio_locks[fd]);
}
示例#19
0
/**
 * @return human-readable error string corresponding to error code `errnum'.
 */
const char *
tok_strerror(tok_error_t errnum)
{
	STATIC_ASSERT(G_N_ELEMENTS(tok_errstr) == TOK_MAX_ERROR);

	if (UNSIGNED(errnum) >= G_N_ELEMENTS(tok_errstr))
		return "Invalid error code";

	return tok_errstr[errnum];
}
示例#20
0
void
gnet_stats_count_dropped(gnutella_node_t *n, msg_drop_reason_t reason)
{
	uint32 size;
	uint type;
	gnet_stats_t *stats;

	g_assert(UNSIGNED(reason) < MSG_DROP_REASON_COUNT);
	g_assert(thread_is_main());

	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	if (NODE_TALKS_G2(n)) {
		int f = g2_msg_type(n->data, n->size);
		if (f != G2_MSG_MAX) {
			f += MSG_G2_BASE;
		} else {
			f = G_N_ELEMENTS(stats_lut) - 1;	/* Last, holds MSG_UNKNOWN */
		}
		type = stats_lut[f];
		size = n->size;
	} else {
		type = stats_lut[gnutella_header_get_function(&n->header)];
		size = n->size + sizeof(n->header);
	}

	entropy_harvest_small(
		VARLEN(n->addr), VARLEN(n->port), VARLEN(reason), VARLEN(type),
		VARLEN(size), NULL);

	DROP_STATS(stats, type, size);
	node_inc_rxdrop(n);

	switch (reason) {
	case MSG_DROP_HOSTILE_IP: n->n_hostile++; break;
	case MSG_DROP_SPAM: n->n_spam++; break;
	case MSG_DROP_EVIL: n->n_evil++; break;
	default: ;
	}

	if (NODE_TALKS_G2(n)) {
		if (GNET_PROPERTY(log_dropped_g2)) {
			g2_msg_log_dropped_data(n->data, n->size,
				"from %s: %s", node_infostr(n),
				gnet_stats_drop_reason_to_string(reason));
		}
	} else {
		if (GNET_PROPERTY(log_dropped_gnutella)) {
			gmsg_log_split_dropped(&n->header, n->data, n->size,
				"from %s: %s", node_infostr(n),
				gnet_stats_drop_reason_to_string(reason));
		}
	}
}
示例#21
0
static inline ALWAYS_INLINE void
THREAD_LOCK(int fd)
{
	if G_UNLIKELY(!pio_inited)
		pio_init();

	g_assert(fd >= 0);
	g_assert(UNSIGNED(fd) < pio_capacity);

	spinlock_hidden(&pio_locks[fd]);
}
示例#22
0
/**
 * Sets the state of the browse host context to ``state'' and resets the
 * data block variables.
 */
static inline void
browse_host_next_state(struct browse_host_upload *bh, enum bh_state state)
{
	g_assert(NULL != bh);
	g_assert(UNSIGNED(state) < NUM_BH_STATES);
	bh->w_buf = NULL;
	bh->w_buf_size = 0;
	bh->b_data = NULL;
	bh->b_size = 0;
	bh->b_offset = 0;
	bh->state = state;
}
示例#23
0
/**
 * Account for dropped Kademlia message of specified opcode from node ``n''.
 */
void
gnet_dht_stats_count_dropped(gnutella_node_t *n, kda_msg_t opcode,
	msg_drop_reason_t reason)
{
	uint32 size;
	uint type;
	gnet_stats_t *stats;

	g_assert(UNSIGNED(reason) < MSG_DROP_REASON_COUNT);
	g_assert(opcode <= KDA_MSG_MAX_ID);
	g_assert(UNSIGNED(opcode + MSG_DHT_BASE) < G_N_ELEMENTS(stats_lut));
	g_assert(thread_is_main());

    size = n->size + sizeof(n->header);
	type = stats_lut[opcode + MSG_DHT_BASE];
	stats = NODE_USES_UDP(n) ? &gnet_udp_stats : &gnet_tcp_stats;

	entropy_harvest_small(
		VARLEN(n->addr), VARLEN(n->port), VARLEN(reason), VARLEN(type),
		VARLEN(size), NULL);

	DROP_STATS(stats, type, size);
	node_inc_rxdrop(n);
}
示例#24
0
static void
on_notebook_downloads_info_switch_page(GtkNotebook *unused_notebook,
	GtkNotebookPage *unused_page, int page_num, void *unused_udata)
{
	(void) unused_notebook;
	(void) unused_page;
	(void) unused_udata;

	g_return_if_fail(UNSIGNED(page_num) < NUM_DOWNLOADS_INFO_NB_PAGES);

	entropy_harvest_single(VARLEN(page_num));

	notebook_downloads_info_current_page = page_num;
	gui_prop_set_guint32_val(PROP_DOWNLOADS_INFO_NOTEBOOK_TAB, page_num);
}
示例#25
0
/**
 * Write NUL-terminated string.
 *
 * If (size_t) -1 is given as length, then it is computed via strlen(), in
 * which case the string buffer must be NUL-terminated.  Otherwise, the value
 * is taken to be the pre-computed string length.
 *
 * The string is written as: <ule64(length)><bytes>, no trailing NUL.
 */
void
pmsg_write_string(pmsg_t *mb, const char *str, size_t length)
{
	size_t len;

	g_assert(pmsg_is_writable(mb));	/* Not shared, or would corrupt data */

	len = (size_t) -1 == length ? strlen(str) : length;

	g_assert(UNSIGNED(pmsg_available(mb)) >= len + 10);	/* Need ule64 length */

	pmsg_write_ule64(mb, (uint64) len);
	if (len != 0) {
		pmsg_write(mb, str, len);
	}
}
示例#26
0
/**
 * Write NUL-terminated string, up to `n' characters or the first seen NUL
 * in the buffer, whichever comes first.
 *
 * The string is written as: <ule64(length)><bytes>, no trailing NUL.
 */
void
pmsg_write_fixed_string(pmsg_t *mb, const char *str, size_t n)
{
	size_t len;

	g_assert(pmsg_is_writable(mb));	/* Not shared, or would corrupt data */
	g_assert(UNSIGNED(pmsg_available(mb)) >= n + 10);	/* Need ule64 length */

	len = strlen(str);
	len = MIN(n, len);
	pmsg_write_ule64(mb, (uint64) len);

	if (len != 0) {
		pmsg_write(mb, str, len);
	}
}
示例#27
0
/**
 * Write I/O vector.
 *
 * @return amount of bytes written, or -1 on error.
 */
static ssize_t
tx_deflate_writev(txdrv_t *tx, iovec_t *iov, int iovcnt)
{
	struct attr *attr = tx->opaque;
	int sent = 0;

	if (tx_deflate_debugging(9)) {
		g_debug("TX %s: (%s) (buffer #%d, nagle %s, unflushed %zu) [%c%c]",
			G_STRFUNC, gnet_host_to_string(&tx->host), attr->fill_idx,
			(attr->flags & DF_NAGLE) ? "on" : "off", attr->unflushed,
			(attr->flags & DF_FLOWC) ? 'C' : '-',
			(attr->flags & DF_FLUSH) ? 'f' : '-');
	}

	while (iovcnt-- > 0) {
		int ret;

		/*
		 * If we're flow controlled or shut down, stop sending.
		 */

		if (attr->flags & (DF_FLOWC|DF_SHUTDOWN))
			break;

		ret = deflate_add(tx, iovec_base(iov), iovec_len(iov));

		if (-1 == ret)
			return -1;

		sent += ret;
		if (UNSIGNED(ret) < iovec_len(iov)) {
			/* Could not write all, flow-controlled */
			break;
		}
		iov++;
	}

	if (tx_deflate_debugging(9)) {
		g_debug("TX %s: (%s) sent %lu bytes (buffer #%d, nagle %s, "
			"unflushed %zu) [%c%c]", G_STRFUNC,
			gnet_host_to_string(&tx->host), (ulong) sent, attr->fill_idx,
			(attr->flags & DF_NAGLE) ? "on" : "off", attr->unflushed,
			(attr->flags & DF_FLOWC) ? 'C' : '-',
			(attr->flags & DF_FLUSH) ? 'f' : '-');
	}
	return sent;
}
示例#28
0
/**
 * Write NUL-terminated string, up to `n' characters or the first seen NUL
 * in the buffer, whichever comes first.
 *
 * The string is written as: <ule64(length)><bytes>, no trailing NUL.
 */
void
pmsg_write_fixed_string(pmsg_t *mb, const char *str, size_t n)
{
	size_t len;

	g_assert(pmsg_is_writable(mb));	/* Not shared, or would corrupt data */
	g_assert(UNSIGNED(pmsg_available(mb)) >= n + 10);	/* Need ule64 length */
	g_assert_log(size_is_non_negative(n), "%s(): n=%zd", G_STRFUNC, n);

	len = vstrlen(str);
	len = MIN(n, len);
	pmsg_write_ule64(mb, (uint64) len);

	if (len != 0) {
		pmsg_write(mb, str, len);
	}
}
示例#29
0
/**
 * Create new message holding serialized tree.
 *
 * @param t			the tree to serialize
 * @param prio		priority of the message
 * @param freecb	if non-NULL, the free routine to attach to message
 * @param arg		additional argument for the free routine
 *
 * @return a message containing the serialized tree.
 */
static pmsg_t *
g2_build_pmsg_prio(const g2_tree_t *t, int prio, pmsg_free_t freecb, void *arg)
{
	size_t len;
	pmsg_t *mb;

	len = g2_frame_serialize(t, NULL, 0);
	if (NULL == freecb)
		mb = pmsg_new(prio, NULL, len);
	else
		mb = pmsg_new_extend(prio, NULL, len, freecb, arg);
	g2_frame_serialize(t, pmsg_start(mb), len);
	pmsg_seek(mb, len);

	g_assert(UNSIGNED(pmsg_size(mb)) == len);

	return mb;
}
示例#30
0
/**
 * Write NUL-terminated string.
 *
 * If (size_t) -1 is given as length, then it is computed via strlen(), in
 * which case the string buffer must be NUL-terminated.  Otherwise, the value
 * is taken to be the pre-computed string length.
 *
 * The string is written as: <ule64(length)><bytes>, no trailing NUL.
 */
void
pmsg_write_string(pmsg_t *mb, const char *str, size_t length)
{
	size_t len;

	g_assert(pmsg_is_writable(mb));	/* Not shared, or would corrupt data */
	g_assert_log(size_is_non_negative(length) || (size_t) -1 == length,
		"%s(): length=%zd", G_STRFUNC, length);

	len = (size_t) -1 == length ? strlen(str) : length;

	g_assert(UNSIGNED(pmsg_available(mb)) >= len + 10);	/* Need ule64 length */

	pmsg_write_ule64(mb, (uint64) len);
	if (len != 0) {
		pmsg_write(mb, str, len);
	}
}