blob: 45a8bacd3f8963ca38def10ef58602ddd848bfc3 [file] [log] [blame]
/*
* include/haproxy/stream_interface.h
* This file contains stream_interface function prototypes
*
* Copyright (C) 2000-2014 Willy Tarreau - w@1wt.eu
*
* 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
*/
#ifndef _HAPROXY_STREAM_INTERFACE_H
#define _HAPROXY_STREAM_INTERFACE_H
#include <haproxy/api.h>
#include <haproxy/applet.h>
#include <haproxy/channel.h>
#include <haproxy/connection.h>
#include <haproxy/conn_stream.h>
#include <haproxy/obj_type.h>
extern struct data_cb si_conn_cb;
extern struct data_cb check_conn_cb;
struct stream_interface *si_new(struct conn_stream *cs);
void si_free(struct stream_interface *si);
/* main event functions used to move data between sockets and buffers */
void si_applet_wake_cb(struct stream_interface *si);
struct task *si_cs_io_cb(struct task *t, void *ctx, unsigned int state);
int si_sync_recv(struct stream_interface *si);
void si_sync_send(struct stream_interface *si);
/* Functions used to communicate with a conn_stream. The first two may be used
* directly, the last one is mostly a wake callback.
*/
int si_cs_recv(struct conn_stream *cs);
int si_cs_send(struct conn_stream *cs);
int si_cs_process(struct conn_stream *cs);
/* returns the channel which receives data from this stream interface (input channel) */
static inline struct channel *si_ic(struct stream_interface *si)
{
struct stream *strm = __cs_strm(si->cs);
return ((si->flags & SI_FL_ISBACK) ? &(strm->res) : &(strm->req));
}
/* returns the channel which feeds data to this stream interface (output channel) */
static inline struct channel *si_oc(struct stream_interface *si)
{
struct stream *strm = __cs_strm(si->cs);
return ((si->flags & SI_FL_ISBACK) ? &(strm->req) : &(strm->res));
}
/* returns the buffer which receives data from this stream interface (input channel's buffer) */
static inline struct buffer *si_ib(struct stream_interface *si)
{
return &si_ic(si)->buf;
}
/* returns the buffer which feeds data to this stream interface (output channel's buffer) */
static inline struct buffer *si_ob(struct stream_interface *si)
{
return &si_oc(si)->buf;
}
/* returns the stream associated to a stream interface */
static inline struct stream *si_strm(struct stream_interface *si)
{
return __cs_strm(si->cs);
}
/* returns the task associated to this stream interface */
static inline struct task *si_task(struct stream_interface *si)
{
struct stream *strm = __cs_strm(si->cs);
return strm->task;
}
/* returns the stream interface on the other side. Used during forwarding. */
static inline struct stream_interface *si_opposite(struct stream_interface *si)
{
struct stream *strm = __cs_strm(si->cs);
return ((si->flags & SI_FL_ISBACK) ? strm->csf->si : strm->csb->si);
}
/* initializes a stream interface and create the event
* tasklet.
*/
static inline int si_init(struct stream_interface *si)
{
si->flags &= SI_FL_ISBACK;
si->cs = NULL;
return 0;
}
/* 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 Rx path is blocked because of lack
* of room in the input buffer.
*/
static inline int si_rx_blocked_room(const struct stream_interface *si)
{
return !!(si->flags & SI_FL_RXBLK_ROOM);
}
/* 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);
}
/* 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)
{
si->flags |= SI_FL_RX_WAIT_EP;
}
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
/* 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;
}
/* 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);
}
/* Report that a stream interface wants to get some data from the output buffer */
static inline void si_want_get(struct stream_interface *si)
{
si->flags |= SI_FL_WANT_GET;
}
/* Report that a stream interface failed to get some data from the output buffer */
static inline void si_cant_get(struct stream_interface *si)
{
si->flags |= SI_FL_WANT_GET | SI_FL_WAIT_DATA;
}
/* 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)
{
si->flags &= ~SI_FL_WANT_GET;
}
/* 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);
}
/* Try to allocate a buffer for the stream-int's input channel. It relies on
* 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,
* 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.
*/
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)
si_rx_buff_blk(si);
return ret;
}
/* The stream interface is only responsible for the connection during the early
* states, before plugging a mux. Thus it should only care about CO_FL_ERROR
* before CS_ST_EST, and after that it must absolutely ignore it since the mux
* may hold pending data. This function returns true if such an error was
* reported. Both the CS and the CONN must be valid.
*/
static inline int si_is_conn_error(const struct stream_interface *si)
{
struct connection *conn;
if (si->cs->state >= CS_ST_EST)
return 0;
conn = __cs_conn(si->cs);
BUG_ON(!conn);
return !!(conn->flags & CO_FL_ERROR);
}
#endif /* _HAPROXY_STREAM_INTERFACE_H */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/