mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-18 19:50:54 +00:00
MEDIUM: connection: make xprt->snd_buf() take the byte count in argument
This way the senders don't need to modify the buffer's metadata anymore nor to know about the output's split point. This way the functions can take a const buffer and it's clearer who's in charge of updating the buffer after a send. That's why the buffer realignment is now performed by the caller of the transport's snd_buf() functions. The return type was updated to return a size_t to comply with the count argument.
This commit is contained in:
parent
55f3ce1c91
commit
787db9a6a4
@ -269,7 +269,7 @@ enum {
|
||||
*/
|
||||
struct xprt_ops {
|
||||
int (*rcv_buf)(struct connection *conn, struct buffer *buf, int count); /* recv callback */
|
||||
int (*snd_buf)(struct connection *conn, struct buffer *buf, int flags); /* send callback */
|
||||
size_t (*snd_buf)(struct connection *conn, const struct buffer *buf, size_t count, int flags); /* send callback */
|
||||
int (*rcv_pipe)(struct connection *conn, struct pipe *pipe, unsigned int count); /* recv-to-pipe callback */
|
||||
int (*snd_pipe)(struct connection *conn, struct pipe *pipe); /* send-to-pipe callback */
|
||||
void (*shutr)(struct connection *, int); /* shutr function */
|
||||
|
18
src/mux_h2.c
18
src/mux_h2.c
@ -2213,8 +2213,13 @@ static void h2_send(struct connection *conn)
|
||||
if (h2c->flags & (H2_CF_MUX_MFULL | H2_CF_DEM_MBUSY | H2_CF_DEM_MROOM))
|
||||
flags |= CO_SFL_MSG_MORE;
|
||||
|
||||
if (h2c->mbuf->o && conn->xprt->snd_buf(conn, h2c->mbuf, flags) <= 0)
|
||||
break;
|
||||
if (h2c->mbuf->o) {
|
||||
int ret = conn->xprt->snd_buf(conn, h2c->mbuf, h2c->mbuf->o, flags);
|
||||
if (!ret)
|
||||
break;
|
||||
b_del(h2c->mbuf, ret);
|
||||
b_realign_if_empty(h2c->mbuf);
|
||||
}
|
||||
|
||||
/* wrote at least one byte, the buffer is not full anymore */
|
||||
h2c->flags &= ~(H2_CF_MUX_MFULL | H2_CF_DEM_MROOM);
|
||||
@ -2369,8 +2374,13 @@ static struct task *h2_timeout_task(struct task *t, void *context, unsigned shor
|
||||
if (h2c_send_goaway_error(h2c, NULL) <= 0)
|
||||
h2c->flags |= H2_CF_GOAWAY_FAILED;
|
||||
|
||||
if (h2c->mbuf->o && !(h2c->flags & H2_CF_GOAWAY_FAILED) && conn_xprt_ready(h2c->conn))
|
||||
h2c->conn->xprt->snd_buf(h2c->conn, h2c->mbuf, 0);
|
||||
if (h2c->mbuf->o && !(h2c->flags & H2_CF_GOAWAY_FAILED) && conn_xprt_ready(h2c->conn)) {
|
||||
int ret = h2c->conn->xprt->snd_buf(h2c->conn, h2c->mbuf, h2c->mbuf->o, 0);
|
||||
if (ret > 0) {
|
||||
b_del(h2c->mbuf, ret);
|
||||
b_realign_if_empty(h2c->mbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* either we can release everything now or it will be done later once
|
||||
* the last stream closes.
|
||||
|
@ -174,7 +174,13 @@ static int mux_pt_rcv_buf(struct conn_stream *cs, struct buffer *buf, int count)
|
||||
/* Called from the upper layer, to send data */
|
||||
static int mux_pt_snd_buf(struct conn_stream *cs, struct buffer *buf, int flags)
|
||||
{
|
||||
return (cs->conn->xprt->snd_buf(cs->conn, buf, flags));
|
||||
int ret = cs->conn->xprt->snd_buf(cs->conn, buf, buf->o, flags);
|
||||
|
||||
if (ret > 0)
|
||||
b_del(buf, ret);
|
||||
|
||||
b_realign_if_empty(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_HAP_LINUX_SPLICE)
|
||||
|
@ -360,19 +360,22 @@ static int raw_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
|
||||
}
|
||||
|
||||
|
||||
/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
|
||||
* <flags> may contain some CO_SFL_* flags to hint the system about other
|
||||
* pending data for example.
|
||||
/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
|
||||
* socket. <flags> may contain some CO_SFL_* flags to hint the system about
|
||||
* other pending data for example, but this flag is ignored at the moment.
|
||||
* Only one call to send() is performed, unless the buffer wraps, in which case
|
||||
* a second call may be performed. The connection's flags are updated with
|
||||
* whatever special event is detected (error, empty). The caller is responsible
|
||||
* for taking care of those events and avoiding the call if inappropriate. The
|
||||
* function does not call the connection's polling update function, so the caller
|
||||
* is responsible for this.
|
||||
* is responsible for this. It's up to the caller to update the buffer's contents
|
||||
* based on the return value.
|
||||
*/
|
||||
static int raw_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
|
||||
static size_t raw_sock_from_buf(struct connection *conn, const struct buffer *buf, size_t count, int flags)
|
||||
{
|
||||
int ret, try, done, send_flag;
|
||||
ssize_t ret;
|
||||
size_t try, done;
|
||||
int send_flag;
|
||||
|
||||
if (!conn_ctrl_ready(conn))
|
||||
return 0;
|
||||
@ -386,26 +389,21 @@ static int raw_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
||||
* to send() unless the buffer wraps and we exactly fill the first hunk,
|
||||
* in which case we accept to do it once again.
|
||||
*/
|
||||
while (buf->o) {
|
||||
try = buf->o;
|
||||
/* outgoing data may wrap at the end */
|
||||
if (buf->data + try > buf->p)
|
||||
try = buf->data + try - buf->p;
|
||||
while (count) {
|
||||
try = b_contig_data(buf, done);
|
||||
if (try > count)
|
||||
try = count;
|
||||
|
||||
send_flag = MSG_DONTWAIT | MSG_NOSIGNAL;
|
||||
if (try < buf->o || flags & CO_SFL_MSG_MORE)
|
||||
if (try < count || flags & CO_SFL_MSG_MORE)
|
||||
send_flag |= MSG_MORE;
|
||||
|
||||
ret = send(conn->handle.fd, b_head(buf), try, send_flag);
|
||||
ret = send(conn->handle.fd, b_peek(buf, done), try, send_flag);
|
||||
|
||||
if (ret > 0) {
|
||||
buf->o -= ret;
|
||||
count -= ret;
|
||||
done += ret;
|
||||
|
||||
if (likely(buffer_empty(buf)))
|
||||
/* optimize data alignment in the buffer */
|
||||
buf->p = buf->data;
|
||||
|
||||
/* if the system buffer is full, don't insist */
|
||||
if (ret < try)
|
||||
break;
|
||||
|
@ -5493,19 +5493,22 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
|
||||
}
|
||||
|
||||
|
||||
/* Send all pending bytes from buffer <buf> to connection <conn>'s socket.
|
||||
* <flags> may contain some CO_SFL_* flags to hint the system about other
|
||||
* pending data for example, but this flag is ignored at the moment.
|
||||
/* Send up to <count> pending bytes from buffer <buf> to connection <conn>'s
|
||||
* socket. <flags> may contain some CO_SFL_* flags to hint the system about
|
||||
* other pending data for example, but this flag is ignored at the moment.
|
||||
* Only one call to send() is performed, unless the buffer wraps, in which case
|
||||
* a second call may be performed. The connection's flags are updated with
|
||||
* whatever special event is detected (error, empty). The caller is responsible
|
||||
* for taking care of those events and avoiding the call if inappropriate. The
|
||||
* function does not call the connection's polling update function, so the caller
|
||||
* is responsible for this.
|
||||
* is responsible for this. The buffer's output is not adjusted, it's up to the
|
||||
* caller to take care of this. It's up to the caller to update the buffer's
|
||||
* contents based on the return value.
|
||||
*/
|
||||
static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int flags)
|
||||
static size_t ssl_sock_from_buf(struct connection *conn, const struct buffer *buf, size_t count, int flags)
|
||||
{
|
||||
int ret, try, done;
|
||||
ssize_t ret;
|
||||
size_t try, done;
|
||||
|
||||
done = 0;
|
||||
conn_refresh_polling_flags(conn);
|
||||
@ -5521,14 +5524,14 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
||||
* to send() unless the buffer wraps and we exactly fill the first hunk,
|
||||
* in which case we accept to do it once again.
|
||||
*/
|
||||
while (buf->o) {
|
||||
while (count) {
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10101000L)
|
||||
size_t written_data;
|
||||
#endif
|
||||
|
||||
try = b_contig_data(buf, 0);
|
||||
if (try > buf->o)
|
||||
try = buf->o;
|
||||
try = b_contig_data(buf, done);
|
||||
if (try > count)
|
||||
try = count;
|
||||
|
||||
if (!(flags & CO_SFL_STREAMER) &&
|
||||
!(conn->xprt_st & SSL_SOCK_SEND_UNLIMITED) &&
|
||||
@ -5564,7 +5567,7 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = SSL_write_early_data(conn->xprt_ctx, b_head(buf), try, &written_data);
|
||||
ret = SSL_write_early_data(conn->xprt_ctx, b_peek(buf, done), try, &written_data);
|
||||
if (ret == 1) {
|
||||
ret = written_data;
|
||||
conn->sent_early_data += ret;
|
||||
@ -5577,7 +5580,7 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
||||
|
||||
} else
|
||||
#endif
|
||||
ret = SSL_write(conn->xprt_ctx, b_head(buf), try);
|
||||
ret = SSL_write(conn->xprt_ctx, b_peek(buf, done), try);
|
||||
|
||||
if (conn->flags & CO_FL_ERROR) {
|
||||
/* CO_FL_ERROR may be set by ssl_sock_infocbk */
|
||||
@ -5585,13 +5588,8 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
||||
}
|
||||
if (ret > 0) {
|
||||
conn->xprt_st &= ~SSL_SOCK_SEND_UNLIMITED;
|
||||
|
||||
buf->o -= ret;
|
||||
count -= ret;
|
||||
done += ret;
|
||||
|
||||
if (likely(buffer_empty(buf)))
|
||||
/* optimize data alignment in the buffer */
|
||||
buf->p = buf->data;
|
||||
}
|
||||
else {
|
||||
ret = SSL_get_error(conn->xprt_ctx, ret);
|
||||
|
Loading…
Reference in New Issue
Block a user