# define QUIC_CFQ_STATE_NEW 0
# define QUIC_CFQ_STATE_TX 1
+/* If set, do not retransmit on loss */
+#define QUIC_CFQ_ITEM_FLAG_UNRELIABLE (1U << 0)
+
/* Returns the frame type of a CFQ item. */
uint64_t ossl_quic_cfq_item_get_frame_type(const QUIC_CFQ_ITEM *item);
/* Returns the PN space for the CFQ item. */
uint32_t ossl_quic_cfq_item_get_pn_space(const QUIC_CFQ_ITEM *item);
+/* Returns 1 if this is an unreliable frame. */
+int ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM *item);
+
/*
* QUIC Control Frame Queue
* ========================
* The frame type is duplicated as the frame_type argument here, even though it
* is also encoded into the buffer. This allows the caller to determine the
* frame type if desired without having to decode the frame.
+ *
+ * flags is zero or more QUIC_CFQ_ITEM_FLAG values.
*/
typedef void (cfq_free_cb)(unsigned char *buf, size_t buf_len, void *arg);
uint32_t priority,
uint32_t pn_space,
uint64_t frame_type,
+ uint32_t flags,
const unsigned char *encoded,
size_t encoded_len,
cfq_free_cb *free_cb,
void *free_cb_arg;
uint64_t frame_type;
size_t encoded_len;
- uint32_t priority, pn_space;
+ uint32_t priority, pn_space, flags;
int state;
};
return ex->pn_space;
}
+int ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM *item)
+{
+ QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
+
+ return (ex->flags & QUIC_CFQ_ITEM_FLAG_UNRELIABLE) != 0;
+}
+
typedef struct quic_cfq_item_list_st {
QUIC_CFQ_ITEM_EX *head, *tail;
} QUIC_CFQ_ITEM_LIST;
uint32_t priority,
uint32_t pn_space,
uint64_t frame_type,
+ uint32_t flags,
const unsigned char *encoded,
size_t encoded_len,
cfq_free_cb *free_cb,
item->free_cb_arg = free_cb_arg;
item->state = QUIC_CFQ_STATE_NEW;
+ item->flags = flags;
list_remove(&cfq->free_list, item);
list_insert_sorted(&cfq->new_list, item, compare);
return &item->public;
{
QUIC_CFQ_ITEM_EX *ex = (QUIC_CFQ_ITEM_EX *)item;
+ if (ossl_quic_cfq_item_is_unreliable(item)) {
+ ossl_quic_cfq_release(cfq, item);
+ return;
+ }
+
switch (ex->state) {
case QUIC_CFQ_STATE_NEW:
if (priority != UINT32_MAX && priority != ex->priority) {
goto err;
if (ossl_quic_cfq_add_frame(ch->cfq, 1, QUIC_PN_SPACE_APP,
- OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID,
+ OSSL_QUIC_FRAME_TYPE_RETIRE_CONN_ID, 0,
(unsigned char *)buf_mem->data, l,
free_frame_data, NULL) == NULL)
goto err;
if (!ossl_quic_cfq_add_frame(ch->cfq, 0, QUIC_PN_SPACE_APP,
OSSL_QUIC_FRAME_TYPE_PATH_RESPONSE,
+ QUIC_CFQ_ITEM_FLAG_UNRELIABLE,
encoded, encoded_len,
free_path_response, NULL))
goto err;
for (i = 0; i < OSSL_NELEM(ref_buf); ++i) {
if (!TEST_ptr(item = ossl_quic_cfq_add_frame(cfq, ref_priority[i],
ref_pn_space[i],
- ref_frame_type[i],
+ ref_frame_type[i], 0,
ref_buf + i,
1,
free_cb,
cfq_freed = 0;
if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(info->cfq, 10,
pn_space,
- OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,
+ OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 0,
placeholder_data,
sizeof(placeholder_data),
cfq_free_cb_, NULL))
if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(h->args.cfq, 1,
QUIC_PN_SPACE_APP,
- OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID,
+ OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, 0,
(unsigned char *)buf_mem->data, l,
free_buf_mem,
buf_mem)))
if (!TEST_ptr(cfq_item = ossl_quic_cfq_add_frame(h->args.cfq, 1,
QUIC_PN_SPACE_APP,
- OSSL_QUIC_FRAME_TYPE_NEW_TOKEN,
+ OSSL_QUIC_FRAME_TYPE_NEW_TOKEN, 0,
(unsigned char *)buf_mem->data, l,
free_buf_mem,
buf_mem)))