"Fossies" - the Fresh Open Source Software Archive

Member "haproxy-2.0.9/include/proto/stream_interface.h" (15 Nov 2019, 18238 Bytes) of package /linux/misc/haproxy-2.0.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stream_interface.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.0.8_vs_2.0.9.

    1 /*
    2  * include/proto/stream_interface.h
    3  * This file contains stream_interface function prototypes
    4  *
    5  * Copyright (C) 2000-2014 Willy Tarreau - w@1wt.eu
    6  *
    7  * This library is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation, version 2.1
   10  * exclusively.
   11  *
   12  * This library is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with this library; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   20  */
   21 
   22 #ifndef _PROTO_STREAM_INTERFACE_H
   23 #define _PROTO_STREAM_INTERFACE_H
   24 
   25 #include <stdlib.h>
   26 
   27 #include <common/config.h>
   28 #include <types/server.h>
   29 #include <types/stream.h>
   30 #include <types/stream_interface.h>
   31 #include <proto/applet.h>
   32 #include <proto/channel.h>
   33 #include <proto/connection.h>
   34 
   35 
   36 extern struct si_ops si_embedded_ops;
   37 extern struct si_ops si_conn_ops;
   38 extern struct si_ops si_applet_ops;
   39 extern struct data_cb si_conn_cb;
   40 
   41 /* main event functions used to move data between sockets and buffers */
   42 int si_check_timeouts(struct stream_interface *si);
   43 void si_report_error(struct stream_interface *si);
   44 void si_retnclose(struct stream_interface *si, const struct buffer *msg);
   45 int conn_si_send_proxy(struct connection *conn, unsigned int flag);
   46 struct appctx *si_register_handler(struct stream_interface *si, struct applet *app);
   47 void si_applet_wake_cb(struct stream_interface *si);
   48 void si_update_rx(struct stream_interface *si);
   49 void si_update_tx(struct stream_interface *si);
   50 int si_cs_recv(struct conn_stream *cs);
   51 struct task *si_cs_io_cb(struct task *t, void *ctx, unsigned short state);
   52 void si_update_both(struct stream_interface *si_f, struct stream_interface *si_b);
   53 void si_sync_send(struct stream_interface *si);
   54 
   55 /* returns the channel which receives data from this stream interface (input channel) */
   56 static inline struct channel *si_ic(struct stream_interface *si)
   57 {
   58     if (si->flags & SI_FL_ISBACK)
   59         return &LIST_ELEM(si, struct stream *, si[1])->res;
   60     else
   61         return &LIST_ELEM(si, struct stream *, si[0])->req;
   62 }
   63 
   64 /* returns the channel which feeds data to this stream interface (output channel) */
   65 static inline struct channel *si_oc(struct stream_interface *si)
   66 {
   67     if (si->flags & SI_FL_ISBACK)
   68         return &LIST_ELEM(si, struct stream *, si[1])->req;
   69     else
   70         return &LIST_ELEM(si, struct stream *, si[0])->res;
   71 }
   72 
   73 /* returns the buffer which receives data from this stream interface (input channel's buffer) */
   74 static inline struct buffer *si_ib(struct stream_interface *si)
   75 {
   76     return &si_ic(si)->buf;
   77 }
   78 
   79 /* returns the buffer which feeds data to this stream interface (output channel's buffer) */
   80 static inline struct buffer *si_ob(struct stream_interface *si)
   81 {
   82     return &si_oc(si)->buf;
   83 }
   84 
   85 /* returns the stream associated to a stream interface */
   86 static inline struct stream *si_strm(struct stream_interface *si)
   87 {
   88     if (si->flags & SI_FL_ISBACK)
   89         return LIST_ELEM(si, struct stream *, si[1]);
   90     else
   91         return LIST_ELEM(si, struct stream *, si[0]);
   92 }
   93 
   94 /* returns the task associated to this stream interface */
   95 static inline struct task *si_task(struct stream_interface *si)
   96 {
   97     if (si->flags & SI_FL_ISBACK)
   98         return LIST_ELEM(si, struct stream *, si[1])->task;
   99     else
  100         return LIST_ELEM(si, struct stream *, si[0])->task;
  101 }
  102 
  103 /* returns the stream interface on the other side. Used during forwarding. */
  104 static inline struct stream_interface *si_opposite(struct stream_interface *si)
  105 {
  106     if (si->flags & SI_FL_ISBACK)
  107         return &LIST_ELEM(si, struct stream *, si[1])->si[0];
  108     else
  109         return &LIST_ELEM(si, struct stream *, si[0])->si[1];
  110 }
  111 
  112 /* initializes a stream interface in the SI_ST_INI state. It's detached from
  113  * any endpoint and only keeps its side which is expected to have already been
  114  * set.
  115  */
  116 static inline int si_reset(struct stream_interface *si)
  117 {
  118     si->err_type       = SI_ET_NONE;
  119     si->conn_retries   = 0;  /* used for logging too */
  120     si->exp            = TICK_ETERNITY;
  121     si->flags         &= SI_FL_ISBACK;
  122     si->end            = NULL;
  123     si->state          = si->prev_state = SI_ST_INI;
  124     si->ops            = &si_embedded_ops;
  125     si->wait_event.tasklet = tasklet_new();
  126     if (!si->wait_event.tasklet)
  127         return -1;
  128     si->wait_event.tasklet->process = si_cs_io_cb;
  129     si->wait_event.tasklet->context = si;
  130     si->wait_event.events = 0;
  131     return 0;
  132 }
  133 
  134 /* sets the current and previous state of a stream interface to <state>. This
  135  * is mainly used to create one in the established state on incoming
  136  * conncetions.
  137  */
  138 static inline void si_set_state(struct stream_interface *si, int state)
  139 {
  140     si->state = si->prev_state = state;
  141 }
  142 
  143 /* returns a bit for a stream-int state, to match against SI_SB_* */
  144 static inline enum si_state_bit si_state_bit(enum si_state state)
  145 {
  146     BUG_ON(state > SI_ST_CLO);
  147     return 1U << state;
  148 }
  149 
  150 /* returns true if <state> matches one of the SI_SB_* bits in <mask> */
  151 static inline int si_state_in(enum si_state state, enum si_state_bit mask)
  152 {
  153     BUG_ON(mask & ~SI_SB_ALL);
  154     return !!(si_state_bit(state) & mask);
  155 }
  156 
  157 /* only detaches the endpoint from the SI, which means that it's set to
  158  * NULL and that ->ops is mapped to si_embedded_ops. The previous endpoint
  159  * is returned.
  160  */
  161 static inline enum obj_type *si_detach_endpoint(struct stream_interface *si)
  162 {
  163     enum obj_type *prev = si->end;
  164 
  165     si->end = NULL;
  166     si->ops = &si_embedded_ops;
  167     return prev;
  168 }
  169 
  170 /* Release the endpoint if it's a connection or an applet, then nullify it.
  171  * Note: released connections are closed then freed.
  172  */
  173 static inline void si_release_endpoint(struct stream_interface *si)
  174 {
  175     struct connection *conn;
  176     struct conn_stream *cs;
  177     struct appctx *appctx;
  178 
  179     if (!si->end)
  180         return;
  181 
  182     if ((cs = objt_cs(si->end))) {
  183         if (si->wait_event.events != 0)
  184             cs->conn->mux->unsubscribe(cs, si->wait_event.events,
  185                 &si->wait_event);
  186         cs_destroy(cs);
  187     }
  188     else if ((appctx = objt_appctx(si->end))) {
  189         if (appctx->applet->release && !si_state_in(si->state, SI_SB_DIS|SI_SB_CLO))
  190             appctx->applet->release(appctx);
  191         appctx_free(appctx); /* we share the connection pool */
  192     } else if ((conn = objt_conn(si->end))) {
  193         conn_stop_tracking(conn);
  194         conn_full_close(conn);
  195         conn_free(conn);
  196     }
  197     si_detach_endpoint(si);
  198 }
  199 
  200 /* Attach conn_stream <cs> to the stream interface <si>. The stream interface
  201  * is configured to work with a connection and the connection it configured
  202  * with a stream interface data layer.
  203  */
  204 static inline void si_attach_cs(struct stream_interface *si, struct conn_stream *cs)
  205 {
  206     si->ops = &si_conn_ops;
  207     si->end = &cs->obj_type;
  208     cs_attach(cs, si, &si_conn_cb);
  209 }
  210 
  211 /* Returns true if a connection is attached to the stream interface <si> and
  212  * if this connection is ready.
  213  */
  214 static inline int si_conn_ready(struct stream_interface *si)
  215 {
  216     struct connection *conn = cs_conn(objt_cs(si->end));
  217 
  218     return conn && conn_ctrl_ready(conn) && conn_xprt_ready(conn);
  219 }
  220 
  221 /* Attach appctx <appctx> to the stream interface <si>. The stream interface
  222  * is configured to work with an applet context.
  223  */
  224 static inline void si_attach_appctx(struct stream_interface *si, struct appctx *appctx)
  225 {
  226     si->ops = &si_applet_ops;
  227     si->end = &appctx->obj_type;
  228     appctx->owner = si;
  229 }
  230 
  231 /* returns a pointer to the appctx being run in the SI, which must be valid */
  232 static inline struct appctx *si_appctx(struct stream_interface *si)
  233 {
  234     return __objt_appctx(si->end);
  235 }
  236 
  237 /* call the applet's release function if any. Needs to be called upon close() */
  238 static inline void si_applet_release(struct stream_interface *si)
  239 {
  240     struct appctx *appctx;
  241 
  242     appctx = objt_appctx(si->end);
  243     if (appctx && appctx->applet->release && !si_state_in(si->state, SI_SB_DIS|SI_SB_CLO))
  244         appctx->applet->release(appctx);
  245 }
  246 
  247 /* Returns non-zero if the stream interface's Rx path is blocked */
  248 static inline int si_rx_blocked(const struct stream_interface *si)
  249 {
  250     return !!(si->flags & SI_FL_RXBLK_ANY);
  251 }
  252 
  253 /* Returns non-zero if the stream interface's endpoint is ready to receive */
  254 static inline int si_rx_endp_ready(const struct stream_interface *si)
  255 {
  256     return !(si->flags & SI_FL_RX_WAIT_EP);
  257 }
  258 
  259 /* The stream interface announces it is ready to try to deliver more data to the input buffer */
  260 static inline void si_rx_endp_more(struct stream_interface *si)
  261 {
  262     si->flags &= ~SI_FL_RX_WAIT_EP;
  263 }
  264 
  265 /* The stream interface announces it doesn't have more data for the input buffer */
  266 static inline void si_rx_endp_done(struct stream_interface *si)
  267 {
  268     si->flags |=  SI_FL_RX_WAIT_EP;
  269 }
  270 
  271 /* Tell a stream interface the input channel is OK with it sending it some data */
  272 static inline void si_rx_chan_rdy(struct stream_interface *si)
  273 {
  274     si->flags &= ~SI_FL_RXBLK_CHAN;
  275 }
  276 
  277 /* Tell a stream interface the input channel is not OK with it sending it some data */
  278 static inline void si_rx_chan_blk(struct stream_interface *si)
  279 {
  280     si->flags |=  SI_FL_RXBLK_CHAN;
  281 }
  282 
  283 /* Tell a stream interface the other side is connected */
  284 static inline void si_rx_conn_rdy(struct stream_interface *si)
  285 {
  286     si->flags &= ~SI_FL_RXBLK_CONN;
  287 }
  288 
  289 /* Tell a stream interface it must wait for the other side to connect */
  290 static inline void si_rx_conn_blk(struct stream_interface *si)
  291 {
  292     si->flags |=  SI_FL_RXBLK_CONN;
  293 }
  294 
  295 /* The stream interface just got the input buffer it was waiting for */
  296 static inline void si_rx_buff_rdy(struct stream_interface *si)
  297 {
  298     si->flags &= ~SI_FL_RXBLK_BUFF;
  299 }
  300 
  301 /* The stream interface failed to get an input buffer and is waiting for it.
  302  * Since it indicates a willingness to deliver data to the buffer that will
  303  * have to be retried, we automatically clear RXBLK_ENDP to be called again
  304  * as soon as RXBLK_BUFF is cleared.
  305  */
  306 static inline void si_rx_buff_blk(struct stream_interface *si)
  307 {
  308     si->flags |=  SI_FL_RXBLK_BUFF;
  309 }
  310 
  311 /* Tell a stream interface some room was made in the input buffer */
  312 static inline void si_rx_room_rdy(struct stream_interface *si)
  313 {
  314     si->flags &= ~SI_FL_RXBLK_ROOM;
  315 }
  316 
  317 /* The stream interface announces it failed to put data into the input buffer
  318  * by lack of room. Since it indicates a willingness to deliver data to the
  319  * buffer that will have to be retried, we automatically clear RXBLK_ENDP to
  320  * be called again as soon as RXBLK_ROOM is cleared.
  321  */
  322 static inline void si_rx_room_blk(struct stream_interface *si)
  323 {
  324     si->flags |=  SI_FL_RXBLK_ROOM;
  325 }
  326 
  327 /* The stream interface announces it will never put new data into the input
  328  * buffer and that it's not waiting for its endpoint to deliver anything else.
  329  * This function obviously doesn't have a _rdy equivalent.
  330  */
  331 static inline void si_rx_shut_blk(struct stream_interface *si)
  332 {
  333     si->flags |=  SI_FL_RXBLK_SHUT;
  334 }
  335 
  336 /* Returns non-zero if the stream interface's Rx path is blocked */
  337 static inline int si_tx_blocked(const struct stream_interface *si)
  338 {
  339     return !!(si->flags & SI_FL_WAIT_DATA);
  340 }
  341 
  342 /* Returns non-zero if the stream interface's endpoint is ready to transmit */
  343 static inline int si_tx_endp_ready(const struct stream_interface *si)
  344 {
  345     return (si->flags & SI_FL_WANT_GET);
  346 }
  347 
  348 /* Report that a stream interface wants to get some data from the output buffer */
  349 static inline void si_want_get(struct stream_interface *si)
  350 {
  351     si->flags |= SI_FL_WANT_GET;
  352 }
  353 
  354 /* Report that a stream interface failed to get some data from the output buffer */
  355 static inline void si_cant_get(struct stream_interface *si)
  356 {
  357     si->flags |= SI_FL_WANT_GET | SI_FL_WAIT_DATA;
  358 }
  359 
  360 /* Report that a stream interface doesn't want to get data from the output buffer */
  361 static inline void si_stop_get(struct stream_interface *si)
  362 {
  363     si->flags &= ~SI_FL_WANT_GET;
  364 }
  365 
  366 /* Report that a stream interface won't get any more data from the output buffer */
  367 static inline void si_done_get(struct stream_interface *si)
  368 {
  369     si->flags &= ~(SI_FL_WANT_GET | SI_FL_WAIT_DATA);
  370 }
  371 
  372 /* Try to allocate a new conn_stream and assign it to the interface. If
  373  * an endpoint was previously allocated, it is released first. The newly
  374  * allocated conn_stream is initialized, assigned to the stream interface,
  375  * and returned.
  376  */
  377 static inline struct conn_stream *si_alloc_cs(struct stream_interface *si, struct connection *conn)
  378 {
  379     struct conn_stream *cs;
  380 
  381     si_release_endpoint(si);
  382 
  383     cs = cs_new(conn);
  384     if (cs)
  385         si_attach_cs(si, cs);
  386 
  387     return cs;
  388 }
  389 
  390 /* Try to allocate a buffer for the stream-int's input channel. It relies on
  391  * channel_alloc_buffer() for this so it abides by its rules. It returns 0 on
  392  * failure, non-zero otherwise. If no buffer is available, the requester,
  393  * represented by the <wait> pointer, will be added in the list of objects
  394  * waiting for an available buffer, and SI_FL_RXBLK_BUFF will be set on the
  395  * stream-int and SI_FL_RX_WAIT_EP cleared. The requester will be responsible
  396  * for calling this function to try again once woken up.
  397  */
  398 static inline int si_alloc_ibuf(struct stream_interface *si, struct buffer_wait *wait)
  399 {
  400     int ret;
  401 
  402     ret = channel_alloc_buffer(si_ic(si), wait);
  403     if (!ret)
  404         si_rx_buff_blk(si);
  405     return ret;
  406 }
  407 
  408 /* Release the interface's existing endpoint (connection or appctx) and
  409  * allocate then initialize a new appctx which is assigned to the interface
  410  * and returned. NULL may be returned upon memory shortage. Applet <applet>
  411  * is assigned to the appctx, but it may be NULL.
  412  */
  413 static inline struct appctx *si_alloc_appctx(struct stream_interface *si, struct applet *applet)
  414 {
  415     struct appctx *appctx;
  416 
  417     si_release_endpoint(si);
  418     appctx = appctx_new(applet, tid_bit);
  419     if (appctx) {
  420         si_attach_appctx(si, appctx);
  421         appctx->t->nice = si_strm(si)->task->nice;
  422     }
  423 
  424     return appctx;
  425 }
  426 
  427 /* Sends a shutr to the connection using the data layer */
  428 static inline void si_shutr(struct stream_interface *si)
  429 {
  430     si->ops->shutr(si);
  431 }
  432 
  433 /* Sends a shutw to the connection using the data layer */
  434 static inline void si_shutw(struct stream_interface *si)
  435 {
  436     si->ops->shutw(si);
  437 }
  438 
  439 /* Marks on the stream-interface that next shutw must kill the whole connection */
  440 static inline void si_must_kill_conn(struct stream_interface *si)
  441 {
  442     si->flags |= SI_FL_KILL_CONN;
  443 }
  444 
  445 /* This is to be used after making some room available in a channel. It will
  446  * return without doing anything if the stream interface's RX path is blocked.
  447  * It will automatically mark the stream interface as busy processing the end
  448  * point in order to avoid useless repeated wakeups.
  449  * It will then call ->chk_rcv() to enable receipt of new data.
  450  */
  451 static inline void si_chk_rcv(struct stream_interface *si)
  452 {
  453     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))
  454         si_rx_conn_rdy(si);
  455 
  456     if (si_rx_blocked(si) || !si_rx_endp_ready(si))
  457         return;
  458 
  459     if (!si_state_in(si->state, SI_SB_RDY|SI_SB_EST))
  460         return;
  461 
  462     si->flags |= SI_FL_RX_WAIT_EP;
  463     si->ops->chk_rcv(si);
  464 }
  465 
  466 /* This tries to perform a synchronous receive on the stream interface to
  467  * try to collect last arrived data. In practice it's only implemented on
  468  * conn_streams. Returns 0 if nothing was done, non-zero if new data or a
  469  * shutdown were collected. This may result on some delayed receive calls
  470  * to be programmed and performed later, though it doesn't provide any
  471  * such guarantee.
  472  */
  473 static inline int si_sync_recv(struct stream_interface *si)
  474 {
  475     struct conn_stream *cs;
  476 
  477     if (!si_state_in(si->state, SI_SB_RDY|SI_SB_EST))
  478         return 0;
  479 
  480     cs = objt_cs(si->end);
  481     if (!cs)
  482         return 0; // only conn_streams are supported
  483 
  484     if (si->wait_event.events & SUB_RETRY_RECV)
  485         return 0; // already subscribed
  486 
  487     if (!si_rx_endp_ready(si) || si_rx_blocked(si))
  488         return 0; // already failed
  489 
  490     return si_cs_recv(cs);
  491 }
  492 
  493 /* Calls chk_snd on the connection using the data layer */
  494 static inline void si_chk_snd(struct stream_interface *si)
  495 {
  496     si->ops->chk_snd(si);
  497 }
  498 
  499 /* Calls chk_snd on the connection using the ctrl layer */
  500 static inline int si_connect(struct stream_interface *si, struct connection *conn)
  501 {
  502     int ret = SF_ERR_NONE;
  503     int conn_flags = 0;
  504 
  505     if (unlikely(!conn || !conn->ctrl || !conn->ctrl->connect))
  506         return SF_ERR_INTERNAL;
  507 
  508     if (!channel_is_empty(si_oc(si)))
  509         conn_flags |= CONNECT_HAS_DATA;
  510     if (si->conn_retries == si_strm(si)->be->conn_retries)
  511         conn_flags |= CONNECT_CAN_USE_TFO;
  512     if (!conn_ctrl_ready(conn) || !conn_xprt_ready(conn)) {
  513         ret = conn->ctrl->connect(conn, conn_flags);
  514         if (ret != SF_ERR_NONE)
  515             return ret;
  516 
  517         /* we're in the process of establishing a connection */
  518         si->state = SI_ST_CON;
  519     }
  520     else {
  521         /* try to reuse the existing connection, it will be
  522          * confirmed once we can send on it.
  523          */
  524         /* Is the connection really ready ? */
  525         if (conn->mux->ctl(conn, MUX_STATUS, NULL) & MUX_STATUS_READY)
  526             si->state = SI_ST_RDY;
  527         else
  528             si->state = SI_ST_CON;
  529     }
  530 
  531     /* needs src ip/port for logging */
  532     if (si->flags & SI_FL_SRC_ADDR)
  533         conn_get_from_addr(conn);
  534 
  535     return ret;
  536 }
  537 
  538 /* Combines both si_update_rx() and si_update_tx() at once */
  539 static inline void si_update(struct stream_interface *si)
  540 {
  541     si_update_rx(si);
  542     si_update_tx(si);
  543 }
  544 
  545 /* Returns info about the conn_stream <cs>, if not NULL. It call the mux layer's
  546  * get_cs_info() function, if it exists. On success, it returns a cs_info
  547  * structure. Otherwise, on error, if the mux does not implement get_cs_info()
  548  * or if conn_stream is NULL, NULL is returned.
  549  */
  550 static inline const struct cs_info *si_get_cs_info(struct conn_stream *cs)
  551 {
  552     if (cs && cs->conn->mux->get_cs_info)
  553         return cs->conn->mux->get_cs_info(cs);
  554     return NULL;
  555 }
  556 
  557 /* for debugging, reports the stream interface state name */
  558 static inline const char *si_state_str(int state)
  559 {
  560     switch (state) {
  561     case SI_ST_INI: return "INI";
  562     case SI_ST_REQ: return "REQ";
  563     case SI_ST_QUE: return "QUE";
  564     case SI_ST_TAR: return "TAR";
  565     case SI_ST_ASS: return "ASS";
  566     case SI_ST_CON: return "CON";
  567     case SI_ST_CER: return "CER";
  568     case SI_ST_RDY: return "RDY";
  569     case SI_ST_EST: return "EST";
  570     case SI_ST_DIS: return "DIS";
  571     case SI_ST_CLO: return "CLO";
  572     default:        return "???";
  573     }
  574 }
  575 
  576 #endif /* _PROTO_STREAM_INTERFACE_H */
  577 
  578 /*
  579  * Local variables:
  580  *  c-indent-level: 8
  581  *  c-basic-offset: 8
  582  * End:
  583  */