Пример #1
0
/* Update polling on connection <c>'s file descriptor depending on its current
 * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
 * in CO_FL_WAIT_*, and the sock layer expectations indicated by CO_FL_SOCK_*.
 * The connection flags are updated with the new flags at the end of the
 * operation. Polling is totally disabled if an error was reported.
 */
void conn_update_sock_polling(struct connection *c)
{
	unsigned int f = c->flags;

	if (!conn_ctrl_ready(c))
		return;

	/* update read status if needed */
	if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_SOCK_RD_ENA)) {
		fd_want_recv(c->t.sock.fd);
		f |= CO_FL_CURR_RD_ENA;
	}
	else if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_CURR_RD_ENA)) {
		fd_stop_recv(c->t.sock.fd);
		f &= ~CO_FL_CURR_RD_ENA;
	}

	/* update write status if needed */
	if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_SOCK_WR_ENA)) {
		fd_want_send(c->t.sock.fd);
		f |= CO_FL_CURR_WR_ENA;
	}
	else if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_CURR_WR_ENA)) {
		fd_stop_send(c->t.sock.fd);
		f &= ~CO_FL_CURR_WR_ENA;
	}
	c->flags = f;
}
Пример #2
0
/* Update polling on connection <c>'s file descriptor depending on its current
 * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
 * in CO_FL_WAIT_*, and the sock layer expectations indicated by CO_FL_SOCK_*.
 * The connection flags are updated with the new flags at the end of the
 * operation.
 */
void conn_update_sock_polling(struct connection *c)
{
	unsigned int f = c->flags;

	/* update read status if needed */
	if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_CURR_RD_ENA)) {
		f &= ~(CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL);
		fd_stop_recv(c->t.sock.fd);
	}
	else if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL)) != (CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL) &&
	                  (f & (CO_FL_SOCK_RD_ENA|CO_FL_WAIT_RD)) == (CO_FL_SOCK_RD_ENA|CO_FL_WAIT_RD))) {
		f |= (CO_FL_CURR_RD_ENA|CO_FL_CURR_RD_POL);
		fd_poll_recv(c->t.sock.fd);
	}
	else if (unlikely((f & (CO_FL_CURR_RD_ENA|CO_FL_SOCK_RD_ENA)) == CO_FL_SOCK_RD_ENA)) {
		f |= CO_FL_CURR_RD_ENA;
		fd_want_recv(c->t.sock.fd);
	}

	/* update write status if needed */
	if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_CURR_WR_ENA)) {
		f &= ~(CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL);
		fd_stop_send(c->t.sock.fd);
	}
	else if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL)) != (CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL) &&
	                  (f & (CO_FL_SOCK_WR_ENA|CO_FL_WAIT_WR)) == (CO_FL_SOCK_WR_ENA|CO_FL_WAIT_WR))) {
		f |= (CO_FL_CURR_WR_ENA|CO_FL_CURR_WR_POL);
		fd_poll_send(c->t.sock.fd);
	}
	else if (unlikely((f & (CO_FL_CURR_WR_ENA|CO_FL_SOCK_WR_ENA)) == CO_FL_SOCK_WR_ENA)) {
		f |= CO_FL_CURR_WR_ENA;
		fd_want_send(c->t.sock.fd);
	}
	c->flags = f;
}
Пример #3
0
/* This function tries to resume a temporarily disabled listener. Paused, full,
 * limited and disabled listeners are handled, which means that this function
 * may replace enable_listener(). The resulting state will either be LI_READY
 * or LI_FULL. 0 is returned in case of failure to resume (eg: dead socket).
 * Listeners bound to a different process are not woken up unless we're in
 * foreground mode.
 */
int resume_listener(struct listener *l)
{
	if (l->state < LI_PAUSED)
		return 0;

	if ((global.mode & (MODE_DAEMON | MODE_SYSTEMD)) &&
	    l->bind_conf->bind_proc &&
	    !(l->bind_conf->bind_proc & (1UL << (relative_pid - 1))))
		return 0;

	if (l->proto->sock_prot == IPPROTO_TCP &&
	    l->state == LI_PAUSED &&
	    listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
		return 0;

	if (l->state == LI_READY)
		return 1;

	if (l->state == LI_LIMITED)
		LIST_DEL(&l->wait_queue);

	if (l->nbconn >= l->maxconn) {
		l->state = LI_FULL;
		return 1;
	}

	fd_want_recv(l->fd);
	l->state = LI_READY;
	return 1;
}
Пример #4
0
/* This function tries to resume a temporarily disabled listener. Paused, full,
 * limited and disabled listeners are handled, which means that this function
 * may replace enable_listener(). The resulting state will either be LI_READY
 * or LI_FULL. 0 is returned in case of failure to resume (eg: dead socket).
 */
int resume_listener(struct listener *l)
{
	if (l->state < LI_PAUSED)
		return 0;

	if (l->proto->sock_prot == IPPROTO_TCP &&
	    l->state == LI_PAUSED &&
	    listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
		return 0;

	if (l->state == LI_READY)
		return 1;

	if (l->state == LI_LIMITED)
		LIST_DEL(&l->wait_queue);

	if (l->nbconn >= l->maxconn) {
		l->state = LI_FULL;
		return 1;
	}

	fd_want_recv(l->fd);
	l->state = LI_READY;
	return 1;
}
Пример #5
0
/* This function adds the specified listener's file descriptor to the polling
 * lists if it is in the LI_LISTEN state. The listener enters LI_READY or
 * LI_FULL state depending on its number of connections.
 */
void enable_listener(struct listener *listener)
{
	if (listener->state == LI_LISTEN) {
		if (listener->nbconn < listener->maxconn) {
			fd_want_recv(listener->fd);
			listener->state = LI_READY;
		} else {
			listener->state = LI_FULL;
		}
	}
}
Пример #6
0
/* This function tries to resume a temporarily disabled listener. Paused, full,
 * limited and disabled listeners are handled, which means that this function
 * may replace enable_listener(). The resulting state will either be LI_READY
 * or LI_FULL. 0 is returned in case of failure to resume (eg: dead socket).
 * Listeners bound to a different process are not woken up unless we're in
 * foreground mode. If the listener was only in the assigned state, it's totally
 * rebound. This can happen if a pause() has completely stopped it. If the
 * resume fails, 0 is returned and an error might be displayed.
 */
int resume_listener(struct listener *l)
{
	if (l->state == LI_ASSIGNED) {
		char msg[100];
		int err;

		err = l->proto->bind(l, msg, sizeof(msg));
		if (err & ERR_ALERT)
			Alert("Resuming listener: %s\n", msg);
		else if (err & ERR_WARN)
			Warning("Resuming listener: %s\n", msg);

		if (err & (ERR_FATAL | ERR_ABORT))
			return 0;
	}

	if (l->state < LI_PAUSED)
		return 0;

	if ((global.mode & (MODE_DAEMON | MODE_SYSTEMD)) &&
	    l->bind_conf->bind_proc &&
	    !(l->bind_conf->bind_proc & (1UL << (relative_pid - 1))))
		return 0;

	if (l->proto->sock_prot == IPPROTO_TCP &&
	    l->state == LI_PAUSED &&
	    listen(l->fd, l->backlog ? l->backlog : l->maxconn) != 0)
		return 0;

	if (l->state == LI_READY)
		return 1;

	if (l->state == LI_LIMITED)
		LIST_DEL(&l->wait_queue);

	if (l->nbconn >= l->maxconn) {
		l->state = LI_FULL;
		return 1;
	}

	fd_want_recv(l->fd);
	l->state = LI_READY;
	return 1;
}
Пример #7
0
/* This function adds the specified listener's file descriptor to the polling
 * lists if it is in the LI_LISTEN state. The listener enters LI_READY or
 * LI_FULL state depending on its number of connections. In deamon mode, we
 * also support binding only the relevant processes to their respective
 * listeners. We don't do that in debug mode however.
 */
void enable_listener(struct listener *listener)
{
	if (listener->state == LI_LISTEN) {
		if ((global.mode & (MODE_DAEMON | MODE_SYSTEMD)) &&
		    listener->bind_conf->bind_proc &&
		    !(listener->bind_conf->bind_proc & (1UL << (relative_pid - 1)))) {
			/* we don't want to enable this listener and don't
			 * want any fd event to reach it.
			 */
			fd_stop_recv(listener->fd);
			listener->state = LI_PAUSED;
		}
		else if (listener->nbconn < listener->maxconn) {
			fd_want_recv(listener->fd);
			listener->state = LI_READY;
		}
		else {
			listener->state = LI_FULL;
		}
	}
}