Skip to content

Commit

Permalink
Release 1.14.0
Browse files Browse the repository at this point in the history
- [API Change] Disable packet sending if full batch cannot be sent
  If lsquic_packets_out_f() cannot send the whole batch, disable
  packet sending until lsquic_engine_send_unsent_packets() is called.
- [BUGFIX] Handle case when STREAM frame does not fit.
- [BUGFIX] Always allow incoming STREAM frames to overlap.  Peers
  may send overlapping STREAM frames even if using versions older
  than Q043.
- Custom header set fixes:
  - set "FIN reached" flag when custom header with FIN flag is
    claimed;
  - do not return custom header set for a reset stream.
  • Loading branch information
Dmitri Tikhonov committed Sep 6, 2018
1 parent 3b55e6a commit 14e3680
Show file tree
Hide file tree
Showing 19 changed files with 187 additions and 70 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
2018-09-06
- 1.14.0
- [API Change] Disable packet sending if full batch cannot be sent
If lsquic_packets_out_f() cannot send the whole batch, disable
packet sending until lsquic_engine_send_unsent_packets() is called.
- [BUGFIX] Handle case when STREAM frame does not fit.
- [BUGFIX] Always allow incoming STREAM frames to overlap. Peers
may send overlapping STREAM frames even if using versions older
than Q043.
- Custom header set fixes:
- set "FIN reached" flag when custom header with FIN flag is
claimed;
- do not return custom header set for a reset stream.

2018-08-27

- 1.13.0
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ include_directories(${BORINGSSL_INCLUDE} ${VCPKG_INCLUDE} )
link_directories( ${BORINGSSL_LIB} )

SET(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories( include )
include_directories( include src/lshpack)
IF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# Find libevent on FreeBSD:
include_directories( /usr/local/include )
Expand Down
11 changes: 6 additions & 5 deletions include/lsquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern "C" {
#endif

#define LSQUIC_MAJOR_VERSION 1
#define LSQUIC_MINOR_VERSION 13
#define LSQUIC_MINOR_VERSION 14
#define LSQUIC_PATCH_VERSION 0

/**
Expand Down Expand Up @@ -471,9 +471,10 @@ struct lsquic_out_spec

/**
* Returns number of packets successfully sent out or -1 on error. -1 should
* only be returned if no packets were sent out. If -1 is returned,
* no packets will be attempted to be sent out until
* @ref lsquic_engine_send_unsent_packets() is called.
* only be returned if no packets were sent out. If -1 is returned or if the
* return value is smaller than `n_packets_out', this indicates that sending
* of packets is not possible No packets will be attempted to be sent out
* until @ref lsquic_engine_send_unsent_packets() is called.
*/
typedef int (*lsquic_packets_out_f)(
void *packets_out_ctx,
Expand Down Expand Up @@ -625,7 +626,7 @@ lsquic_engine_connect (lsquic_engine_t *, const struct sockaddr *local_sa,
/**
* Pass incoming packet to the QUIC engine. This function can be called
* more than once in a row. After you add one or more packets, call
* lsquic_engine_process_conns_with_incoming() to schedule output, if any.
* lsquic_engine_process_conns() to schedule output, if any.
*
* @retval 0 Packet was processed by a real connection.
*
Expand Down
2 changes: 1 addition & 1 deletion src/liblsquic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ SET(lsquic_STAT_SRCS
lsquic_xxhash.c
lsquic_buf.c
lsquic_min_heap.c
lshpack.c
../lshpack/lshpack.c
lsquic_parse_Q044.c
lsquic_http1x_if.c
)
Expand Down
8 changes: 6 additions & 2 deletions src/liblsquic/lsquic_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,13 +977,17 @@ send_batch (lsquic_engine_t *engine, struct conns_out_iter *conns_iter,
batch->packets[i]->po_sent = now;
n_sent = engine->packets_out(engine->packets_out_ctx, batch->outs,
n_to_send);
if (n_sent < (int) n_to_send)
{
engine->pub.enp_flags &= ~ENPUB_CAN_SEND;
LSQ_DEBUG("cannot send packets");
EV_LOG_GENERIC_EVENT("cannot send packets");
}
if (n_sent >= 0)
LSQ_DEBUG("packets out returned %d (out of %u)", n_sent, n_to_send);
else
{
engine->pub.enp_flags &= ~ENPUB_CAN_SEND;
LSQ_DEBUG("packets out returned an error: %s", strerror(errno));
EV_LOG_GENERIC_EVENT("cannot send packets");
n_sent = 0;
}
if (n_sent > 0)
Expand Down
3 changes: 0 additions & 3 deletions src/liblsquic/lsquic_full_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,9 +913,6 @@ new_stream_ext (struct full_conn *conn, uint32_t stream_id, int if_idx,
{
struct lsquic_stream *stream;

if (conn->fc_conn.cn_version >= LSQVER_043)
stream_ctor_flags |= SCF_ALLOW_OVERLAP;

stream = lsquic_stream_new_ext(stream_id, &conn->fc_pub,
conn->fc_stream_ifs[if_idx].stream_if,
conn->fc_stream_ifs[if_idx].stream_if_ctx, conn->fc_settings->es_sfcw,
Expand Down
7 changes: 6 additions & 1 deletion src/liblsquic/lsquic_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ struct parse_funcs
struct packin_parse_state *);
enum QUIC_FRAME_TYPE
(*pf_parse_frame_type) (unsigned char);
/* Return used buffer length */
/* Return used buffer length or a negative value if there was not enough
* room to write the stream frame. In the latter case, the negative of
* the negative return value is the number of bytes required. The
* exception is -1, which is a generic error code, as we always need
* more than 1 byte to write a STREAM frame.
*/
int
(*pf_gen_stream_frame) (unsigned char *buf, size_t bufsz,
uint32_t stream_id, uint64_t offset,
Expand Down
2 changes: 1 addition & 1 deletion src/liblsquic/lsquic_parse_Q044.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ gen_long_pkt_header (const struct lsquic_conn *lconn,
p += 4;


assert(need = p - buf);
assert(need == (unsigned int)(p - buf));
return p - buf;
}

Expand Down
9 changes: 9 additions & 0 deletions src/liblsquic/lsquic_parse_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,13 @@ int
lsquic_iquic_parse_packet_in_begin (struct lsquic_packet_in *,
size_t length, int is_server, struct packin_parse_state *);

/* Instead of just -1 like CHECK_SPACE(), this macro returns the number
* of bytes needed.
*/
#define CHECK_STREAM_SPACE(need, pstart, pend) do { \
if ((intptr_t) (need) > ((pend) - (pstart))) { \
return -((int) (need)); \
} \
} while (0)

#endif
4 changes: 2 additions & 2 deletions src/liblsquic/lsquic_parse_gquic_be.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ gquic_be_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
dlen = (size < n_avail) << 1;
n_avail -= dlen;

CHECK_SPACE(1 + olen + slen + dlen +
CHECK_STREAM_SPACE(1 + olen + slen + dlen +
+ 1 /* We need to write at least 1 byte */, buf, buf + buf_len);

#if __BYTE_ORDER == __LITTLE_ENDIAN
Expand Down Expand Up @@ -255,7 +255,7 @@ gquic_be_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
else
{
dlen = 2;
CHECK_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
CHECK_STREAM_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
#if __BYTE_ORDER == __LITTLE_ENDIAN
stream_id = bswap_32(stream_id);
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/liblsquic/lsquic_parse_gquic_le.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ gquic_le_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
dlen = (size < n_avail) << 1;
n_avail -= dlen;

CHECK_SPACE(1 + olen + slen + dlen +
CHECK_STREAM_SPACE(1 + olen + slen + dlen +
+ 1 /* We need to write at least 1 byte */, buf, buf + buf_len);

memcpy(p, &stream_id, slen);
Expand All @@ -238,7 +238,7 @@ gquic_le_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_i
else
{
dlen = 2;
CHECK_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
CHECK_STREAM_SPACE(1 + slen + olen + 2, buf, buf + buf_len);
memcpy(p, &stream_id, slen);
p += slen;
memcpy(p, &offset, olen);
Expand Down
46 changes: 31 additions & 15 deletions src/liblsquic/lsquic_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,6 @@ lsquic_stream_new_ext (uint32_t id, struct lsquic_conn_public *conn_pub,
lsquic_stream_call_on_new(stream);
if (ctor_flags & SCF_DISP_RW_ONCE)
stream->stream_flags |= STREAM_RW_ONCE;
if (ctor_flags & SCF_ALLOW_OVERLAP)
stream->stream_flags |= STREAM_ALLOW_OVERLAP;
return stream;
}

Expand Down Expand Up @@ -559,17 +557,12 @@ lsquic_stream_frame_in (lsquic_stream_t *stream, stream_frame_t *frame)
}
else if (INS_FRAME_OVERLAP == ins_frame)
{
if (stream->stream_flags & STREAM_ALLOW_OVERLAP)
{
LSQ_DEBUG("overlap: switching DATA IN implementation");
stream->data_in = stream->data_in->di_if->di_switch_impl(
stream->data_in, stream->read_offset);
if (stream->data_in)
goto insert_frame;
stream->data_in = data_in_error_new();
}
else
LSQ_DEBUG("overlap not supported");
LSQ_DEBUG("overlap: switching DATA IN implementation");
stream->data_in = stream->data_in->di_if->di_switch_impl(
stream->data_in, stream->read_offset);
if (stream->data_in)
goto insert_frame;
stream->data_in = data_in_error_new();
lsquic_packet_in_put(stream->conn_pub->mm, frame->packet_in);
lsquic_malo_put(frame);
return -1;
Expand Down Expand Up @@ -1573,6 +1566,7 @@ stream_write_to_packet (struct frame_gen_ctx *fg_ctx, const size_t size)
stream->tosend_off);
need_at_least = stream_header_sz + (size > 0);
hsk = LSQUIC_STREAM_HANDSHAKE == stream->id;
get_packet:
packet_out = get_packet[hsk](send_ctl, need_at_least, stream);
if (!packet_out)
return SWTP_STOP;
Expand All @@ -1588,8 +1582,18 @@ stream_write_to_packet (struct frame_gen_ctx *fg_ctx, const size_t size)
frame_gen_fin(fg_ctx), size, frame_gen_read, fg_ctx);
if (len < 0)
{
LSQ_ERROR("could not generate stream frame");
return SWTP_ERROR;
if (-len > (int) need_at_least)
{
LSQ_DEBUG("need more room (%d bytes) than initially calculated "
"%u bytes, will try again", -len, need_at_least);
need_at_least = -len;
goto get_packet;
}
else
{
LSQ_ERROR("could not generate stream frame");
return SWTP_ERROR;
}
}

EV_LOG_GENERATED_STREAM_FRAME(LSQUIC_LOG_CONN_ID, pf,
Expand Down Expand Up @@ -2181,6 +2185,13 @@ lsquic_stream_get_hset (struct lsquic_stream *stream)
{
void *hset;

if (stream->stream_flags & STREAM_RST_FLAGS)
{
LSQ_INFO("%s: stream is reset, no headers returned", __func__);
errno = ECONNRESET;
return NULL;
}

if ((stream->stream_flags & (STREAM_USE_HEADERS|STREAM_HAVE_UH))
!= (STREAM_USE_HEADERS|STREAM_HAVE_UH))
{
Expand All @@ -2204,6 +2215,11 @@ lsquic_stream_get_hset (struct lsquic_stream *stream)
hset = stream->uh->uh_hset;
stream->uh->uh_hset = NULL;
destroy_uh(stream);
if (stream->stream_flags & STREAM_HEAD_IN_FIN)
{
stream->stream_flags |= STREAM_FIN_REACHED;
SM_HISTORY_APPEND(stream, SHE_REACH_FIN);
}
LSQ_DEBUG("return header set");
return hset;
}
2 changes: 0 additions & 2 deletions src/liblsquic/lsquic_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ struct lsquic_stream
STREAM_ONNEW_DONE = (1 <<26), /* on_new_stream has been called */
STREAM_AUTOSWITCH = (1 <<27),
STREAM_RW_ONCE = (1 <<28), /* When set, read/write events are dispatched once per call */
STREAM_ALLOW_OVERLAP= (1 <<29),
} stream_flags;

/* There are more than one reason that a stream may be put onto
Expand Down Expand Up @@ -140,7 +139,6 @@ enum stream_ctor_flags
* performance.
*/
SCF_DISP_RW_ONCE = (1 << 3),
SCF_ALLOW_OVERLAP = (1 << 4), /* Allow STREAM frames to overlap */
};

lsquic_stream_t *
Expand Down
2 changes: 1 addition & 1 deletion src/liblsquic/lshpack.c → src/lshpack/lshpack.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ SOFTWARE.
#if LS_HPACK_EMIT_TEST_CODE
#include "lshpack-test.h"
#endif
#include XXH_HEADER_NAME
#include "lsquic_xxhash.h"

#define HPACK_STATIC_TABLE_SIZE 61
#define INITIAL_DYNAMIC_TABLE_SIZE 4096
Expand Down
File renamed without changes.
2 changes: 2 additions & 0 deletions test/prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ send_unsent (evutil_socket_t fd, short what, void *arg)
event_del(prog->prog_send);
event_free(prog->prog_send);
prog->prog_send = NULL;
LSQ_DEBUG("on_write event fires");
lsquic_engine_send_unsent_packets(prog->prog_engine);
}

Expand All @@ -438,6 +439,7 @@ void
prog_sport_cant_send (struct prog *prog, int fd)
{
assert(!prog->prog_send);
LSQ_DEBUG("cannot send: register on_write event");
prog->prog_send = event_new(prog->prog_eb, fd, EV_WRITE, send_unsent, prog);
event_add(prog->prog_send, NULL);
}
5 changes: 4 additions & 1 deletion test/test_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,7 @@ send_packets_one_by_one (const struct lsquic_out_spec *specs, unsigned count)
assert(count > 0);
sport = specs[0].peer_ctx;
LSQ_NOTICE("sending \"randomly\" fails");
prog_sport_cant_send(sport->sp_prog, sport->fd);
goto random_send_failure;
}
}
Expand Down Expand Up @@ -951,14 +952,16 @@ send_packets_one_by_one (const struct lsquic_out_spec *specs, unsigned count)
}
}

if (n < count)
prog_sport_cant_send(sport->sp_prog, sport->fd);

if (n > 0)
return n;
else if (s < 0)
{
#if LSQUIC_RANDOM_SEND_FAILURE
random_send_failure:
#endif
prog_sport_cant_send(sport->sp_prog, sport->fd);
return -1;
}
else
Expand Down
Loading

0 comments on commit 14e3680

Please sign in to comment.