[MAJOR] add a connection error state to the stream_interface
Tracking connection status changes was hard, and some code was
redundant. A new SI_ST_CER state was added to the stream interface
to indicate a past connection error, and an SI_FL_ERR flag was
added to report past I/O error. The stream_sock code does not set
the connection to SI_ST_CLO anymore in case of I/O error, it's
the upper layer which does it. This makes it possible to know
exactly when the file descriptors are allocated.
The new SI_ST_CER state permitted to split tcp_connection_status()
in two parts, one processing SI_ST_CON and the other one SI_ST_CER.
Synchronous connection errors now make use of this last state, hence
eliminating duplicate code.
Some ib<->ob copy paste errors were found and fixed, and all entities
setting SI_ST_CLO also shut the buffers down.
Some of these stream_interface specific functions and structures
have migrated to a new stream_interface.c file.
Some types of errors are still not detected by the buffers. For
instance, let's assume the following scenario in one single pass
of process_session: a connection sits in SI_ST_TAR state during
a retry. At TAR expiration, a new connection attempt is made, the
connection is obtained and srv->cur_sess is increased. Then the
buffer timeout is fires and everything is cleared, the new state
becomes SI_ST_CLO. The cleaning code checks that previous state
was either SI_ST_CON or SI_ST_EST to release the connection. But
that's wrong because last state is still SI_ST_TAR. So the
server's connection count does not get decreased.
This means that prev_state must not be used, and must be replaced
by some transition detection instead of level detection.
The following debugging line was useful to track state changes :
fprintf(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s-> rep->flags);
2008-11-03 05:26:53 +00:00
|
|
|
/*
|
2009-10-18 21:56:35 +00:00
|
|
|
* include/proto/stream_interface.h
|
|
|
|
* This file contains stream_interface function prototypes
|
|
|
|
*
|
2014-11-28 10:11:05 +00:00
|
|
|
* Copyright (C) 2000-2014 Willy Tarreau - w@1wt.eu
|
2009-10-18 21:56:35 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
|
|
* exclusively.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
[MAJOR] add a connection error state to the stream_interface
Tracking connection status changes was hard, and some code was
redundant. A new SI_ST_CER state was added to the stream interface
to indicate a past connection error, and an SI_FL_ERR flag was
added to report past I/O error. The stream_sock code does not set
the connection to SI_ST_CLO anymore in case of I/O error, it's
the upper layer which does it. This makes it possible to know
exactly when the file descriptors are allocated.
The new SI_ST_CER state permitted to split tcp_connection_status()
in two parts, one processing SI_ST_CON and the other one SI_ST_CER.
Synchronous connection errors now make use of this last state, hence
eliminating duplicate code.
Some ib<->ob copy paste errors were found and fixed, and all entities
setting SI_ST_CLO also shut the buffers down.
Some of these stream_interface specific functions and structures
have migrated to a new stream_interface.c file.
Some types of errors are still not detected by the buffers. For
instance, let's assume the following scenario in one single pass
of process_session: a connection sits in SI_ST_TAR state during
a retry. At TAR expiration, a new connection attempt is made, the
connection is obtained and srv->cur_sess is increased. Then the
buffer timeout is fires and everything is cleared, the new state
becomes SI_ST_CLO. The cleaning code checks that previous state
was either SI_ST_CON or SI_ST_EST to release the connection. But
that's wrong because last state is still SI_ST_TAR. So the
server's connection count does not get decreased.
This means that prev_state must not be used, and must be replaced
by some transition detection instead of level detection.
The following debugging line was useful to track state changes :
fprintf(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s-> rep->flags);
2008-11-03 05:26:53 +00:00
|
|
|
|
|
|
|
#ifndef _PROTO_STREAM_INTERFACE_H
|
|
|
|
#define _PROTO_STREAM_INTERFACE_H
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <common/config.h>
|
2015-08-04 17:00:17 +00:00
|
|
|
#include <types/server.h>
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
#include <types/stream.h>
|
[MAJOR] add a connection error state to the stream_interface
Tracking connection status changes was hard, and some code was
redundant. A new SI_ST_CER state was added to the stream interface
to indicate a past connection error, and an SI_FL_ERR flag was
added to report past I/O error. The stream_sock code does not set
the connection to SI_ST_CLO anymore in case of I/O error, it's
the upper layer which does it. This makes it possible to know
exactly when the file descriptors are allocated.
The new SI_ST_CER state permitted to split tcp_connection_status()
in two parts, one processing SI_ST_CON and the other one SI_ST_CER.
Synchronous connection errors now make use of this last state, hence
eliminating duplicate code.
Some ib<->ob copy paste errors were found and fixed, and all entities
setting SI_ST_CLO also shut the buffers down.
Some of these stream_interface specific functions and structures
have migrated to a new stream_interface.c file.
Some types of errors are still not detected by the buffers. For
instance, let's assume the following scenario in one single pass
of process_session: a connection sits in SI_ST_TAR state during
a retry. At TAR expiration, a new connection attempt is made, the
connection is obtained and srv->cur_sess is increased. Then the
buffer timeout is fires and everything is cleared, the new state
becomes SI_ST_CLO. The cleaning code checks that previous state
was either SI_ST_CON or SI_ST_EST to release the connection. But
that's wrong because last state is still SI_ST_TAR. So the
server's connection count does not get decreased.
This means that prev_state must not be used, and must be replaced
by some transition detection instead of level detection.
The following debugging line was useful to track state changes :
fprintf(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s-> rep->flags);
2008-11-03 05:26:53 +00:00
|
|
|
#include <types/stream_interface.h>
|
2015-04-13 11:24:54 +00:00
|
|
|
#include <proto/applet.h>
|
2012-08-30 20:23:13 +00:00
|
|
|
#include <proto/channel.h>
|
2012-08-17 15:33:53 +00:00
|
|
|
#include <proto/connection.h>
|
[MAJOR] add a connection error state to the stream_interface
Tracking connection status changes was hard, and some code was
redundant. A new SI_ST_CER state was added to the stream interface
to indicate a past connection error, and an SI_FL_ERR flag was
added to report past I/O error. The stream_sock code does not set
the connection to SI_ST_CLO anymore in case of I/O error, it's
the upper layer which does it. This makes it possible to know
exactly when the file descriptors are allocated.
The new SI_ST_CER state permitted to split tcp_connection_status()
in two parts, one processing SI_ST_CON and the other one SI_ST_CER.
Synchronous connection errors now make use of this last state, hence
eliminating duplicate code.
Some ib<->ob copy paste errors were found and fixed, and all entities
setting SI_ST_CLO also shut the buffers down.
Some of these stream_interface specific functions and structures
have migrated to a new stream_interface.c file.
Some types of errors are still not detected by the buffers. For
instance, let's assume the following scenario in one single pass
of process_session: a connection sits in SI_ST_TAR state during
a retry. At TAR expiration, a new connection attempt is made, the
connection is obtained and srv->cur_sess is increased. Then the
buffer timeout is fires and everything is cleared, the new state
becomes SI_ST_CLO. The cleaning code checks that previous state
was either SI_ST_CON or SI_ST_EST to release the connection. But
that's wrong because last state is still SI_ST_TAR. So the
server's connection count does not get decreased.
This means that prev_state must not be used, and must be replaced
by some transition detection instead of level detection.
The following debugging line was useful to track state changes :
fprintf(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s-> rep->flags);
2008-11-03 05:26:53 +00:00
|
|
|
|
|
|
|
|
2012-08-24 16:12:41 +00:00
|
|
|
extern struct si_ops si_embedded_ops;
|
|
|
|
extern struct si_ops si_conn_ops;
|
2015-04-13 14:30:14 +00:00
|
|
|
extern struct si_ops si_applet_ops;
|
2012-10-02 22:41:04 +00:00
|
|
|
extern struct data_cb si_conn_cb;
|
2012-05-07 15:15:39 +00:00
|
|
|
|
2018-12-19 14:19:27 +00:00
|
|
|
/* main event functions used to move data between sockets and buffers */
|
|
|
|
int si_check_timeouts(struct stream_interface *si);
|
|
|
|
void si_report_error(struct stream_interface *si);
|
|
|
|
void si_retnclose(struct stream_interface *si, const struct buffer *msg);
|
|
|
|
int conn_si_send_proxy(struct connection *conn, unsigned int flag);
|
|
|
|
struct appctx *si_register_handler(struct stream_interface *si, struct applet *app);
|
2015-09-25 09:45:06 +00:00
|
|
|
void si_applet_wake_cb(struct stream_interface *si);
|
2019-06-06 06:19:20 +00:00
|
|
|
void si_update_rx(struct stream_interface *si);
|
|
|
|
void si_update_tx(struct stream_interface *si);
|
2018-09-14 17:41:13 +00:00
|
|
|
int si_cs_recv(struct conn_stream *cs);
|
2018-08-02 16:06:28 +00:00
|
|
|
struct task *si_cs_io_cb(struct task *t, void *ctx, unsigned short state);
|
2018-11-08 17:15:29 +00:00
|
|
|
void si_update_both(struct stream_interface *si_f, struct stream_interface *si_b);
|
2019-06-06 06:20:17 +00:00
|
|
|
void si_sync_send(struct stream_interface *si);
|
2009-09-05 18:57:35 +00:00
|
|
|
|
2014-11-28 10:11:05 +00:00
|
|
|
/* returns the channel which receives data from this stream interface (input channel) */
|
|
|
|
static inline struct channel *si_ic(struct stream_interface *si)
|
|
|
|
{
|
2014-11-28 10:50:38 +00:00
|
|
|
if (si->flags & SI_FL_ISBACK)
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return &LIST_ELEM(si, struct stream *, si[1])->res;
|
2014-11-28 10:50:38 +00:00
|
|
|
else
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return &LIST_ELEM(si, struct stream *, si[0])->req;
|
2014-11-28 10:11:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* returns the channel which feeds data to this stream interface (output channel) */
|
|
|
|
static inline struct channel *si_oc(struct stream_interface *si)
|
|
|
|
{
|
2014-11-28 10:50:38 +00:00
|
|
|
if (si->flags & SI_FL_ISBACK)
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return &LIST_ELEM(si, struct stream *, si[1])->req;
|
2014-11-28 10:50:38 +00:00
|
|
|
else
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return &LIST_ELEM(si, struct stream *, si[0])->res;
|
2014-11-28 10:11:05 +00:00
|
|
|
}
|
|
|
|
|
2014-11-28 11:18:45 +00:00
|
|
|
/* returns the buffer which receives data from this stream interface (input channel's buffer) */
|
|
|
|
static inline struct buffer *si_ib(struct stream_interface *si)
|
|
|
|
{
|
2018-07-10 15:43:27 +00:00
|
|
|
return &si_ic(si)->buf;
|
2014-11-28 11:18:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* returns the buffer which feeds data to this stream interface (output channel's buffer) */
|
|
|
|
static inline struct buffer *si_ob(struct stream_interface *si)
|
|
|
|
{
|
2018-07-10 15:43:27 +00:00
|
|
|
return &si_oc(si)->buf;
|
2014-11-28 11:18:45 +00:00
|
|
|
}
|
|
|
|
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
/* returns the stream associated to a stream interface */
|
|
|
|
static inline struct stream *si_strm(struct stream_interface *si)
|
2014-11-28 11:03:32 +00:00
|
|
|
{
|
|
|
|
if (si->flags & SI_FL_ISBACK)
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return LIST_ELEM(si, struct stream *, si[1]);
|
2014-11-28 11:03:32 +00:00
|
|
|
else
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return LIST_ELEM(si, struct stream *, si[0]);
|
2014-11-28 11:03:32 +00:00
|
|
|
}
|
|
|
|
|
2014-11-28 11:08:47 +00:00
|
|
|
/* returns the task associated to this stream interface */
|
|
|
|
static inline struct task *si_task(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
if (si->flags & SI_FL_ISBACK)
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return LIST_ELEM(si, struct stream *, si[1])->task;
|
2014-11-28 11:08:47 +00:00
|
|
|
else
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return LIST_ELEM(si, struct stream *, si[0])->task;
|
2014-11-28 11:08:47 +00:00
|
|
|
}
|
|
|
|
|
2014-11-28 12:59:31 +00:00
|
|
|
/* returns the stream interface on the other side. Used during forwarding. */
|
|
|
|
static inline struct stream_interface *si_opposite(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
if (si->flags & SI_FL_ISBACK)
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return &LIST_ELEM(si, struct stream *, si[1])->si[0];
|
2014-11-28 12:59:31 +00:00
|
|
|
else
|
REORG/MAJOR: session: rename the "session" entity to "stream"
With HTTP/2, we'll have to support multiplexed streams. A stream is in
fact the largest part of what we currently call a session, it has buffers,
logs, etc.
In order to catch any error, this commit removes any reference to the
struct session and tries to rename most "session" occurrences in function
names to "stream" and "sess" to "strm" when that's related to a session.
The files stream.{c,h} were added and session.{c,h} removed.
The session will be reintroduced later and a few parts of the stream
will progressively be moved overthere. It will more or less contain
only what we need in an embryonic session.
Sample fetch functions and converters will have to change a bit so
that they'll use an L5 (session) instead of what's currently called
"L4" which is in fact L6 for now.
Once all changes are completed, we should see approximately this :
L7 - http_txn
L6 - stream
L5 - session
L4 - connection | applet
There will be at most one http_txn per stream, and a same session will
possibly be referenced by multiple streams. A connection will point to
a session and to a stream. The session will hold all the information
we need to keep even when we don't yet have a stream.
Some more cleanup is needed because some code was already far from
being clean. The server queue management still refers to sessions at
many places while comments talk about connections. This will have to
be cleaned up once we have a server-side connection pool manager.
Stream flags "SN_*" still need to be renamed, it doesn't seem like
any of them will need to move to the session.
2015-04-02 22:22:06 +00:00
|
|
|
return &LIST_ELEM(si, struct stream *, si[0])->si[1];
|
2014-11-28 12:59:31 +00:00
|
|
|
}
|
|
|
|
|
2013-10-24 09:51:38 +00:00
|
|
|
/* initializes a stream interface in the SI_ST_INI state. It's detached from
|
2014-11-28 11:12:34 +00:00
|
|
|
* any endpoint and only keeps its side which is expected to have already been
|
|
|
|
* set.
|
2013-10-24 09:51:38 +00:00
|
|
|
*/
|
2018-08-02 16:21:38 +00:00
|
|
|
static inline int si_reset(struct stream_interface *si)
|
2013-10-24 09:51:38 +00:00
|
|
|
{
|
|
|
|
si->err_type = SI_ET_NONE;
|
|
|
|
si->conn_retries = 0; /* used for logging too */
|
|
|
|
si->exp = TICK_ETERNITY;
|
2014-11-28 10:26:07 +00:00
|
|
|
si->flags &= SI_FL_ISBACK;
|
2013-10-24 09:51:38 +00:00
|
|
|
si->end = NULL;
|
|
|
|
si->state = si->prev_state = SI_ST_INI;
|
2015-04-19 23:03:17 +00:00
|
|
|
si->ops = &si_embedded_ops;
|
2019-06-14 12:42:29 +00:00
|
|
|
si->wait_event.tasklet = tasklet_new();
|
|
|
|
if (!si->wait_event.tasklet)
|
2018-08-02 16:21:38 +00:00
|
|
|
return -1;
|
2019-06-14 12:42:29 +00:00
|
|
|
si->wait_event.tasklet->process = si_cs_io_cb;
|
|
|
|
si->wait_event.tasklet->context = si;
|
2018-12-19 12:59:17 +00:00
|
|
|
si->wait_event.events = 0;
|
2018-08-02 16:21:38 +00:00
|
|
|
return 0;
|
2013-10-24 09:51:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* sets the current and previous state of a stream interface to <state>. This
|
|
|
|
* is mainly used to create one in the established state on incoming
|
|
|
|
* conncetions.
|
|
|
|
*/
|
|
|
|
static inline void si_set_state(struct stream_interface *si, int state)
|
|
|
|
{
|
|
|
|
si->state = si->prev_state = state;
|
|
|
|
}
|
|
|
|
|
2019-06-05 12:45:06 +00:00
|
|
|
/* returns a bit for a stream-int state, to match against SI_SB_* */
|
|
|
|
static inline enum si_state_bit si_state_bit(enum si_state state)
|
|
|
|
{
|
2019-06-06 14:38:40 +00:00
|
|
|
BUG_ON(state > SI_ST_CLO);
|
2019-06-05 12:45:06 +00:00
|
|
|
return 1U << state;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns true if <state> matches one of the SI_SB_* bits in <mask> */
|
|
|
|
static inline int si_state_in(enum si_state state, enum si_state_bit mask)
|
|
|
|
{
|
|
|
|
BUG_ON(mask & ~SI_SB_ALL);
|
|
|
|
return !!(si_state_bit(state) & mask);
|
|
|
|
}
|
|
|
|
|
2015-08-04 18:44:05 +00:00
|
|
|
/* only detaches the endpoint from the SI, which means that it's set to
|
|
|
|
* NULL and that ->ops is mapped to si_embedded_ops. The previous endpoint
|
|
|
|
* is returned.
|
|
|
|
*/
|
|
|
|
static inline enum obj_type *si_detach_endpoint(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
enum obj_type *prev = si->end;
|
|
|
|
|
|
|
|
si->end = NULL;
|
|
|
|
si->ops = &si_embedded_ops;
|
|
|
|
return prev;
|
|
|
|
}
|
|
|
|
|
2013-12-01 10:31:38 +00:00
|
|
|
/* Release the endpoint if it's a connection or an applet, then nullify it.
|
|
|
|
* Note: released connections are closed then freed.
|
|
|
|
*/
|
2013-10-11 17:34:20 +00:00
|
|
|
static inline void si_release_endpoint(struct stream_interface *si)
|
2013-09-29 15:19:56 +00:00
|
|
|
{
|
2017-09-13 16:30:23 +00:00
|
|
|
struct conn_stream *cs;
|
2013-12-01 10:31:38 +00:00
|
|
|
struct appctx *appctx;
|
2013-10-11 17:34:20 +00:00
|
|
|
|
2013-12-01 10:31:38 +00:00
|
|
|
if (!si->end)
|
|
|
|
return;
|
|
|
|
|
2018-10-11 15:09:14 +00:00
|
|
|
if ((cs = objt_cs(si->end))) {
|
2018-12-19 12:59:17 +00:00
|
|
|
if (si->wait_event.events != 0)
|
|
|
|
cs->conn->mux->unsubscribe(cs, si->wait_event.events,
|
2018-10-11 15:09:14 +00:00
|
|
|
&si->wait_event);
|
2017-09-13 16:30:23 +00:00
|
|
|
cs_destroy(cs);
|
2018-10-11 15:09:14 +00:00
|
|
|
}
|
2013-12-01 10:31:38 +00:00
|
|
|
else if ((appctx = objt_appctx(si->end))) {
|
2019-06-05 12:53:22 +00:00
|
|
|
if (appctx->applet->release && !si_state_in(si->state, SI_SB_DIS|SI_SB_CLO))
|
2015-04-13 10:05:19 +00:00
|
|
|
appctx->applet->release(appctx);
|
2019-07-18 08:41:36 +00:00
|
|
|
appctx_free(appctx);
|
2018-12-19 22:21:46 +00:00
|
|
|
}
|
2015-08-04 18:44:05 +00:00
|
|
|
si_detach_endpoint(si);
|
2013-09-29 15:19:56 +00:00
|
|
|
}
|
|
|
|
|
2017-09-13 16:30:23 +00:00
|
|
|
/* Attach conn_stream <cs> to the stream interface <si>. The stream interface
|
2013-10-24 13:50:53 +00:00
|
|
|
* is configured to work with a connection and the connection it configured
|
|
|
|
* with a stream interface data layer.
|
2013-10-01 08:45:07 +00:00
|
|
|
*/
|
2017-09-13 16:30:23 +00:00
|
|
|
static inline void si_attach_cs(struct stream_interface *si, struct conn_stream *cs)
|
2012-10-02 18:57:19 +00:00
|
|
|
{
|
|
|
|
si->ops = &si_conn_ops;
|
2017-09-13 16:30:23 +00:00
|
|
|
si->end = &cs->obj_type;
|
|
|
|
cs_attach(cs, si, &si_conn_cb);
|
2012-10-02 18:57:19 +00:00
|
|
|
}
|
|
|
|
|
2013-12-15 09:23:20 +00:00
|
|
|
/* Returns true if a connection is attached to the stream interface <si> and
|
|
|
|
* if this connection is ready.
|
|
|
|
*/
|
|
|
|
static inline int si_conn_ready(struct stream_interface *si)
|
|
|
|
{
|
2017-09-13 16:30:23 +00:00
|
|
|
struct connection *conn = cs_conn(objt_cs(si->end));
|
2013-12-15 09:23:20 +00:00
|
|
|
|
|
|
|
return conn && conn_ctrl_ready(conn) && conn_xprt_ready(conn);
|
|
|
|
}
|
|
|
|
|
2013-12-01 10:31:38 +00:00
|
|
|
/* Attach appctx <appctx> to the stream interface <si>. The stream interface
|
2015-04-04 22:15:26 +00:00
|
|
|
* is configured to work with an applet context.
|
2013-12-01 10:31:38 +00:00
|
|
|
*/
|
|
|
|
static inline void si_attach_appctx(struct stream_interface *si, struct appctx *appctx)
|
2012-08-24 16:12:41 +00:00
|
|
|
{
|
2015-04-13 14:30:14 +00:00
|
|
|
si->ops = &si_applet_ops;
|
2013-12-01 10:31:38 +00:00
|
|
|
si->end = &appctx->obj_type;
|
2015-04-13 09:48:16 +00:00
|
|
|
appctx->owner = si;
|
2012-08-24 16:12:41 +00:00
|
|
|
}
|
|
|
|
|
2018-09-20 09:08:47 +00:00
|
|
|
/* returns a pointer to the appctx being run in the SI, which must be valid */
|
2013-12-01 08:15:12 +00:00
|
|
|
static inline struct appctx *si_appctx(struct stream_interface *si)
|
|
|
|
{
|
2018-09-20 09:08:47 +00:00
|
|
|
return __objt_appctx(si->end);
|
2013-12-01 08:15:12 +00:00
|
|
|
}
|
|
|
|
|
2013-10-24 18:10:45 +00:00
|
|
|
/* call the applet's release function if any. Needs to be called upon close() */
|
|
|
|
static inline void si_applet_release(struct stream_interface *si)
|
|
|
|
{
|
2015-04-13 10:05:19 +00:00
|
|
|
struct appctx *appctx;
|
2013-10-24 18:10:45 +00:00
|
|
|
|
2018-09-20 09:08:47 +00:00
|
|
|
appctx = objt_appctx(si->end);
|
2019-06-05 12:53:22 +00:00
|
|
|
if (appctx && appctx->applet->release && !si_state_in(si->state, SI_SB_DIS|SI_SB_CLO))
|
2015-04-13 10:05:19 +00:00
|
|
|
appctx->applet->release(appctx);
|
2013-10-24 18:10:45 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 13:01:40 +00:00
|
|
|
/* Returns non-zero if the stream interface's Rx path is blocked */
|
|
|
|
static inline int si_rx_blocked(const struct stream_interface *si)
|
|
|
|
{
|
|
|
|
return !!(si->flags & SI_FL_RXBLK_ANY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns non-zero if the stream interface's endpoint is ready to receive */
|
|
|
|
static inline int si_rx_endp_ready(const struct stream_interface *si)
|
|
|
|
{
|
|
|
|
return !(si->flags & SI_FL_RX_WAIT_EP);
|
|
|
|
}
|
|
|
|
|
2018-11-14 16:54:13 +00:00
|
|
|
/* The stream interface announces it is ready to try to deliver more data to the input buffer */
|
|
|
|
static inline void si_rx_endp_more(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags &= ~SI_FL_RX_WAIT_EP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The stream interface announces it doesn't have more data for the input buffer */
|
|
|
|
static inline void si_rx_endp_done(struct stream_interface *si)
|
2018-11-06 18:17:31 +00:00
|
|
|
{
|
2018-11-14 12:43:35 +00:00
|
|
|
si->flags |= SI_FL_RX_WAIT_EP;
|
2018-11-06 18:17:31 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 16:10:36 +00:00
|
|
|
/* Tell a stream interface the input channel is OK with it sending it some data */
|
|
|
|
static inline void si_rx_chan_rdy(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags &= ~SI_FL_RXBLK_CHAN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tell a stream interface the input channel is not OK with it sending it some data */
|
|
|
|
static inline void si_rx_chan_blk(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags |= SI_FL_RXBLK_CHAN;
|
|
|
|
}
|
|
|
|
|
2018-12-06 14:24:01 +00:00
|
|
|
/* Tell a stream interface the other side is connected */
|
|
|
|
static inline void si_rx_conn_rdy(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags &= ~SI_FL_RXBLK_CONN;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Tell a stream interface it must wait for the other side to connect */
|
|
|
|
static inline void si_rx_conn_blk(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags |= SI_FL_RXBLK_CONN;
|
|
|
|
}
|
|
|
|
|
2018-11-14 14:12:08 +00:00
|
|
|
/* The stream interface just got the input buffer it was waiting for */
|
|
|
|
static inline void si_rx_buff_rdy(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags &= ~SI_FL_RXBLK_BUFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The stream interface failed to get an input buffer and is waiting for it.
|
|
|
|
* Since it indicates a willingness to deliver data to the buffer that will
|
|
|
|
* have to be retried, we automatically clear RXBLK_ENDP to be called again
|
|
|
|
* as soon as RXBLK_BUFF is cleared.
|
|
|
|
*/
|
|
|
|
static inline void si_rx_buff_blk(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags |= SI_FL_RXBLK_BUFF;
|
|
|
|
}
|
|
|
|
|
2018-11-15 10:08:52 +00:00
|
|
|
/* Tell a stream interface some room was made in the input buffer */
|
|
|
|
static inline void si_rx_room_rdy(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags &= ~SI_FL_RXBLK_ROOM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The stream interface announces it failed to put data into the input buffer
|
|
|
|
* by lack of room. Since it indicates a willingness to deliver data to the
|
|
|
|
* buffer that will have to be retried, we automatically clear RXBLK_ENDP to
|
|
|
|
* be called again as soon as RXBLK_ROOM is cleared.
|
|
|
|
*/
|
|
|
|
static inline void si_rx_room_blk(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags |= SI_FL_RXBLK_ROOM;
|
|
|
|
}
|
|
|
|
|
2018-11-14 15:58:52 +00:00
|
|
|
/* The stream interface announces it will never put new data into the input
|
|
|
|
* buffer and that it's not waiting for its endpoint to deliver anything else.
|
|
|
|
* This function obviously doesn't have a _rdy equivalent.
|
|
|
|
*/
|
|
|
|
static inline void si_rx_shut_blk(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags |= SI_FL_RXBLK_SHUT;
|
|
|
|
}
|
|
|
|
|
2018-11-14 13:01:40 +00:00
|
|
|
/* Returns non-zero if the stream interface's Rx path is blocked */
|
|
|
|
static inline int si_tx_blocked(const struct stream_interface *si)
|
|
|
|
{
|
|
|
|
return !!(si->flags & SI_FL_WAIT_DATA);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns non-zero if the stream interface's endpoint is ready to transmit */
|
|
|
|
static inline int si_tx_endp_ready(const struct stream_interface *si)
|
|
|
|
{
|
|
|
|
return (si->flags & SI_FL_WANT_GET);
|
|
|
|
}
|
|
|
|
|
2018-11-06 17:46:37 +00:00
|
|
|
/* Report that a stream interface wants to get some data from the output buffer */
|
|
|
|
static inline void si_want_get(struct stream_interface *si)
|
2015-04-21 16:44:02 +00:00
|
|
|
{
|
|
|
|
si->flags |= SI_FL_WANT_GET;
|
|
|
|
}
|
|
|
|
|
2018-11-06 17:46:37 +00:00
|
|
|
/* Report that a stream interface failed to get some data from the output buffer */
|
|
|
|
static inline void si_cant_get(struct stream_interface *si)
|
2015-04-21 16:44:02 +00:00
|
|
|
{
|
|
|
|
si->flags |= SI_FL_WANT_GET | SI_FL_WAIT_DATA;
|
|
|
|
}
|
|
|
|
|
2018-11-06 17:46:37 +00:00
|
|
|
/* Report that a stream interface doesn't want to get data from the output buffer */
|
|
|
|
static inline void si_stop_get(struct stream_interface *si)
|
2015-04-21 16:44:02 +00:00
|
|
|
{
|
|
|
|
si->flags &= ~SI_FL_WANT_GET;
|
|
|
|
}
|
|
|
|
|
2018-11-06 18:17:31 +00:00
|
|
|
/* Report that a stream interface won't get any more data from the output buffer */
|
|
|
|
static inline void si_done_get(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags &= ~(SI_FL_WANT_GET | SI_FL_WAIT_DATA);
|
|
|
|
}
|
|
|
|
|
2017-09-13 16:30:23 +00:00
|
|
|
/* Try to allocate a new conn_stream and assign it to the interface. If
|
2015-08-05 19:47:23 +00:00
|
|
|
* an endpoint was previously allocated, it is released first. The newly
|
2017-09-13 16:30:23 +00:00
|
|
|
* allocated conn_stream is initialized, assigned to the stream interface,
|
2015-08-05 19:47:23 +00:00
|
|
|
* and returned.
|
2013-12-15 12:31:35 +00:00
|
|
|
*/
|
2017-09-13 16:30:23 +00:00
|
|
|
static inline struct conn_stream *si_alloc_cs(struct stream_interface *si, struct connection *conn)
|
2013-10-11 17:34:20 +00:00
|
|
|
{
|
2017-09-13 16:30:23 +00:00
|
|
|
struct conn_stream *cs;
|
2013-10-11 17:34:20 +00:00
|
|
|
|
2015-08-05 19:47:23 +00:00
|
|
|
si_release_endpoint(si);
|
2013-10-11 17:34:20 +00:00
|
|
|
|
2017-09-13 16:30:23 +00:00
|
|
|
cs = cs_new(conn);
|
|
|
|
if (cs)
|
|
|
|
si_attach_cs(si, cs);
|
2013-10-11 17:34:20 +00:00
|
|
|
|
2017-09-13 16:30:23 +00:00
|
|
|
return cs;
|
2013-10-11 17:34:20 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 08:16:07 +00:00
|
|
|
/* Try to allocate a buffer for the stream-int's input channel. It relies on
|
2018-11-07 17:53:29 +00:00
|
|
|
* channel_alloc_buffer() for this so it abides by its rules. It returns 0 on
|
|
|
|
* failure, non-zero otherwise. If no buffer is available, the requester,
|
2018-11-14 14:12:08 +00:00
|
|
|
* represented by the <wait> pointer, will be added in the list of objects
|
|
|
|
* waiting for an available buffer, and SI_FL_RXBLK_BUFF will be set on the
|
|
|
|
* stream-int and SI_FL_RX_WAIT_EP cleared. The requester will be responsible
|
|
|
|
* for calling this function to try again once woken up.
|
2018-10-25 08:16:07 +00:00
|
|
|
*/
|
|
|
|
static inline int si_alloc_ibuf(struct stream_interface *si, struct buffer_wait *wait)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = channel_alloc_buffer(si_ic(si), wait);
|
|
|
|
if (!ret)
|
2018-11-14 14:12:08 +00:00
|
|
|
si_rx_buff_blk(si);
|
2018-10-25 08:16:07 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-12-01 10:31:38 +00:00
|
|
|
/* Release the interface's existing endpoint (connection or appctx) and
|
|
|
|
* allocate then initialize a new appctx which is assigned to the interface
|
2015-04-04 22:15:26 +00:00
|
|
|
* and returned. NULL may be returned upon memory shortage. Applet <applet>
|
|
|
|
* is assigned to the appctx, but it may be NULL.
|
2013-12-01 10:31:38 +00:00
|
|
|
*/
|
2015-04-13 11:50:30 +00:00
|
|
|
static inline struct appctx *si_alloc_appctx(struct stream_interface *si, struct applet *applet)
|
2013-12-01 10:31:38 +00:00
|
|
|
{
|
|
|
|
struct appctx *appctx;
|
|
|
|
|
|
|
|
si_release_endpoint(si);
|
2017-06-19 10:38:55 +00:00
|
|
|
appctx = appctx_new(applet, tid_bit);
|
2018-05-31 12:44:25 +00:00
|
|
|
if (appctx) {
|
2013-12-01 10:31:38 +00:00
|
|
|
si_attach_appctx(si, appctx);
|
2018-05-31 12:44:25 +00:00
|
|
|
appctx->t->nice = si_strm(si)->task->nice;
|
|
|
|
}
|
2013-12-01 10:31:38 +00:00
|
|
|
|
|
|
|
return appctx;
|
|
|
|
}
|
|
|
|
|
2012-05-21 14:31:45 +00:00
|
|
|
/* Sends a shutr to the connection using the data layer */
|
|
|
|
static inline void si_shutr(struct stream_interface *si)
|
|
|
|
{
|
2013-09-29 13:16:03 +00:00
|
|
|
si->ops->shutr(si);
|
2012-05-21 14:31:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Sends a shutw to the connection using the data layer */
|
|
|
|
static inline void si_shutw(struct stream_interface *si)
|
|
|
|
{
|
2013-09-29 13:16:03 +00:00
|
|
|
si->ops->shutw(si);
|
2012-05-21 14:31:45 +00:00
|
|
|
}
|
|
|
|
|
2019-01-31 18:02:43 +00:00
|
|
|
/* Marks on the stream-interface that next shutw must kill the whole connection */
|
|
|
|
static inline void si_must_kill_conn(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si->flags |= SI_FL_KILL_CONN;
|
|
|
|
}
|
|
|
|
|
2018-11-07 10:55:54 +00:00
|
|
|
/* This is to be used after making some room available in a channel. It will
|
2018-11-14 13:07:59 +00:00
|
|
|
* return without doing anything if the stream interface's RX path is blocked.
|
|
|
|
* It will automatically mark the stream interface as busy processing the end
|
|
|
|
* point in order to avoid useless repeated wakeups.
|
2018-11-09 15:21:43 +00:00
|
|
|
* It will then call ->chk_rcv() to enable receipt of new data.
|
2018-11-07 10:55:54 +00:00
|
|
|
*/
|
2012-05-21 14:31:45 +00:00
|
|
|
static inline void si_chk_rcv(struct stream_interface *si)
|
|
|
|
{
|
2019-06-05 12:34:03 +00:00
|
|
|
if (si->flags & SI_FL_RXBLK_CONN && si_state_in(si_opposite(si)->state, SI_SB_RDY|SI_SB_EST|SI_SB_DIS|SI_SB_CLO))
|
2018-12-06 14:24:01 +00:00
|
|
|
si_rx_conn_rdy(si);
|
|
|
|
|
2018-11-14 13:07:59 +00:00
|
|
|
if (si_rx_blocked(si) || !si_rx_endp_ready(si))
|
2018-11-07 10:55:54 +00:00
|
|
|
return;
|
|
|
|
|
2019-06-05 12:34:03 +00:00
|
|
|
if (!si_state_in(si->state, SI_SB_RDY|SI_SB_EST))
|
2018-11-07 13:59:45 +00:00
|
|
|
return;
|
|
|
|
|
2018-11-14 12:43:35 +00:00
|
|
|
si->flags |= SI_FL_RX_WAIT_EP;
|
2018-11-07 10:28:12 +00:00
|
|
|
si->ops->chk_rcv(si);
|
2012-05-21 14:31:45 +00:00
|
|
|
}
|
|
|
|
|
2018-11-17 18:51:07 +00:00
|
|
|
/* This tries to perform a synchronous receive on the stream interface to
|
|
|
|
* try to collect last arrived data. In practice it's only implemented on
|
|
|
|
* conn_streams. Returns 0 if nothing was done, non-zero if new data or a
|
|
|
|
* shutdown were collected. This may result on some delayed receive calls
|
|
|
|
* to be programmed and performed later, though it doesn't provide any
|
|
|
|
* such guarantee.
|
|
|
|
*/
|
|
|
|
static inline int si_sync_recv(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
struct conn_stream *cs;
|
|
|
|
|
2019-06-05 12:34:03 +00:00
|
|
|
if (!si_state_in(si->state, SI_SB_RDY|SI_SB_EST))
|
2018-11-17 18:51:07 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
cs = objt_cs(si->end);
|
2020-01-22 16:34:54 +00:00
|
|
|
if (!cs || !cs->conn->mux)
|
2018-11-17 18:51:07 +00:00
|
|
|
return 0; // only conn_streams are supported
|
|
|
|
|
2018-12-19 12:59:17 +00:00
|
|
|
if (si->wait_event.events & SUB_RETRY_RECV)
|
2018-11-17 18:51:07 +00:00
|
|
|
return 0; // already subscribed
|
|
|
|
|
2018-11-16 13:26:11 +00:00
|
|
|
if (!si_rx_endp_ready(si) || si_rx_blocked(si))
|
2018-11-17 18:51:07 +00:00
|
|
|
return 0; // already failed
|
|
|
|
|
|
|
|
return si_cs_recv(cs);
|
|
|
|
}
|
|
|
|
|
2012-05-21 14:31:45 +00:00
|
|
|
/* Calls chk_snd on the connection using the data layer */
|
|
|
|
static inline void si_chk_snd(struct stream_interface *si)
|
|
|
|
{
|
2018-11-07 10:28:12 +00:00
|
|
|
si->ops->chk_snd(si);
|
2012-05-21 14:31:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Calls chk_snd on the connection using the ctrl layer */
|
2018-11-20 23:16:29 +00:00
|
|
|
static inline int si_connect(struct stream_interface *si, struct connection *conn)
|
2012-05-21 14:31:45 +00:00
|
|
|
{
|
2015-04-02 23:14:29 +00:00
|
|
|
int ret = SF_ERR_NONE;
|
2017-01-23 22:36:45 +00:00
|
|
|
int conn_flags = 0;
|
2012-08-30 20:23:13 +00:00
|
|
|
|
2013-10-01 08:45:07 +00:00
|
|
|
if (unlikely(!conn || !conn->ctrl || !conn->ctrl->connect))
|
2015-04-02 23:14:29 +00:00
|
|
|
return SF_ERR_INTERNAL;
|
2012-08-30 20:23:13 +00:00
|
|
|
|
2017-01-23 22:36:45 +00:00
|
|
|
if (!channel_is_empty(si_oc(si)))
|
|
|
|
conn_flags |= CONNECT_HAS_DATA;
|
|
|
|
if (si->conn_retries == si_strm(si)->be->conn_retries)
|
|
|
|
conn_flags |= CONNECT_CAN_USE_TFO;
|
2013-12-15 15:20:50 +00:00
|
|
|
if (!conn_ctrl_ready(conn) || !conn_xprt_ready(conn)) {
|
2017-01-23 22:36:45 +00:00
|
|
|
ret = conn->ctrl->connect(conn, conn_flags);
|
2015-04-02 23:14:29 +00:00
|
|
|
if (ret != SF_ERR_NONE)
|
2013-12-15 15:20:50 +00:00
|
|
|
return ret;
|
2013-12-31 22:32:12 +00:00
|
|
|
|
|
|
|
/* we're in the process of establishing a connection */
|
|
|
|
si->state = SI_ST_CON;
|
2013-12-15 15:20:50 +00:00
|
|
|
}
|
2015-12-23 08:33:35 +00:00
|
|
|
else {
|
2019-01-23 14:15:09 +00:00
|
|
|
/* try to reuse the existing connection, it will be
|
|
|
|
* confirmed once we can send on it.
|
|
|
|
*/
|
2019-10-25 14:25:20 +00:00
|
|
|
/* Is the connection really ready ? */
|
|
|
|
if (conn->mux->ctl(conn, MUX_STATUS, NULL) & MUX_STATUS_READY)
|
|
|
|
si->state = SI_ST_RDY;
|
|
|
|
else
|
|
|
|
si->state = SI_ST_CON;
|
2013-12-15 15:20:50 +00:00
|
|
|
}
|
2012-08-30 20:23:13 +00:00
|
|
|
|
|
|
|
/* needs src ip/port for logging */
|
|
|
|
if (si->flags & SI_FL_SRC_ADDR)
|
2019-07-17 09:27:38 +00:00
|
|
|
conn_get_src(conn);
|
2012-08-30 20:23:13 +00:00
|
|
|
|
|
|
|
return ret;
|
2012-05-21 14:31:45 +00:00
|
|
|
}
|
2012-05-11 14:16:40 +00:00
|
|
|
|
2019-06-06 06:19:20 +00:00
|
|
|
/* Combines both si_update_rx() and si_update_tx() at once */
|
|
|
|
static inline void si_update(struct stream_interface *si)
|
|
|
|
{
|
|
|
|
si_update_rx(si);
|
|
|
|
si_update_tx(si);
|
|
|
|
}
|
|
|
|
|
MEDIUM: conn_stream: Add a way to get mux's info on a CS from the upper layer
Time to time, the need arises to get some info owned by the multiplexer about a
connection stream from the upper layer. Today we really need to get some dates
and durations specific to the conn_stream. It is only true for the mux H1 and
H2. Otherwise it will be impossible to have correct times reported in the logs.
To do so, the structure cs_info has been defined to provide all info we ever
need on a conn_stream from the upper layer. Of course, it is the first step. So
this structure will certainly envloved. But for now, only the bare minimum is
referenced. On the mux side, the callback get_cs_info() has been added in the
structure mux_ops. Multiplexers can now implement it, if necessary, to return a
pointer on a structure cs_info. And finally, the function si_get_cs_info()
should be used from the upper layer. If the stream interface is not attached to
a connection stream, this function returns NULL, likewise if the callback
get_cs_info() is not defined for the corresponding mux.
2018-11-29 10:29:26 +00:00
|
|
|
/* Returns info about the conn_stream <cs>, if not NULL. It call the mux layer's
|
|
|
|
* get_cs_info() function, if it exists. On success, it returns a cs_info
|
|
|
|
* structure. Otherwise, on error, if the mux does not implement get_cs_info()
|
|
|
|
* or if conn_stream is NULL, NULL is returned.
|
|
|
|
*/
|
|
|
|
static inline const struct cs_info *si_get_cs_info(struct conn_stream *cs)
|
|
|
|
{
|
|
|
|
if (cs && cs->conn->mux->get_cs_info)
|
|
|
|
return cs->conn->mux->get_cs_info(cs);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-12-08 16:48:47 +00:00
|
|
|
/* for debugging, reports the stream interface state name */
|
|
|
|
static inline const char *si_state_str(int state)
|
|
|
|
{
|
|
|
|
switch (state) {
|
|
|
|
case SI_ST_INI: return "INI";
|
|
|
|
case SI_ST_REQ: return "REQ";
|
|
|
|
case SI_ST_QUE: return "QUE";
|
|
|
|
case SI_ST_TAR: return "TAR";
|
|
|
|
case SI_ST_ASS: return "ASS";
|
|
|
|
case SI_ST_CON: return "CON";
|
|
|
|
case SI_ST_CER: return "CER";
|
2019-06-05 12:34:03 +00:00
|
|
|
case SI_ST_RDY: return "RDY";
|
2012-12-08 16:48:47 +00:00
|
|
|
case SI_ST_EST: return "EST";
|
|
|
|
case SI_ST_DIS: return "DIS";
|
|
|
|
case SI_ST_CLO: return "CLO";
|
|
|
|
default: return "???";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[MAJOR] add a connection error state to the stream_interface
Tracking connection status changes was hard, and some code was
redundant. A new SI_ST_CER state was added to the stream interface
to indicate a past connection error, and an SI_FL_ERR flag was
added to report past I/O error. The stream_sock code does not set
the connection to SI_ST_CLO anymore in case of I/O error, it's
the upper layer which does it. This makes it possible to know
exactly when the file descriptors are allocated.
The new SI_ST_CER state permitted to split tcp_connection_status()
in two parts, one processing SI_ST_CON and the other one SI_ST_CER.
Synchronous connection errors now make use of this last state, hence
eliminating duplicate code.
Some ib<->ob copy paste errors were found and fixed, and all entities
setting SI_ST_CLO also shut the buffers down.
Some of these stream_interface specific functions and structures
have migrated to a new stream_interface.c file.
Some types of errors are still not detected by the buffers. For
instance, let's assume the following scenario in one single pass
of process_session: a connection sits in SI_ST_TAR state during
a retry. At TAR expiration, a new connection attempt is made, the
connection is obtained and srv->cur_sess is increased. Then the
buffer timeout is fires and everything is cleared, the new state
becomes SI_ST_CLO. The cleaning code checks that previous state
was either SI_ST_CON or SI_ST_EST to release the connection. But
that's wrong because last state is still SI_ST_TAR. So the
server's connection count does not get decreased.
This means that prev_state must not be used, and must be replaced
by some transition detection instead of level detection.
The following debugging line was useful to track state changes :
fprintf(stderr, "%s:%d: cs=%d ss=%d(%d) rqf=0x%08x rpf=0x%08x\n", __FUNCTION__, __LINE__,
s->si[0].state, s->si[1].state, s->si[1].err_type, s->req->flags, s-> rep->flags);
2008-11-03 05:26:53 +00:00
|
|
|
#endif /* _PROTO_STREAM_INTERFACE_H */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* c-indent-level: 8
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* End:
|
|
|
|
*/
|