예제 #1
0
/**
 * Send buffer datagram to specified destination `to'.
 *
 * @returns amount of bytes written, or -1 on error with errno set.
 */
static ssize_t
tx_dgram_sendto(txdrv_t *tx, const gnet_host_t *to,
	gconstpointer data, size_t len)
{
	ssize_t r;
	struct attr *attr = tx->opaque;

	if (gnet_host_get_port(to) > 0) {
		r = bio_sendto(attr->bio, to, data, len);
	} else {
		errno = EINVAL;
		r = -1;
	}
	if ((ssize_t) -1 == r)
		return tx_dgram_write_error(tx, to, "tx_dgram_sendto");

	if (attr->cb->add_tx_written != NULL)
		attr->cb->add_tx_written(tx->owner, r);

	inet_udp_record_sent(gnet_host_get_addr(to));

	return r;
}
예제 #2
0
/**
 * Send message block to IP:port.
 *
 * @param us		the UDP scheduler
 * @param mb		the message to send
 * @param to		the IP:port destination of the message
 * @param tx		the TX stack sending the message
 * @param cb		callback actions on the datagram
 *
 * @return TRUE if message was sent or dropped, FALSE if there is no more
 * bandwidth to send anything.
 */
static bool
udp_sched_mb_sendto(udp_sched_t *us, pmsg_t *mb, const gnet_host_t *to,
	const txdrv_t *tx, const struct tx_dgram_cb *cb)
{
	ssize_t r;
	int len = pmsg_size(mb);
	bio_source_t *bio = NULL;

	if (0 == gnet_host_get_port(to))
		return TRUE;

	/*
	 * Check whether message still needs to be sent.
	 */

	if (!pmsg_hook_check(mb))
		return TRUE;			/* Dropped */

	/*
	 * Select the proper I/O source depending on the network address type.
	 */

	switch (gnet_host_get_net(to)) {
	case NET_TYPE_IPV4:
		bio = us->bio[UDP_SCHED_IPv4];
		break;
	case NET_TYPE_IPV6:
		bio = us->bio[UDP_SCHED_IPv6];
		break;
	case NET_TYPE_NONE:
	case NET_TYPE_LOCAL:
		g_assert_not_reached();
	}

	/*
	 * If there is no I/O source, then the socket to send that type of traffic
	 * was cleared, hence we simply need to discard the message.
	 */

	if (NULL == bio) {
		udp_sched_log(4, "%p: discarding mb=%p (%d bytes) to %s",
			us, mb, pmsg_size(mb), gnet_host_to_string(to));
		return udp_tx_drop(tx, cb);		/* TRUE, for "sent" */
	}

	/*
	 * OK, proceed if we have bandwidth.
	 */

	r = bio_sendto(bio, to, pmsg_start(mb), len);

	if (r < 0) {		/* Error, or no bandwidth */
		if (udp_sched_write_error(us, to, mb, G_STRFUNC)) {
			udp_sched_log(4, "%p: dropped mb=%p (%d bytes): %m",
				us, mb, pmsg_size(mb));
			return udp_tx_drop(tx, cb);	/* TRUE, for "sent" */
		}
		udp_sched_log(3, "%p: no bandwidth for mb=%p (%d bytes)",
			us, mb, pmsg_size(mb));
		us->used_all = TRUE;
		return FALSE;
	}

	if (r != len) {
		g_warning("%s: partial UDP write (%zd bytes) to %s "
			"for %d-byte datagram",
			G_STRFUNC, r, gnet_host_to_string(to), len);
	} else {
		udp_sched_log(5, "%p: sent mb=%p (%d bytes) prio=%u",
			us, mb, pmsg_size(mb), pmsg_prio(mb));
		pmsg_mark_sent(mb);
		if (cb->msg_account != NULL)
			(*cb->msg_account)(tx->owner, mb);

		inet_udp_record_sent(gnet_host_get_addr(to));
	}

	return TRUE;		/* Message sent */
}