return (c->flags & (CO_FL_DATA_WR_SH | CO_FL_SOCK_WR_SH)) == CO_FL_DATA_WR_SH;
}
+static inline void clear_target(struct target *dest)
+{
+ dest->type = TARG_TYPE_NONE;
+ dest->ptr.v = NULL;
+}
+
+static inline void set_target_client(struct target *dest, struct listener *l)
+{
+ dest->type = TARG_TYPE_CLIENT;
+ dest->ptr.l = l;
+}
+
+static inline void set_target_server(struct target *dest, struct server *s)
+{
+ dest->type = TARG_TYPE_SERVER;
+ dest->ptr.s = s;
+}
+
+static inline void set_target_proxy(struct target *dest, struct proxy *p)
+{
+ dest->type = TARG_TYPE_PROXY;
+ dest->ptr.p = p;
+}
+
+static inline void set_target_applet(struct target *dest, struct si_applet *a)
+{
+ dest->type = TARG_TYPE_APPLET;
+ dest->ptr.a = a;
+}
+
+static inline void set_target_task(struct target *dest, struct task *t)
+{
+ dest->type = TARG_TYPE_TASK;
+ dest->ptr.t = t;
+}
+
+static inline struct target *copy_target(struct target *dest, struct target *src)
+{
+ *dest = *src;
+ return dest;
+}
+
+static inline int target_match(struct target *a, struct target *b)
+{
+ return a->type == b->type && a->ptr.v == b->ptr.v;
+}
+
+static inline struct server *target_srv(struct target *t)
+{
+ if (!t || t->type != TARG_TYPE_SERVER)
+ return NULL;
+ return t->ptr.s;
+}
+
+static inline struct listener *target_client(struct target *t)
+{
+ if (!t || t->type != TARG_TYPE_CLIENT)
+ return NULL;
+ return t->ptr.l;
+}
+
#endif /* _PROTO_CONNECTION_H */
/*
return si->conn.t.sock.fd;
}
-static inline void clear_target(struct target *dest)
-{
- dest->type = TARG_TYPE_NONE;
- dest->ptr.v = NULL;
-}
-
-static inline void set_target_client(struct target *dest, struct listener *l)
-{
- dest->type = TARG_TYPE_CLIENT;
- dest->ptr.l = l;
-}
-
-static inline void set_target_server(struct target *dest, struct server *s)
-{
- dest->type = TARG_TYPE_SERVER;
- dest->ptr.s = s;
-}
-
-static inline void set_target_proxy(struct target *dest, struct proxy *p)
-{
- dest->type = TARG_TYPE_PROXY;
- dest->ptr.p = p;
-}
-
-static inline void set_target_applet(struct target *dest, struct si_applet *a)
-{
- dest->type = TARG_TYPE_APPLET;
- dest->ptr.a = a;
-}
-
-static inline void set_target_task(struct target *dest, struct task *t)
-{
- dest->type = TARG_TYPE_TASK;
- dest->ptr.t = t;
-}
-
-static inline struct target *copy_target(struct target *dest, struct target *src)
-{
- *dest = *src;
- return dest;
-}
-
-static inline int target_match(struct target *a, struct target *b)
-{
- return a->type == b->type && a->ptr.v == b->ptr.v;
-}
-
-static inline struct server *target_srv(struct target *t)
-{
- if (!t || t->type != TARG_TYPE_SERVER)
- return NULL;
- return t->ptr.s;
-}
-
-static inline struct listener *target_client(struct target *t)
-{
- if (!t || t->type != TARG_TYPE_CLIENT)
- return NULL;
- return t->ptr.l;
-}
-
static inline void si_prepare_conn(struct stream_interface *si, const struct protocol *ctrl, const struct data_ops *ops)
{
si->ops = &si_conn_ops;
if (si_ctrl(si)->get_src(si_fd(si), (struct sockaddr *)&si->addr.from,
sizeof(si->addr.from),
- si->target.type != TARG_TYPE_CLIENT) == -1)
+ si->conn.target.type != TARG_TYPE_CLIENT) == -1)
return;
si->flags |= SI_FL_FROM_SET;
}
if (si_ctrl(si)->get_dst(si_fd(si), (struct sockaddr *)&si->addr.to,
sizeof(si->addr.to),
- si->target.type != TARG_TYPE_CLIENT) == -1)
+ si->conn.target.type != TARG_TYPE_CLIENT) == -1)
return;
si->flags |= SI_FL_TO_SET;
}
struct connection;
struct buffer;
struct pipe;
+struct server;
+struct proxy;
+struct si_applet;
+struct task;
+struct listener;
/* Polling flags that are manipulated by I/O callbacks and handshake callbacks
* indicate what they expect from a file descriptor at each layer. For each
CO_FL_CURR_WR_POL = CO_FL_WR_POL << 28, /* sending needs to poll first */
};
+/* target types */
+enum {
+ TARG_TYPE_NONE = 0, /* no target set, pointer is NULL by definition */
+ TARG_TYPE_CLIENT, /* target is a client, pointer is NULL by definition */
+ TARG_TYPE_PROXY, /* target is a proxy ; use address with the proxy's settings */
+ TARG_TYPE_SERVER, /* target is a server ; use address with server's and its proxy's settings */
+ TARG_TYPE_APPLET, /* target is an applet ; use only the applet */
+ TARG_TYPE_TASK, /* target is a task running an external applet */
+};
+
/* data_ops describes data-layer operations for a connection. They generally
* run over a socket-based control layer, but not always.
void (*send)(struct connection *conn); /* application-layer send callback */
};
+/* a target describes what is on the remote side of the connection. */
+struct target {
+ int type;
+ union {
+ void *v; /* pointer value, for any type */
+ struct proxy *p; /* when type is TARG_TYPE_PROXY */
+ struct server *s; /* when type is TARG_TYPE_SERVER */
+ struct si_applet *a; /* when type is TARG_TYPE_APPLET */
+ struct task *t; /* when type is TARG_TYPE_TASK */
+ struct listener *l; /* when type is TARG_TYPE_CLIENT */
+ } ptr;
+};
+
/* This structure describes a connection with its methods and data.
* A connection may be performed to proxy or server via a local or remote
* socket, and can also be made to an internal applet. It can support
unsigned int flags; /* CO_F_* */
int data_st; /* data layer state, initialized to zero */
void *data_ctx; /* general purpose pointer, initialized to NULL */
+ struct target target; /* the target to connect to (server, proxy, applet, ...) */
struct sockaddr *peeraddr; /* pointer to peer's network address, or NULL if unset */
socklen_t peerlen; /* peer's address length, or 0 if unset */
};
SI_FL_FROM_SET = 0x4000, /* addr.from is set */
};
-/* target types */
-enum {
- TARG_TYPE_NONE = 0, /* no target set, pointer is NULL by definition */
- TARG_TYPE_CLIENT, /* target is a client, pointer is NULL by definition */
- TARG_TYPE_PROXY, /* target is a proxy ; use address with the proxy's settings */
- TARG_TYPE_SERVER, /* target is a server ; use address with server's and its proxy's settings */
- TARG_TYPE_APPLET, /* target is an applet ; use only the applet */
- TARG_TYPE_TASK, /* target is a task running an external applet */
-};
-
#define SI_FL_CAP_SPLICE (SI_FL_CAP_SPLTCP)
-struct server;
-struct proxy;
-struct si_applet;
struct stream_interface;
-struct target {
- int type;
- union {
- void *v; /* pointer value, for any type */
- struct proxy *p; /* when type is TARG_TYPE_PROXY */
- struct server *s; /* when type is TARG_TYPE_SERVER */
- struct si_applet *a; /* when type is TARG_TYPE_APPLET */
- struct task *t; /* when type is TARG_TYPE_TASK */
- struct listener *l; /* when type is TARG_TYPE_CLIENT */
- } ptr;
-};
-
/* operations available on a stream-interface */
struct si_ops {
void (*update)(struct stream_interface *); /* I/O update function */
void (*release)(struct stream_interface *); /* handler to call after the last close() */
/* struct members below are the "remote" part, as seen from the buffer side */
- struct target target; /* the target to connect to (server, proxy, applet, ...) */
int conn_retries; /* number of connect retries left */
int send_proxy_ofs; /* <0 = offset to (re)send from the end, >0 = send all */
struct {
}
/* the target was only on the session, assign it to the SI now */
- copy_target(&s->req->cons->target, &s->target);
+ copy_target(&s->req->cons->conn.target, &s->target);
/* set the correct protocol on the output stream interface */
if (s->target.type == TARG_TYPE_SERVER) {
{
/* we have a dedicated I/O handler for the stats */
stream_int_register_handler(&s->si[1], &cli_applet);
- copy_target(&s->target, &s->si[1].target); // for logging only
+ copy_target(&s->target, &s->si[1].conn.target); // for logging only
s->si[1].conn.data_ctx = s;
s->si[1].applet.st1 = 0;
s->si[1].applet.st0 = STAT_CLI_INIT;
{
struct stream_interface *oldsi;
- if (session->si[0].target.type == TARG_TYPE_APPLET &&
- session->si[0].target.ptr.a == &peer_applet) {
+ if (session->si[0].conn.target.type == TARG_TYPE_APPLET &&
+ session->si[0].conn.target.ptr.a == &peer_applet) {
oldsi = &session->si[0];
}
else {
{
/* we have a dedicated I/O handler for the stats */
stream_int_register_handler(&s->si[1], &peer_applet);
- copy_target(&s->target, &s->si[1].target); // for logging only
+ copy_target(&s->target, &s->si[1].conn.target); // for logging only
s->si[1].conn.data_ctx = s;
s->si[1].applet.st0 = PEER_SESSION_ACCEPT;
s->si[0].err_loc = NULL;
s->si[0].release = NULL;
s->si[0].send_proxy_ofs = 0;
- set_target_client(&s->si[0].target, l);
+ set_target_client(&s->si[0].conn.target, l);
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
if (s->fe->options2 & PR_O2_INDEPSTR)
s->si[1].err_loc = NULL;
s->si[1].release = NULL;
s->si[1].send_proxy_ofs = 0;
- set_target_proxy(&s->si[1].target, s->be);
+ set_target_proxy(&s->si[1].conn.target, s->be);
si_prepare_conn(&s->si[1], peer->proto, peer->data);
s->si[1].exp = TICK_ETERNITY;
s->si[1].flags = SI_FL_NONE;
s->logs.tv_request = now;
s->task->nice = -32; /* small boost for HTTP statistics */
stream_int_register_handler(s->rep->prod, &http_stats_applet);
- copy_target(&s->target, &s->rep->prod->target); // for logging only
+ copy_target(&s->target, &s->rep->prod->conn.target); // for logging only
s->rep->prod->conn.data_ctx = s;
s->rep->prod->applet.st0 = s->rep->prod->applet.st1 = 0;
req->analysers = 0;
struct server *srv;
struct proxy *be;
- switch (si->target.type) {
+ switch (si->conn.target.type) {
case TARG_TYPE_PROXY:
- be = si->target.ptr.p;
+ be = si->conn.target.ptr.p;
srv = NULL;
break;
case TARG_TYPE_SERVER:
- srv = si->target.ptr.s;
+ srv = si->conn.target.ptr.s;
be = srv->proxy;
break;
default:
s->si[0].err_loc = NULL;
s->si[0].release = NULL;
s->si[0].send_proxy_ofs = 0;
- set_target_client(&s->si[0].target, l);
+ set_target_client(&s->si[0].conn.target, l);
s->si[0].exp = TICK_ETERNITY;
s->si[0].flags = SI_FL_NONE;
s->si[1].err_loc = NULL;
s->si[1].release = NULL;
s->si[1].send_proxy_ofs = 0;
- clear_target(&s->si[1].target);
+ clear_target(&s->si[1].conn.target);
si_prepare_embedded(&s->si[1]);
s->si[1].exp = TICK_ETERNITY;
s->si[1].flags = SI_FL_NONE;
*/
s->req->cons->state = SI_ST_REQ; /* new connection requested */
s->req->cons->conn_retries = s->be->conn_retries;
- if (unlikely(s->req->cons->target.type == TARG_TYPE_APPLET &&
+ if (unlikely(s->req->cons->conn.target.type == TARG_TYPE_APPLET &&
!(si_ctrl(s->req->cons) && si_ctrl(s->req->cons)->connect))) {
s->req->cons->state = SI_ST_EST; /* connection established */
s->rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
session_process_counters(s);
- if (s->rep->cons->state == SI_ST_EST && s->rep->cons->target.type != TARG_TYPE_APPLET)
+ if (s->rep->cons->state == SI_ST_EST && s->rep->cons->conn.target.type != TARG_TYPE_APPLET)
si_update(s->rep->cons);
- if (s->req->cons->state == SI_ST_EST && s->req->cons->target.type != TARG_TYPE_APPLET)
+ if (s->req->cons->state == SI_ST_EST && s->req->cons->conn.target.type != TARG_TYPE_APPLET)
si_update(s->req->cons);
s->req->flags &= ~(CF_READ_NULL|CF_READ_PARTIAL|CF_WRITE_NULL|CF_WRITE_PARTIAL|CF_READ_ATTACHED);
/* Call the stream interfaces' I/O handlers when embedded.
* Note that this one may wake the task up again.
*/
- if (s->req->cons->target.type == TARG_TYPE_APPLET ||
- s->rep->cons->target.type == TARG_TYPE_APPLET) {
- if (s->req->cons->target.type == TARG_TYPE_APPLET)
- s->req->cons->target.ptr.a->fct(s->req->cons);
- if (s->rep->cons->target.type == TARG_TYPE_APPLET)
- s->rep->cons->target.ptr.a->fct(s->rep->cons);
+ if (s->req->cons->conn.target.type == TARG_TYPE_APPLET ||
+ s->rep->cons->conn.target.type == TARG_TYPE_APPLET) {
+ if (s->req->cons->conn.target.type == TARG_TYPE_APPLET)
+ s->req->cons->conn.target.ptr.a->fct(s->req->cons);
+ if (s->rep->cons->conn.target.type == TARG_TYPE_APPLET)
+ s->rep->cons->conn.target.ptr.a->fct(s->rep->cons);
if (task_in_rq(t)) {
/* If we woke up, we don't want to requeue the
* task to the wait queue, but rather requeue
DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", app, si, si->owner);
si_prepare_embedded(si);
- set_target_applet(&si->target, app);
+ set_target_applet(&si->conn.target, app);
si->release = app->release;
si->flags |= SI_FL_WAIT_DATA;
return si->owner;
DPRINTF(stderr, "registering handler %p for si %p (was %p)\n", fct, si, si->owner);
si_prepare_task(si);
- clear_target(&si->target);
+ clear_target(&si->conn.target);
si->release = NULL;
si->flags |= SI_FL_WAIT_DATA;
if (!t)
return t;
- set_target_task(&si->target, t);
+ set_target_task(&si->conn.target, t);
t->process = fct;
t->context = si;
*/
void stream_int_unregister_handler(struct stream_interface *si)
{
- if (si->target.type == TARG_TYPE_TASK) {
+ if (si->conn.target.type == TARG_TYPE_TASK) {
/* external handler : kill the task */
- task_delete(si->target.ptr.t);
- task_free(si->target.ptr.t);
+ task_delete(si->conn.target.ptr.t);
+ task_free(si->conn.target.ptr.t);
}
si->release = NULL;
si->owner = NULL;
- clear_target(&si->target);
+ clear_target(&si->conn.target);
}
/* This callback is used to send a valid PROXY protocol line to a socket being