Exemplo n.º 1
0
/**
 * Shutdown stack, disallowing further writes.
 */
void
tx_shutdown(txdrv_t *tx)
{
	txdrv_t *t;

	tx_check(tx);
	g_assert(tx->upper == NULL);

	for (t = tx; t; t = t->lower) {
		t->flags |= TX_DOWN;		/* Signal we're going down */

		/*
		 * If we reach a stage where the service routine was enabled (the
		 * lower driver was meant to call its upper layer service routine
		 * when further writing was possible), disable it.  That way, the
		 * layer-specific shutdown does not have to bother with that.
		 */

		if (t->flags & TX_SERVICE)
			tx_srv_disable(t);

		TX_SHUTDOWN(t);
	}
}
Exemplo n.º 2
0
/**
 * Service routine for UDP message queue.
 */
static void
mq_udp_service(void *data)
{
	mqueue_t *q = data;
	int r;
	GList *l;
	unsigned dropped = 0;

	mq_check(q, 0);
	g_assert(q->count);		/* Queue is serviced, we must have something */

	/*
	 * Write as much as possible.
	 */

	for (l = q->qtail; l; /* empty */) {
		pmsg_t *mb = l->data;
		int mb_size = pmsg_size(mb);
		struct mq_udp_info *mi = pmsg_get_metadata(mb);

		if (!pmsg_check(mb, q)) {
			dropped++;
			goto skip;
		}

		r = tx_sendto(q->tx_drv, mb, &mi->to);

		if (r < 0)		/* Error, drop packet and continue */
			goto skip;

		if (r == 0)		/* No more bandwidth */
			break;

		g_assert(r == mb_size);

		node_add_tx_given(q->node, r);

		if (q->flags & MQ_FLOWC)
			q->flowc_written += r;

		/*
		 * The UDP layer is non-reliable so the message could be dropped
		 * later on by lower layers.
		 *
		 * Therefore, message statistics will be updated by a specific
		 * accounting callback that is known to the datagram layer, such
		 * as node_msg_accounting().
		 */

	skip:
		if (q->qlink)
			q->cops->qlink_remove(q, l);

		/* drop the message from queue, will be freed by mq_rmlink_prev() */
		l = q->cops->rmlink_prev(q, l, mb_size);
	}

	mq_check(q, 0);
	g_assert(q->size >= 0 && q->count >= 0);

	if (dropped)
		node_add_txdrop(q->node, dropped);	/* Dropped during TX */

	/*
	 * Update flow-control information.
	 */

	q->cops->update_flowc(q);

	/*
	 * If queue is empty, disable servicing.
	 */

	if (q->size == 0) {
		g_assert(q->count == 0);
		tx_srv_disable(q->tx_drv);
		node_tx_service(q->node, FALSE);
	}

	mq_check(q, 0);
}
Exemplo n.º 3
0
/**
 * Service routine for the compressing stage.
 *
 * Called by lower layer when it is ready to process more data.
 */
static void
deflate_service(void *data)
{
	txdrv_t *tx = data;
	struct attr *attr = tx->opaque;
	struct buffer *b;

	g_assert(attr->send_idx < BUFFER_COUNT);

	if (tx_deflate_debugging(9)) {
		g_debug("TX %s: (%s) %s(buffer #%d, %zu bytes held) [%c%c]",
			G_STRFUNC, gnet_host_to_string(&tx->host),
			(tx->flags & TX_ERROR) ? "ERROR " : "",
			attr->send_idx,
			attr->send_idx >= 0 ?
				(attr->buf[attr->send_idx].wptr -
					attr->buf[attr->send_idx].rptr) : 0,
			(attr->flags & DF_FLOWC) ? 'C' : '-',
			(attr->flags & DF_FLUSH) ? 'f' : '-');
	}
	/*
	 * First, attempt to transmit the whole send buffer, if any pending.
	 */

	if (attr->send_idx >= 0)
		deflate_send(tx);			/* Send buffer `send_idx' */

	if (attr->send_idx >= 0)		/* Could not send it entirely */
		return;						/* Done, servicing still enabled */

	/*
	 * NB: In the following operations, order matters.  In particular, we
	 * must disable the servicing before attempting to service the upper
	 * layer, since the data it will send us can cause us to flow control
	 * and re-enable the servicing.
	 *
	 * If the `fill' buffer is full, try to send it now.
	 */

	b = &attr->buf[attr->fill_idx];	/* Buffer we fill */

	if (b->wptr >= b->end) {
		if (tx_deflate_debugging(9)) {
			g_debug("TX %s: (%s) sending fill buffer #%d, %zu bytes",
				G_STRFUNC, gnet_host_to_string(&tx->host), attr->fill_idx,
				b->wptr - b->rptr);
		}
		deflate_rotate_and_send(tx);	/* Can set TX_ERROR */

		if (tx->flags & TX_ERROR)
			return;
	}

	/*
	 * If we were able to send the whole send buffer, disable servicing.
	 */

	if (-1 == attr->send_idx)
		tx_srv_disable(tx->lower);

	/*
	 * If we entered flow control, we can now safely leave it, since we
	 * have at least a free `fill' buffer.
	 */

	if (attr->flags & DF_FLOWC)
		deflate_set_flowc(tx, FALSE);	/* Leave flow control state */

	/*
	 * If closing, we're done once we have flushed everything we could.
	 * There's no need to even bother with the upper layer: if we're
	 * closing, we won't accept any further data to write anyway.
	 */

	if (tx->flags & TX_CLOSING) {
		deflate_flush_send(tx);

		if (tx->flags & TX_ERROR)
			return;

		if (0 == tx_deflate_pending(tx)) {
			(*attr->closed)(tx, attr->closed_arg);
			return;
		}
	}

	if (tx_deflate_debugging(9)) {
		g_debug("TX %s: (%s) %sdone locally [%c%c]",
			G_STRFUNC, gnet_host_to_string(&tx->host),
			(tx->flags & TX_ERROR) ? "ERROR " : "",
			(attr->flags & DF_FLOWC) ? 'C' : '-',
			(attr->flags & DF_FLUSH) ? 'f' : '-');
	}

	/*
	 * If upper layer wants servicing, do it now.
	 * Note that this can put us back into flow control.
	 */

	if (tx->flags & TX_SERVICE) {
		g_assert(tx->srv_routine);
		tx->srv_routine(tx->srv_arg);
	}
}