mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
MEDIUM: stream_interface: offer a generic function for connection updates
We need to have a generic function to be called by upper layers when buffer flags have been updated (the si->update function). At the moment, both sock_raw and sock_ssl had their own which basically was a copy-paste. Since these functions are only used to update stream interface flags, it is logical to have them handled by the stream interface code. This allowed us to remove the stream_interface-specific update function from sock_raw and sock_ssl which now use the generic code. The stream_sock_update_conn callback has also been more appropriately renamed conn_notify_si() since it's meant to be called by lower layers to notify the SI and possibly upper layers about incoming changes.
This commit is contained in:
parent
26f44d1e91
commit
100c467120
@ -35,7 +35,8 @@ int stream_int_check_timeouts(struct stream_interface *si);
|
||||
void stream_int_report_error(struct stream_interface *si);
|
||||
void stream_int_retnclose(struct stream_interface *si, const struct chunk *msg);
|
||||
int conn_si_send_proxy(struct connection *conn, unsigned int flag);
|
||||
void stream_sock_update_conn(struct connection *conn);
|
||||
void conn_notify_si(struct connection *conn);
|
||||
void stream_int_update_conn(struct stream_interface *si);
|
||||
int stream_int_shutr(struct stream_interface *si);
|
||||
int stream_int_shutw(struct stream_interface *si);
|
||||
|
||||
|
@ -82,7 +82,7 @@ int conn_fd_handler(int fd)
|
||||
|
||||
leave:
|
||||
if (conn->flags & CO_FL_NOTIFY_SI)
|
||||
stream_sock_update_conn(conn);
|
||||
conn_notify_si(conn);
|
||||
|
||||
/* Last check, verify if the connection just established */
|
||||
if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED))))
|
||||
|
@ -45,7 +45,6 @@
|
||||
/* main event functions used to move data between sockets and buffers */
|
||||
static void sock_raw_read(struct connection *conn);
|
||||
static void sock_raw_write(struct connection *conn);
|
||||
static void sock_raw_data_finish(struct stream_interface *si);
|
||||
static void sock_raw_read0(struct stream_interface *si);
|
||||
static void sock_raw_chk_rcv(struct stream_interface *si);
|
||||
static void sock_raw_chk_snd(struct stream_interface *si);
|
||||
@ -674,86 +673,6 @@ static void sock_raw_read0(struct stream_interface *si)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates a connected sock_raw file descriptor status and timeouts
|
||||
* according to the buffers' flags. It should only be called once after the
|
||||
* buffer flags have settled down, and before they are cleared. It doesn't
|
||||
* harm to call it as often as desired (it just slightly hurts performance).
|
||||
*/
|
||||
static void sock_raw_data_finish(struct stream_interface *si)
|
||||
{
|
||||
struct buffer *ib = si->ib;
|
||||
struct buffer *ob = si->ob;
|
||||
|
||||
DPRINTF(stderr,"[%u] %s: fd=%d owner=%p ib=%p, ob=%p, exp(r,w)=%u,%u ibf=%08x obf=%08x ibh=%d ibt=%d obh=%d obd=%d si=%d\n",
|
||||
now_ms, __FUNCTION__,
|
||||
si_fd(si), fdtab[si_fd(fd)].owner,
|
||||
ib, ob,
|
||||
ib->rex, ob->wex,
|
||||
ib->flags, ob->flags,
|
||||
ib->i, ib->o, ob->i, ob->o, si->state);
|
||||
|
||||
/* Check if we need to close the read side */
|
||||
if (!(ib->flags & BF_SHUTR)) {
|
||||
/* Read not closed, update FD status and timeout for reads */
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
|
||||
/* stop reading */
|
||||
if (!(si->flags & SI_FL_WAIT_ROOM)) {
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
|
||||
si->flags |= SI_FL_WAIT_ROOM;
|
||||
conn_data_stop_recv(&si->conn);
|
||||
ib->rex = TICK_ETERNITY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* (re)start reading and update timeout. Note: we don't recompute the timeout
|
||||
* everytime we get here, otherwise it would risk never to expire. We only
|
||||
* update it if is was not yet set. The stream socket handler will already
|
||||
* have updated it if there has been a completed I/O.
|
||||
*/
|
||||
si->flags &= ~SI_FL_WAIT_ROOM;
|
||||
conn_data_want_recv(&si->conn);
|
||||
if (!(ib->flags & (BF_READ_NOEXP|BF_DONT_READ)) && !tick_isset(ib->rex))
|
||||
ib->rex = tick_add_ifset(now_ms, ib->rto);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we need to close the write side */
|
||||
if (!(ob->flags & BF_SHUTW)) {
|
||||
/* Write not closed, update FD status and timeout for writes */
|
||||
if (ob->flags & BF_OUT_EMPTY) {
|
||||
/* stop writing */
|
||||
if (!(si->flags & SI_FL_WAIT_DATA)) {
|
||||
if ((ob->flags & (BF_FULL|BF_HIJACK|BF_SHUTW_NOW)) == 0)
|
||||
si->flags |= SI_FL_WAIT_DATA;
|
||||
conn_data_stop_send(&si->conn);
|
||||
ob->wex = TICK_ETERNITY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* (re)start writing and update timeout. Note: we don't recompute the timeout
|
||||
* everytime we get here, otherwise it would risk never to expire. We only
|
||||
* update it if is was not yet set. The stream socket handler will already
|
||||
* have updated it if there has been a completed I/O.
|
||||
*/
|
||||
si->flags &= ~SI_FL_WAIT_DATA;
|
||||
conn_data_want_send(&si->conn);
|
||||
if (!tick_isset(ob->wex)) {
|
||||
ob->wex = tick_add_ifset(now_ms, ob->wto);
|
||||
if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
|
||||
/* Note: depending on the protocol, we don't know if we're waiting
|
||||
* for incoming data or not. So in order to prevent the socket from
|
||||
* expiring read timeouts during writes, we refresh the read timeout,
|
||||
* except if it was already infinite or if we have explicitly setup
|
||||
* independent streams.
|
||||
*/
|
||||
ib->rex = tick_add_ifset(now_ms, ib->rto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is used for inter-stream-interface calls. It is called by the
|
||||
* consumer to inform the producer side that it may be interested in checking
|
||||
* for free space in the buffer. Note that it intentionally does not update
|
||||
@ -889,7 +808,7 @@ static void sock_raw_chk_snd(struct stream_interface *si)
|
||||
|
||||
/* stream sock operations */
|
||||
struct sock_ops sock_raw = {
|
||||
.update = sock_raw_data_finish,
|
||||
.update = stream_int_update_conn,
|
||||
.shutr = NULL,
|
||||
.shutw = NULL,
|
||||
.chk_rcv = sock_raw_chk_rcv,
|
||||
|
@ -552,8 +552,12 @@ int conn_si_send_proxy(struct connection *conn, unsigned int flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* function to be called on stream sockets after all I/O handlers */
|
||||
void stream_sock_update_conn(struct connection *conn)
|
||||
/* Callback to be used by connection I/O handlers upon completion. It differs from
|
||||
* the function below in that it is designed to be called by lower layers after I/O
|
||||
* events have been completed. It will also try to wake the associated task up if
|
||||
* an important event requires special handling.
|
||||
*/
|
||||
void conn_notify_si(struct connection *conn)
|
||||
{
|
||||
int fd = conn->t.sock.fd;
|
||||
struct stream_interface *si = container_of(conn, struct stream_interface, conn);
|
||||
@ -651,6 +655,85 @@ void stream_sock_update_conn(struct connection *conn)
|
||||
si->ib->flags &= ~BF_READ_DONTWAIT;
|
||||
}
|
||||
|
||||
/* Updates the timers and flags of a stream interface attached to a connection,
|
||||
* depending on the buffers' flags. It should only be called once after the
|
||||
* buffer flags have settled down, and before they are cleared. It doesn't
|
||||
* harm to call it as often as desired (it just slightly hurts performance).
|
||||
* It is only meant to be called by upper layers after buffer flags have been
|
||||
* manipulated by analysers.
|
||||
*/
|
||||
void stream_int_update_conn(struct stream_interface *si)
|
||||
{
|
||||
struct buffer *ib = si->ib;
|
||||
struct buffer *ob = si->ob;
|
||||
|
||||
if (si->conn.flags & CO_FL_HANDSHAKE) {
|
||||
/* a handshake is in progress */
|
||||
si->flags &= ~SI_FL_WAIT_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we need to close the read side */
|
||||
if (!(ib->flags & BF_SHUTR)) {
|
||||
/* Read not closed, update FD status and timeout for reads */
|
||||
if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
|
||||
/* stop reading */
|
||||
if (!(si->flags & SI_FL_WAIT_ROOM)) {
|
||||
if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
|
||||
si->flags |= SI_FL_WAIT_ROOM;
|
||||
conn_data_stop_recv(&si->conn);
|
||||
ib->rex = TICK_ETERNITY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* (re)start reading and update timeout. Note: we don't recompute the timeout
|
||||
* everytime we get here, otherwise it would risk never to expire. We only
|
||||
* update it if is was not yet set. The stream socket handler will already
|
||||
* have updated it if there has been a completed I/O.
|
||||
*/
|
||||
si->flags &= ~SI_FL_WAIT_ROOM;
|
||||
conn_data_want_recv(&si->conn);
|
||||
if (!(ib->flags & (BF_READ_NOEXP|BF_DONT_READ)) && !tick_isset(ib->rex))
|
||||
ib->rex = tick_add_ifset(now_ms, ib->rto);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we need to close the write side */
|
||||
if (!(ob->flags & BF_SHUTW)) {
|
||||
/* Write not closed, update FD status and timeout for writes */
|
||||
if (ob->flags & BF_OUT_EMPTY) {
|
||||
/* stop writing */
|
||||
if (!(si->flags & SI_FL_WAIT_DATA)) {
|
||||
if ((ob->flags & (BF_FULL|BF_HIJACK|BF_SHUTW_NOW)) == 0)
|
||||
si->flags |= SI_FL_WAIT_DATA;
|
||||
conn_data_stop_send(&si->conn);
|
||||
ob->wex = TICK_ETERNITY;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* (re)start writing and update timeout. Note: we don't recompute the timeout
|
||||
* everytime we get here, otherwise it would risk never to expire. We only
|
||||
* update it if is was not yet set. The stream socket handler will already
|
||||
* have updated it if there has been a completed I/O.
|
||||
*/
|
||||
si->flags &= ~SI_FL_WAIT_DATA;
|
||||
conn_data_want_send(&si->conn);
|
||||
if (!tick_isset(ob->wex)) {
|
||||
ob->wex = tick_add_ifset(now_ms, ob->wto);
|
||||
if (tick_isset(ib->rex) && !(si->flags & SI_FL_INDEP_STR)) {
|
||||
/* Note: depending on the protocol, we don't know if we're waiting
|
||||
* for incoming data or not. So in order to prevent the socket from
|
||||
* expiring read timeouts during writes, we refresh the read timeout,
|
||||
* except if it was already infinite or if we have explicitly setup
|
||||
* independent streams.
|
||||
*/
|
||||
ib->rex = tick_add_ifset(now_ms, ib->rto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
|
Loading…
Reference in New Issue
Block a user