/* Send as many bytes as possible from the pipe to the connection's socket. */ int raw_sock_from_pipe(struct connection *conn, struct pipe *pipe) { int ret, done; if (!conn_ctrl_ready(conn)) return 0; if (!fd_send_ready(conn->t.sock.fd)) return 0; done = 0; while (pipe->data) { ret = splice(pipe->cons, NULL, conn->t.sock.fd, NULL, pipe->data, SPLICE_F_MOVE|SPLICE_F_NONBLOCK); if (ret <= 0) { if (ret == 0 || errno == EAGAIN) { fd_cant_send(conn->t.sock.fd); break; } else if (errno == EINTR) continue; /* here we have another error */ conn->flags |= CO_FL_ERROR; break; } done += ret; pipe->data -= ret; } if (unlikely(conn->flags & CO_FL_WAIT_L4_CONN) && done) conn->flags &= ~CO_FL_WAIT_L4_CONN; return done; }
/* datagram handler callback */ void dgram_fd_handler(int fd) { struct dgram_conn *dgram = fdtab[fd].owner; if (unlikely(!dgram)) return; if (fd_recv_ready(fd)) dgram->data->recv(dgram); else if (fd_send_ready(fd)) dgram->data->send(dgram); return; }
/* Send a message over an established connection. It makes use of send() and * returns the same return code and errno. If the socket layer is not ready yet * then -1 is returned and ENOTSOCK is set into errno. If the fd is not marked * as ready, or if EAGAIN or ENOTCONN is returned, then we return 0. It returns * EMSGSIZE if called with a zero length message. The purpose is to simplify * some rare attempts to directly write on the socket from above the connection * (typically send_proxy). In case of EAGAIN, the fd is marked as "cant_send". * It automatically retries on EINTR. Other errors cause the connection to be * marked as in error state. It takes similar arguments as send() except the * first one which is the connection instead of the file descriptor. Note, * MSG_DONTWAIT and MSG_NOSIGNAL are forced on the flags. */ int conn_sock_send(struct connection *conn, const void *buf, int len, int flags) { int ret; ret = -1; errno = ENOTSOCK; if (conn->flags & CO_FL_SOCK_WR_SH) goto fail; if (!conn_ctrl_ready(conn)) goto fail; errno = EMSGSIZE; if (!len) goto fail; if (!fd_send_ready(conn->t.sock.fd)) goto wait; do { ret = send(conn->t.sock.fd, buf, len, flags | MSG_DONTWAIT | MSG_NOSIGNAL); } while (ret < 0 && errno == EINTR); if (ret > 0) return ret; if (ret == 0 || errno == EAGAIN || errno == ENOTCONN) { wait: fd_cant_send(conn->t.sock.fd); return 0; } fail: conn->flags |= CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH | CO_FL_ERROR; return ret; }
/* I/O callback for fd-based connections. It calls the read/write handlers * provided by the connection's sock_ops, which must be valid. It returns 0. */ int conn_fd_handler(int fd) { struct connection *conn = fdtab[fd].owner; unsigned int flags; if (unlikely(!conn)) return 0; conn_refresh_polling_flags(conn); flags = conn->flags & ~CO_FL_ERROR; /* ensure to call the wake handler upon error */ process_handshake: /* The handshake callbacks are called in sequence. If either of them is * missing something, it must enable the required polling at the socket * layer of the connection. Polling state is not guaranteed when entering * these handlers, so any handshake handler which does not complete its * work must explicitly disable events it's not interested in. Error * handling is also performed here in order to reduce the number of tests * around. */ while (unlikely(conn->flags & (CO_FL_HANDSHAKE | CO_FL_ERROR))) { if (unlikely(conn->flags & CO_FL_ERROR)) goto leave; if (conn->flags & CO_FL_ACCEPT_PROXY) if (!conn_recv_proxy(conn, CO_FL_ACCEPT_PROXY)) goto leave; if (conn->flags & CO_FL_SEND_PROXY) if (!conn_si_send_proxy(conn, CO_FL_SEND_PROXY)) goto leave; #ifdef USE_OPENSSL if (conn->flags & CO_FL_SSL_WAIT_HS) if (!ssl_sock_handshake(conn, CO_FL_SSL_WAIT_HS)) goto leave; #endif } /* Once we're purely in the data phase, we disable handshake polling */ if (!(conn->flags & CO_FL_POLL_SOCK)) __conn_sock_stop_both(conn); /* The data layer might not be ready yet (eg: when using embryonic * sessions). If we're about to move data, we must initialize it first. * The function may fail and cause the connection to be destroyed, thus * we must not use it anymore and should immediately leave instead. */ if ((conn->flags & CO_FL_INIT_DATA) && conn->data->init(conn) < 0) return 0; /* The data transfer starts here and stops on error and handshakes. Note * that we must absolutely test conn->xprt at each step in case it suddenly * changes due to a quick unexpected close(). */ if (conn->xprt && fd_recv_ready(fd) && ((conn->flags & (CO_FL_DATA_RD_ENA|CO_FL_WAIT_ROOM|CO_FL_ERROR|CO_FL_HANDSHAKE)) == CO_FL_DATA_RD_ENA)) { /* force detection of a flag change : it's impossible to have both * CONNECTED and WAIT_CONN so we're certain to trigger a change. */ flags = CO_FL_WAIT_L4_CONN | CO_FL_CONNECTED; conn->data->recv(conn); } if (conn->xprt && fd_send_ready(fd) && ((conn->flags & (CO_FL_DATA_WR_ENA|CO_FL_WAIT_DATA|CO_FL_ERROR|CO_FL_HANDSHAKE)) == CO_FL_DATA_WR_ENA)) { /* force detection of a flag change : it's impossible to have both * CONNECTED and WAIT_CONN so we're certain to trigger a change. */ flags = CO_FL_WAIT_L4_CONN | CO_FL_CONNECTED; conn->data->send(conn); } /* It may happen during the data phase that a handshake is * enabled again (eg: SSL) */ if (unlikely(conn->flags & (CO_FL_HANDSHAKE | CO_FL_ERROR))) goto process_handshake; if (unlikely(conn->flags & CO_FL_WAIT_L4_CONN)) { /* still waiting for a connection to establish and nothing was * attempted yet to probe the connection. Then let's retry the * connect(). */ if (!tcp_connect_probe(conn)) goto leave; } leave: /* The wake callback may be used to process a critical error and abort the * connection. If so, we don't want to go further as the connection will * have been released and the FD destroyed. */ if ((conn->flags & CO_FL_WAKE_DATA) && ((conn->flags ^ flags) & CO_FL_CONN_STATE) && conn->data->wake(conn) < 0) return 0; /* Last check, verify if the connection just established */ if (unlikely(!(conn->flags & (CO_FL_WAIT_L4_CONN | CO_FL_WAIT_L6_CONN | CO_FL_CONNECTED)))) conn->flags |= CO_FL_CONNECTED; /* remove the events before leaving */ fdtab[fd].ev &= FD_POLL_STICKY; /* commit polling changes */ conn_cond_update_polling(conn); return 0; }
/* This callback is used to send a valid PROXY protocol line to a socket being * established. It returns 0 if it fails in a fatal way or needs to poll to go * further, otherwise it returns non-zero and removes itself from the connection's * flags (the bit is provided in <flag> by the caller). It is designed to be * called by the connection handler and relies on it to commit polling changes. * Note that it can emit a PROXY line by relying on the other end's address * when the connection is attached to a stream interface, or by resolving the * local address otherwise (also called a LOCAL line). */ int conn_si_send_proxy(struct connection *conn, unsigned int flag) { /* we might have been called just after an asynchronous shutw */ if (conn->flags & CO_FL_SOCK_WR_SH) goto out_error; if (!conn_ctrl_ready(conn)) goto out_error; if (!fd_send_ready(conn->t.sock.fd)) goto out_wait; /* If we have a PROXY line to send, we'll use this to validate the * connection, in which case the connection is validated only once * we've sent the whole proxy line. Otherwise we use connect(). */ while (conn->send_proxy_ofs) { int ret; /* The target server expects a PROXY line to be sent first. * If the send_proxy_ofs is negative, it corresponds to the * offset to start sending from then end of the proxy string * (which is recomputed every time since it's constant). If * it is positive, it means we have to send from the start. * We can only send a "normal" PROXY line when the connection * is attached to a stream interface. Otherwise we can only * send a LOCAL line (eg: for use with health checks). */ if (conn->data == &si_conn_cb) { struct stream_interface *si = conn->owner; struct connection *remote = objt_conn(si->ob->prod->end); ret = make_proxy_line(trash.str, trash.size, objt_server(conn->target), remote); } else { /* The target server expects a LOCAL line to be sent first. Retrieving * local or remote addresses may fail until the connection is established. */ conn_get_from_addr(conn); if (!(conn->flags & CO_FL_ADDR_FROM_SET)) goto out_wait; conn_get_to_addr(conn); if (!(conn->flags & CO_FL_ADDR_TO_SET)) goto out_wait; ret = make_proxy_line(trash.str, trash.size, objt_server(conn->target), conn); } if (!ret) goto out_error; if (conn->send_proxy_ofs > 0) conn->send_proxy_ofs = -ret; /* first call */ /* we have to send trash from (ret+sp for -sp bytes). If the * data layer has a pending write, we'll also set MSG_MORE. */ ret = send(conn->t.sock.fd, trash.str + ret + conn->send_proxy_ofs, -conn->send_proxy_ofs, (conn->flags & CO_FL_DATA_WR_ENA) ? MSG_MORE : 0); if (ret == 0) goto out_wait; if (ret < 0) { if (errno == EAGAIN || errno == ENOTCONN) goto out_wait; if (errno == EINTR) continue; conn->flags |= CO_FL_SOCK_RD_SH | CO_FL_SOCK_WR_SH; goto out_error; } conn->send_proxy_ofs += ret; /* becomes zero once complete */ if (conn->send_proxy_ofs != 0) goto out_wait; /* OK we've sent the whole line, we're connected */ break; } /* The connection is ready now, simply return and let the connection * handler notify upper layers if needed. */ if (conn->flags & CO_FL_WAIT_L4_CONN) conn->flags &= ~CO_FL_WAIT_L4_CONN; conn->flags &= ~flag; return 1; out_error: /* Write error on the file descriptor */ conn->flags |= CO_FL_ERROR; return 0; out_wait: __conn_sock_stop_recv(conn); fd_cant_send(conn->t.sock.fd); return 0; }