summaryrefslogtreecommitdiffstats
path: root/include/internal/quic_txp.h
blob: 607cefc0109c29f93de1d9fcf12cb980e2960ba6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
 * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#ifndef OSSL_QUIC_TXP_H
# define OSSL_QUIC_TXP_H

# include <openssl/ssl.h>
# include "internal/quic_types.h"
# include "internal/quic_predef.h"
# include "internal/quic_record_tx.h"
# include "internal/quic_cfq.h"
# include "internal/quic_txpim.h"
# include "internal/quic_stream.h"
# include "internal/quic_stream_map.h"
# include "internal/quic_fc.h"
# include "internal/bio_addr.h"
# include "internal/time.h"
# include "internal/qlog.h"

# ifndef OPENSSL_NO_QUIC

/*
 * QUIC TX Packetiser
 * ==================
 */
typedef struct ossl_quic_tx_packetiser_args_st {
    /* Configuration Settings */
    QUIC_CONN_ID    cur_scid;   /* Current Source Connection ID we use. */
    QUIC_CONN_ID    cur_dcid;   /* Current Destination Connection ID we use. */
    BIO_ADDR        peer;       /* Current destination L4 address we use. */
    uint32_t        ack_delay_exponent; /* ACK delay exponent used when encoding. */

    /* Injected Dependencies */
    OSSL_QTX        *qtx;       /* QUIC Record Layer TX we are using */
    QUIC_TXPIM      *txpim;     /* QUIC TX'd Packet Information Manager */
    QUIC_CFQ        *cfq;       /* QUIC Control Frame Queue */
    OSSL_ACKM       *ackm;      /* QUIC Acknowledgement Manager */
    QUIC_STREAM_MAP *qsm;       /* QUIC Streams Map */
    QUIC_TXFC       *conn_txfc; /* QUIC Connection-Level TX Flow Controller */
    QUIC_RXFC       *conn_rxfc; /* QUIC Connection-Level RX Flow Controller */
    QUIC_RXFC       *max_streams_bidi_rxfc; /* QUIC RXFC for MAX_STREAMS generation */
    QUIC_RXFC       *max_streams_uni_rxfc;
    const OSSL_CC_METHOD *cc_method; /* QUIC Congestion Controller */
    OSSL_CC_DATA    *cc_data;   /* QUIC Congestion Controller Instance */
    OSSL_TIME       (*now)(void *arg);  /* Callback to get current time. */
    void            *now_arg;
    QLOG            *(*get_qlog_cb)(void *arg); /* Optional QLOG retrieval func */
    void            *get_qlog_cb_arg;

    /*
     * Injected dependencies - crypto streams.
     *
     * Note: There is no crypto stream for the 0-RTT EL.
     *       crypto[QUIC_PN_SPACE_APP] is the 1-RTT crypto stream.
     */
    QUIC_SSTREAM    *crypto[QUIC_PN_SPACE_NUM];

 } OSSL_QUIC_TX_PACKETISER_ARGS;

OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args);

typedef void (ossl_quic_initial_token_free_fn)(const unsigned char *buf,
                                               size_t buf_len, void *arg);

void ossl_quic_tx_packetiser_free(OSSL_QUIC_TX_PACKETISER *txp);

/*
 * When in the closing state we need to maintain a count of received bytes
 * so that we can limit the number of close connection frames we send.
 * Refer RFC 9000 s. 10.2.1 Closing Connection State.
 */
void ossl_quic_tx_packetiser_record_received_closing_bytes(
        OSSL_QUIC_TX_PACKETISER *txp, size_t n);

/*
 * Generates a datagram by polling the various ELs to determine if they want to
 * generate any frames, and generating a datagram which coalesces packets for
 * any ELs which do.
 *
 * Returns 0 on failure (e.g. allocation error or other errors), 1 otherwise.
 *
 * *status is filled with status information about the generated packet.
 * It is always filled even in case of failure. In particular, packets can be
 * sent even if failure is later returned.
 * See QUIC_TXP_STATUS for details.
 */
typedef struct quic_txp_status_st {
    int sent_ack_eliciting; /* Was an ACK-eliciting packet sent? */
    int sent_handshake; /* Was a Handshake packet sent? */
    size_t sent_pkt; /* Number of packets sent (0 if nothing was sent) */
} QUIC_TXP_STATUS;

int ossl_quic_tx_packetiser_generate(OSSL_QUIC_TX_PACKETISER *txp,
                                     QUIC_TXP_STATUS *status);

/*
 * Returns a deadline after which a call to ossl_quic_tx_packetiser_generate()
 * might succeed even if it did not previously. This may return
 * ossl_time_infinite() if there is no such deadline currently applicable. It
 * returns ossl_time_zero() if there is (potentially) more data to be generated
 * immediately. The value returned is liable to change after any call to
 * ossl_quic_tx_packetiser_generate() (or after ACKM or CC state changes). Note
 * that ossl_quic_tx_packetiser_generate() can also start to succeed for other
 * non-chronological reasons, such as changes to send stream buffers, etc.
 */
OSSL_TIME ossl_quic_tx_packetiser_get_deadline(OSSL_QUIC_TX_PACKETISER *txp);

/*
 * Set the token used in Initial packets. The callback is called when the buffer
 * is no longer needed; for example, when the TXP is freed or when this function
 * is called again with a new buffer. Fails returning 0 if the token is too big
 * to ever be reasonably encapsulated in an outgoing packet based on our current
 * understanding of our PMTU.
 */
int ossl_quic_tx_packetiser_set_initial_token(OSSL_QUIC_TX_PACKETISER *txp,
                                              const unsigned char *token,
                                              size_t token_len,
                                              ossl_quic_initial_token_free_fn *free_cb,
                                              void *free_cb_arg);

/* Change the DCID the TXP uses to send outgoing packets. */
int ossl_quic_tx_packetiser_set_cur_dcid(OSSL_QUIC_TX_PACKETISER *txp,
                                         const QUIC_CONN_ID *dcid);

/* Change the SCID the TXP uses to send outgoing (long) packets. */
int ossl_quic_tx_packetiser_set_cur_scid(OSSL_QUIC_TX_PACKETISER *txp,
                                         const QUIC_CONN_ID *scid);

/*
 * Change the destination L4 address the TXP uses to send datagrams. Specify
 * NULL (or AF_UNSPEC) to disable use of addressed mode.
 */
int ossl_quic_tx_packetiser_set_peer(OSSL_QUIC_TX_PACKETISER *txp,
                                     const BIO_ADDR *peer);

/*
 * Change the QLOG instance retrieval function in use after instantiation.
 */
void ossl_quic_tx_packetiser_set_qlog_cb(OSSL_QUIC_TX_PACKETISER *txp,
                                         QLOG *(*get_qlog_cb)(void *arg),
                                         void *get_qlog_cb_arg);

/*
 * Inform the TX packetiser that an EL has been discarded. Idempotent.
 *
 * This does not inform the QTX as well; the caller must also inform the QTX.
 *
 * The TXP will no longer reference the crypto[enc_level] QUIC_SSTREAM which was
 * provided in the TXP arguments. However, it is the callers responsibility to
 * free that QUIC_SSTREAM if desired.
 */
int ossl_quic_tx_packetiser_discard_enc_level(OSSL_QUIC_TX_PACKETISER *txp,
                                              uint32_t enc_level);

/*
 * Informs the TX packetiser that the handshake is complete. The TX packetiser
 * will not send 1-RTT application data until the handshake is complete,
 * as the authenticity of the peer is not confirmed until the handshake
 * complete event occurs.
 */
void ossl_quic_tx_packetiser_notify_handshake_complete(OSSL_QUIC_TX_PACKETISER *txp);

/* Asks the TXP to generate a HANDSHAKE_DONE frame in the next 1-RTT packet. */
void ossl_quic_tx_packetiser_schedule_handshake_done(OSSL_QUIC_TX_PACKETISER *txp);

/* Asks the TXP to ensure the next packet in the given PN space is ACK-eliciting. */
void ossl_quic_tx_packetiser_schedule_ack_eliciting(OSSL_QUIC_TX_PACKETISER *txp,
                                                    uint32_t pn_space);

/*
 * Asks the TXP to ensure an ACK is put in the next packet in the given PN
 * space.
 */
void ossl_quic_tx_packetiser_schedule_ack(OSSL_QUIC_TX_PACKETISER *txp,
                                          uint32_t pn_space);

/*
 * Schedules a connection close. *f and f->reason are copied. This operation is
 * irreversible and causes all further packets generated by the TXP to contain a
 * CONNECTION_CLOSE frame. This function fails if it has already been called
 * successfully; the information in *f cannot be changed after the first
 * successful call to this function.
 */
int ossl_quic_tx_packetiser_schedule_conn_close(OSSL_QUIC_TX_PACKETISER *txp,
                                                const OSSL_QUIC_FRAME_CONN_CLOSE *f);

/* Setters for the msg_callback and msg_callback_arg */
void ossl_quic_tx_packetiser_set_msg_callback(OSSL_QUIC_TX_PACKETISER *txp,
                                              ossl_msg_cb msg_callback,
                                              SSL *msg_callback_ssl);
void ossl_quic_tx_packetiser_set_msg_callback_arg(OSSL_QUIC_TX_PACKETISER *txp,
                                                  void *msg_callback_arg);

/*
 * Determines the next PN which will be used for a given PN space.
 */
QUIC_PN ossl_quic_tx_packetiser_get_next_pn(OSSL_QUIC_TX_PACKETISER *txp,
                                            uint32_t pn_space);

/*
 * Sets a callback which is called whenever TXP sends an ACK frame. The callee
 * must not modify the ACK frame data. Can be used to snoop on PNs being ACKed.
 */
void ossl_quic_tx_packetiser_set_ack_tx_cb(OSSL_QUIC_TX_PACKETISER *txp,
                                           void (*cb)(const OSSL_QUIC_FRAME_ACK *ack,
                                                      uint32_t pn_space,
                                                      void *arg),
                                           void *cb_arg);

# endif

#endif