/* 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; }
/* 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; }
/* This function is used for inter-stream-interface calls. It is called by the * producer to inform the consumer side that it may be interested in checking * for data in the buffer. Note that it intentionally does not update timeouts, * so that we can still check them later at wake-up. */ static void stream_int_chk_snd_conn(struct stream_interface *si) { struct channel *ob = si->ob; if (unlikely(si->state > SI_ST_EST || (ob->flags & CF_SHUTW))) return; if (unlikely(channel_is_empty(ob))) /* called with nothing to send ! */ return; if (!ob->pipe && /* spliced data wants to be forwarded ASAP */ !(si->flags & SI_FL_WAIT_DATA)) /* not waiting for data */ return; if (!(si->conn->flags & (CO_FL_HANDSHAKE|CO_FL_WAIT_L4_CONN|CO_FL_WAIT_L6_CONN))) { /* Before calling the data-level operations, we have to prepare * the polling flags to ensure we properly detect changes. */ if (si->conn->ctrl) fd_want_send(si->conn->t.sock.fd); conn_refresh_polling_flags(si->conn); if (si_conn_send_loop(si->conn) < 0) { /* Write error on the file descriptor */ fd_stop_both(si->conn->t.sock.fd); __conn_data_stop_both(si->conn); si->flags |= SI_FL_ERR; si->conn->flags |= CO_FL_ERROR; goto out_wakeup; } } /* OK, so now we know that some data might have been sent, and that we may * have to poll first. We have to do that too if the buffer is not empty. */ if (channel_is_empty(ob)) { /* the connection is established but we can't write. Either the * buffer is empty, or we just refrain from sending because the * ->o limit was reached. Maybe we just wrote the last * chunk and need to close. */ __conn_data_stop_send(si->conn); if (((ob->flags & (CF_SHUTW|CF_AUTO_CLOSE|CF_SHUTW_NOW)) == (CF_AUTO_CLOSE|CF_SHUTW_NOW)) && (si->state == SI_ST_EST)) { si_shutw(si); goto out_wakeup; } if ((ob->flags & (CF_SHUTW|CF_SHUTW_NOW)) == 0) si->flags |= SI_FL_WAIT_DATA; ob->wex = TICK_ETERNITY; } else { /* Otherwise there are remaining data to be sent in the buffer, * which means we have to poll before doing so. */ __conn_data_want_send(si->conn); si->flags &= ~SI_FL_WAIT_DATA; if (!tick_isset(ob->wex)) ob->wex = tick_add_ifset(now_ms, ob->wto); } if (likely(ob->flags & CF_WRITE_ACTIVITY)) { /* update timeout if we have written something */ if ((ob->flags & (CF_SHUTW|CF_WRITE_PARTIAL)) == CF_WRITE_PARTIAL && !channel_is_empty(ob)) ob->wex = tick_add_ifset(now_ms, ob->wto); if (tick_isset(si->ib->rex) && !(si->flags & SI_FL_INDEP_STR)) { /* Note: to prevent the client from expiring read timeouts * during writes, we refresh it. We only do this if the * interface is not configured for "independent streams", * because for some applications it's better not to do this, * for instance when continuously exchanging small amounts * of data which can full the socket buffers long before a * write timeout is detected. */ si->ib->rex = tick_add_ifset(now_ms, si->ib->rto); } } /* in case of special condition (error, shutdown, end of write...), we * have to notify the task. */ if (likely((ob->flags & (CF_WRITE_NULL|CF_WRITE_ERROR|CF_SHUTW)) || (channel_is_empty(ob) && !ob->to_forward) || si->state != SI_ST_EST)) { out_wakeup: if (!(si->flags & SI_FL_DONT_WAKE) && si->owner) task_wakeup(si->owner, TASK_WOKEN_IO); } /* commit possible polling changes */ conn_cond_update_polling(si->conn); }