* and the other ones are used to setup and release the transport layer.
*/
struct xprt_ops {
- size_t (*rcv_buf)(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, int flags); /* recv callback */
- size_t (*snd_buf)(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, int flags); /* send callback */
+ size_t (*rcv_buf)(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, void *msg_control, size_t *msg_controllen, int flags); /* recv callback */
+ size_t (*snd_buf)(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, void *msg_control, size_t msg_controllen, int flags); /* send callback */
int (*rcv_pipe)(struct connection *conn, void *xprt_ctx, struct pipe *pipe, unsigned int count); /* recv-to-pipe callback */
int (*snd_pipe)(struct connection *conn, void *xprt_ctx, struct pipe *pipe, unsigned int count); /* send-to-pipe callback */
void (*shutr)(struct connection *conn, void *xprt_ctx, int); /* shutr function */
/* snd_buf() already takes care of updating conn->flags and handling
* the FD polling status.
*/
- ret = xprt->snd_buf(conn, NULL, &buffer, buffer.data, flags);
+ ret = xprt->snd_buf(conn, NULL, &buffer, buffer.data, NULL, 0, flags);
if (conn->flags & CO_FL_ERROR)
ret = -1;
return ret;
else
max = b_room(buf);
- ret = max ? conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, 0) : 0;
+ ret = max ? conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, NULL, NULL, 0) : 0;
if (max && !ret && fcgi_recv_allowed(fconn)) {
TRACE_DATA("failed to receive data, subscribing", FCGI_EV_FCONN_RECV, conn);
if (b_data(buf)) {
int ret;
- ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf), flags);
+ ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf), NULL, 0, flags);
if (!ret) {
done = 1;
break;
for (buf = br_head(fconn->mbuf); b_size(buf); buf = br_del_head(fconn->mbuf)) {
if (b_data(buf)) {
int ret = fconn->conn->xprt->snd_buf(fconn->conn, fconn->conn->xprt_ctx,
- buf, b_data(buf), 0);
+ buf, b_data(buf), NULL, 0, 0);
if (!ret)
break;
b_del(buf, ret);
*/
h1c->ibuf.head = sizeof(struct htx);
}
- ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, &h1c->ibuf, max, flags);
+ ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, &h1c->ibuf, max, NULL, 0, flags);
HA_ATOMIC_ADD(&h1c->px_counters->bytes_in, ret);
}
if (h1c->flags & H1C_F_CO_STREAMER)
flags |= CO_SFL_STREAMER;
- ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, &h1c->obuf, b_data(&h1c->obuf), flags);
+ ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, &h1c->obuf, b_data(&h1c->obuf), NULL, 0, flags);
if (ret > 0) {
TRACE_DATA("data sent", H1_EV_H1C_SEND, h1c->conn, 0, 0, (size_t[]){ret});
if (h1c->flags & H1C_F_OUT_FULL) {
#endif
if (!sdo->iobuf.pipe) {
b_add(sdo->iobuf.buf, sdo->iobuf.offset);
- ret = h1c->conn->xprt->rcv_buf(h1c->conn, h1c->conn->xprt_ctx, sdo->iobuf.buf, try, flags);
+ ret = h1c->conn->xprt->rcv_buf(h1c->conn, h1c->conn->xprt_ctx, sdo->iobuf.buf, try, NULL, NULL, flags);
if (ret < try) {
TRACE_STATE("failed to receive data, subscribing", H1_EV_STRM_RECV, h1c->conn);
h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
else
max = b_room(buf);
- ret = max ? conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, 0) : 0;
+ ret = max ? conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, NULL, NULL, 0) : 0;
if (max && !ret && h2_recv_allowed(h2c)) {
TRACE_DATA("failed to receive data, subscribing", H2_EV_H2C_RECV, h2c->conn);
for (buf = br_head(h2c->mbuf); b_size(buf); buf = br_del_head(h2c->mbuf)) {
if (b_data(buf)) {
- int ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf),
+ int ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf), NULL, 0,
flags | (to_send > 1 ? CO_SFL_MSG_MORE : 0));
if (!ret) {
done = 1;
for (buf = br_head(h2c->mbuf); b_size(buf); buf = br_del_head(h2c->mbuf)) {
if (b_data(buf)) {
- int ret = h2c->conn->xprt->snd_buf(h2c->conn, h2c->conn->xprt_ctx, buf, b_data(buf), 0);
+ int ret = h2c->conn->xprt->snd_buf(h2c->conn, h2c->conn->xprt_ctx, buf, b_data(buf), NULL, 0, 0);
if (!ret)
break;
b_del(buf, ret);
goto end;
}
b_realign_if_empty(buf);
- ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, count, flags);
+ ret = conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, count, NULL, NULL, flags);
if (conn->flags & CO_FL_ERROR) {
mux_pt_report_term_evt(ctx, muxc_tevt_type_rcv_err);
se_fl_clr(ctx->sd, SE_FL_RCV_MORE | SE_FL_WANT_ROOM);
TRACE_ENTER(PT_EV_TX_DATA, conn, sc, buf, (size_t[]){count});
- ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, count, flags);
+ ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, count, NULL, 0, flags);
if (ret > 0)
b_del(buf, ret);
}
max = b_room(buf);
- ret = max ? conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, 0) : 0;
+ ret = max ? conn->xprt->rcv_buf(conn, conn->xprt_ctx, buf, max, NULL, NULL, 0) : 0;
if (max && !ret && spop_recv_allowed(spop_conn)) {
TRACE_DATA("failed to receive data, subscribing", SPOP_EV_SPOP_CONN_RECV, conn);
if (b_data(buf)) {
int ret;
- ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf), flags);
+ ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf), NULL, 0, flags);
if (!ret) {
done = 1;
break;
for (buf = br_head(spop_conn->mbuf); b_size(buf); buf = br_del_head(spop_conn->mbuf)) {
if (b_data(buf)) {
int ret = spop_conn->conn->xprt->snd_buf(spop_conn->conn, spop_conn->conn->xprt_ctx,
- buf, b_data(buf), 0);
+ buf, b_data(buf), NULL, 0, 0);
if (!ret)
break;
b_del(buf, ret);
* errno is cleared before starting so that the caller knows that if it spots an
* error without errno, it's pending and can be retrieved via getsockopt(SO_ERROR).
*/
-static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, int flags)
+static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, void *msg_control, size_t *msg_controllen, int flags)
{
ssize_t ret;
size_t try, done = 0;
* EINTR too.
*/
while (count > 0) {
+ struct msghdr msg;
+ struct iovec iov;
+
try = b_contig_space(buf);
if (!try)
break;
if (try > count)
try = count;
- ret = recv(conn->handle.fd, b_tail(buf), try, 0);
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = msg_control;
+ if (msg_controllen)
+ msg.msg_controllen = *msg_controllen;
+ iov.iov_base = b_tail(buf);
+ iov.iov_len = try;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ ret = recvmsg(conn->handle.fd, &msg, 0);
+ if (ret > 0 && msg_controllen != NULL)
+ *msg_controllen = msg.msg_controllen;
if (ret > 0) {
b_add(buf, ret);
* is responsible for this. It's up to the caller to update the buffer's contents
* based on the return value.
*/
-static size_t raw_sock_from_buf(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, int flags)
+static size_t raw_sock_from_buf(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, void *msg_control, size_t msg_controllen, int flags)
{
ssize_t ret;
size_t try, done;
* in which case we accept to do it once again.
*/
while (count) {
+ struct msghdr msg;
+ struct iovec iov;
try = b_contig_data(buf, done);
if (try > count)
try = count;
send_flag = MSG_DONTWAIT | MSG_NOSIGNAL;
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = msg_control;
+ msg.msg_controllen = msg_controllen;
+ iov.iov_base = b_peek(buf, done);
+ iov.iov_len = try;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
if (try < count || flags & CO_SFL_MSG_MORE)
send_flag |= MSG_MORE;
-
- ret = send(conn->handle.fd, b_peek(buf, done), try, send_flag);
+ ret = sendmsg(conn->handle.fd, &msg, send_flag);
if (ret > 0) {
count -= ret;
tmpbuf.data = num;
tmpbuf.head = 0;
flags = (ctx->xprt_st & SSL_SOCK_SEND_MORE) ? CO_SFL_MSG_MORE : 0;
- ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, flags);
+ ret = ctx->xprt->snd_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, num, NULL, 0, flags);
BIO_clear_retry_flags(h);
if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_WR_SH))) {
BIO_set_retry_write(h);
tmpbuf.area = buf;
tmpbuf.data = 0;
tmpbuf.head = 0;
- ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, 0);
+ ret = ctx->xprt->rcv_buf(ctx->conn, ctx->xprt_ctx, &tmpbuf, size, NULL, NULL, 0);
BIO_clear_retry_flags(h);
if (ret == 0 && !(ctx->conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH))) {
BIO_set_retry_read(h);
* avoiding the call if inappropriate. The function does not call the
* connection's polling update function, so the caller is responsible for this.
*/
-static size_t ssl_sock_to_buf(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, int flags)
+static size_t ssl_sock_to_buf(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, void *msg_control, size_t *msg_controllen, int flags)
{
struct ssl_sock_ctx *ctx = xprt_ctx;
ssize_t ret;
if (!ctx)
goto out_error;
+ BUG_ON_HOT(msg_control != NULL);
+
#ifdef SSL_READ_EARLY_DATA_SUCCESS
if (b_data(&ctx->early_buf)) {
try = b_contig_space(buf);
* caller to take care of this. It's up to the caller to update the buffer's
* contents based on the return value.
*/
-static size_t ssl_sock_from_buf(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, int flags)
+static size_t ssl_sock_from_buf(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, void *msg_control, size_t msg_controllen, int flags)
{
struct ssl_sock_ctx *ctx = xprt_ctx;
ssize_t ret;
if (!ctx)
goto out_error;
+ BUG_ON_HOT(msg_control != NULL);
+
if (conn->flags & (CO_FL_WAIT_XPRT | CO_FL_SSL_WAIT_HS | CO_FL_EARLY_SSL_HS)) {
/* a handshake was requested */
TRACE_LEAVE(SSL_EV_CONN_SEND, conn);
/* This XPRT doesn't take care of sending or receiving data, once its handshake
* is done, it just removes itself
*/
-static size_t xprt_handshake_from_buf(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, int flags)
+static size_t xprt_handshake_from_buf(struct connection *conn, void *xprt_ctx, const struct buffer *buf, size_t count, void *msg_control, size_t msg_controllen, int flags)
{
return 0;
}
-static size_t xprt_handshake_to_buf(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, int flags)
+static size_t xprt_handshake_to_buf(struct connection *conn, void *xprt_ctx, struct buffer *buf, size_t count, void *msg_control, size_t *msg_controllen, int flags)
{
return 0;
}