Skip to content

Commit

Permalink
Merge pull request #602 from h2o/kazuho/quicly-error-t
Browse files Browse the repository at this point in the history
support 62-bit error codes
  • Loading branch information
kazuho authored Jan 12, 2025
2 parents f336bd8 + 898c5d6 commit fc5beb1
Show file tree
Hide file tree
Showing 26 changed files with 588 additions and 461 deletions.
84 changes: 43 additions & 41 deletions include/quicly.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,25 +117,25 @@ typedef struct st_quicly_stream_scheduler_t {
* Called by quicly to emit stream data. The scheduler should repeatedly choose a stream and call `quicly_send_stream` until
* `quicly_can_send_stream` returns false.
*/
int (*do_send)(struct st_quicly_stream_scheduler_t *sched, quicly_conn_t *conn, quicly_send_context_t *s);
quicly_error_t (*do_send)(struct st_quicly_stream_scheduler_t *sched, quicly_conn_t *conn, quicly_send_context_t *s);
/**
*
*/
int (*update_state)(struct st_quicly_stream_scheduler_t *sched, quicly_stream_t *stream);
void (*update_state)(struct st_quicly_stream_scheduler_t *sched, quicly_stream_t *stream);
} quicly_stream_scheduler_t;

/**
* called when stream is being open. Application is expected to create it's corresponding state and tie it to stream->data.
*/
QUICLY_CALLBACK_TYPE(int, stream_open, quicly_stream_t *stream);
QUICLY_CALLBACK_TYPE(quicly_error_t, stream_open, quicly_stream_t *stream);
/**
*
*/
QUICLY_CALLBACK_TYPE(void, receive_datagram_frame, quicly_conn_t *conn, ptls_iovec_t payload);
/**
* called when the connection is closed by remote peer
*/
QUICLY_CALLBACK_TYPE(void, closed_by_remote, quicly_conn_t *conn, int err, uint64_t frame_type, const char *reason,
QUICLY_CALLBACK_TYPE(void, closed_by_remote, quicly_conn_t *conn, quicly_error_t err, uint64_t frame_type, const char *reason,
size_t reason_len);
/**
* Returns current time in milliseconds. The returned value MUST monotonically increase (i.e., it is the responsibility of the
Expand All @@ -145,11 +145,11 @@ QUICLY_CALLBACK_TYPE0(int64_t, now);
/**
* called when a NEW_TOKEN token is received on a connection
*/
QUICLY_CALLBACK_TYPE(int, save_resumption_token, quicly_conn_t *conn, ptls_iovec_t token);
QUICLY_CALLBACK_TYPE(quicly_error_t, save_resumption_token, quicly_conn_t *conn, ptls_iovec_t token);
/**
*
*/
QUICLY_CALLBACK_TYPE(int, generate_resumption_token, quicly_conn_t *conn, ptls_buffer_t *buf,
QUICLY_CALLBACK_TYPE(quicly_error_t, generate_resumption_token, quicly_conn_t *conn, ptls_buffer_t *buf,
quicly_address_token_plaintext_t *token);
/**
* called to initialize a congestion controller for a new connection.
Expand Down Expand Up @@ -764,7 +764,7 @@ typedef struct st_quicly_stream_callbacks_t {
/**
* called when the stream is destroyed
*/
void (*on_destroy)(quicly_stream_t *stream, int err);
void (*on_destroy)(quicly_stream_t *stream, quicly_error_t err);
/**
* called whenever data can be retired from the send buffer, specifying the amount that can be newly removed
*/
Expand All @@ -781,7 +781,7 @@ typedef struct st_quicly_stream_callbacks_t {
* called when a STOP_SENDING frame is received. Do not call `quicly_reset_stream` in response. The stream will be
* automatically reset by quicly.
*/
void (*on_send_stop)(quicly_stream_t *stream, int err);
void (*on_send_stop)(quicly_stream_t *stream, quicly_error_t err);
/**
* called when data is newly received. `off` is the offset within the buffer (the beginning position changes as the application
* calls `quicly_stream_sync_recvbuf`. Applications should consult `quicly_stream_t::recvstate` to see if it has contiguous
Expand All @@ -791,7 +791,7 @@ typedef struct st_quicly_stream_callbacks_t {
/**
* called when a RESET_STREAM frame is received
*/
void (*on_receive_reset)(quicly_stream_t *stream, int err);
void (*on_receive_reset)(quicly_stream_t *stream, quicly_error_t err);
} quicly_stream_callbacks_t;

struct st_quicly_stream_t {
Expand Down Expand Up @@ -1063,11 +1063,11 @@ struct sockaddr *quicly_get_peername(quicly_conn_t *conn);
/**
*
*/
int quicly_get_stats(quicly_conn_t *conn, quicly_stats_t *stats);
quicly_error_t quicly_get_stats(quicly_conn_t *conn, quicly_stats_t *stats);
/**
*
*/
int quicly_get_delivery_rate(quicly_conn_t *conn, quicly_rate_t *delivery_rate);
quicly_error_t quicly_get_delivery_rate(quicly_conn_t *conn, quicly_rate_t *delivery_rate);
/**
*
*/
Expand All @@ -1093,7 +1093,7 @@ void quicly_free(quicly_conn_t *conn);
* error; indicating idle close). An application should continue calling quicly_receive and quicly_send, until they return
* QUICLY_ERROR_FREE_CONNECTION. At this point, it is should call quicly_free.
*/
int quicly_close(quicly_conn_t *conn, int err, const char *reason_phrase);
quicly_error_t quicly_close(quicly_conn_t *conn, quicly_error_t err, const char *reason_phrase);
/**
*
*/
Expand Down Expand Up @@ -1122,7 +1122,7 @@ int quicly_can_send_data(quicly_conn_t *conn, quicly_send_context_t *s);
* Sends data of given stream. Called by stream scheduler. Only streams that can send some data or EOS should be specified. It is
* the responsibility of the stream scheduler to maintain a list of such streams.
*/
int quicly_send_stream(quicly_stream_t *stream, quicly_send_context_t *s);
quicly_error_t quicly_send_stream(quicly_stream_t *stream, quicly_send_context_t *s);
/**
* Builds a Version Negotiation packet. The generated packet might include a greasing version.
* * @param versions zero-terminated list of versions to advertise; use `quicly_supported_versions` for sending the list of
Expand All @@ -1133,8 +1133,8 @@ size_t quicly_send_version_negotiation(quicly_context_t *ctx, ptls_iovec_t dest_
/**
*
*/
int quicly_retry_calc_cidpair_hash(ptls_hash_algorithm_t *sha256, ptls_iovec_t client_cid, ptls_iovec_t server_cid,
uint64_t *value);
quicly_error_t quicly_retry_calc_cidpair_hash(ptls_hash_algorithm_t *sha256, ptls_iovec_t client_cid, ptls_iovec_t server_cid,
uint64_t *value);
/**
* Builds a UDP datagram containing a Retry packet.
* @param retry_aead_cache pointer to `ptls_aead_context_t *` that the function can store a AEAD context for future reuse. The
Expand All @@ -1161,8 +1161,8 @@ size_t quicly_send_retry(quicly_context_t *ctx, ptls_aead_context_t *token_encry
* @return 0 if successful, otherwise an error. When an error is returned, the caller must call `quicly_close` to discard the
* connection context.
*/
int quicly_send(quicly_conn_t *conn, quicly_address_t *dest, quicly_address_t *src, struct iovec *datagrams, size_t *num_datagrams,
void *buf, size_t bufsize);
quicly_error_t quicly_send(quicly_conn_t *conn, quicly_address_t *dest, quicly_address_t *src, struct iovec *datagrams,
size_t *num_datagrams, void *buf, size_t bufsize);
/**
* returns ECN bits to be set for the packets built by the last invocation of `quicly_send`
*/
Expand All @@ -1179,11 +1179,12 @@ size_t quicly_send_stateless_reset(quicly_context_t *ctx, const void *src_cid, v
/**
*
*/
int quicly_send_resumption_token(quicly_conn_t *conn);
quicly_error_t quicly_send_resumption_token(quicly_conn_t *conn);
/**
*
*/
int quicly_receive(quicly_conn_t *conn, struct sockaddr *dest_addr, struct sockaddr *src_addr, quicly_decoded_packet_t *packet);
quicly_error_t quicly_receive(quicly_conn_t *conn, struct sockaddr *dest_addr, struct sockaddr *src_addr,
quicly_decoded_packet_t *packet);
/**
* consults if the incoming packet identified by (dest_addr, src_addr, decoded) belongs to the given connection
*/
Expand Down Expand Up @@ -1214,18 +1215,18 @@ int quicly_encode_transport_parameter_list(ptls_buffer_t *buf, const quicly_tran
* pre-fills the vector with an unpredictable value (i.e. random), then calls this function to set the stateless reset token to the
* value supplied by peer.
*/
int quicly_decode_transport_parameter_list(quicly_transport_parameters_t *params, quicly_cid_t *original_dcid,
quicly_cid_t *initial_scid, quicly_cid_t *retry_scid, void *stateless_reset_token,
const uint8_t *src, const uint8_t *end);
quicly_error_t quicly_decode_transport_parameter_list(quicly_transport_parameters_t *params, quicly_cid_t *original_dcid,
quicly_cid_t *initial_scid, quicly_cid_t *retry_scid,
void *stateless_reset_token, const uint8_t *src, const uint8_t *end);
/**
* Initiates a new connection.
* @param new_cid the CID to be used for the connection. path_id is ignored.
* @param appdata initial value to be set to `*quicly_get_data(conn)`
*/
int quicly_connect(quicly_conn_t **conn, quicly_context_t *ctx, const char *server_name, struct sockaddr *dest_addr,
struct sockaddr *src_addr, const quicly_cid_plaintext_t *new_cid, ptls_iovec_t address_token,
ptls_handshake_properties_t *handshake_properties, const quicly_transport_parameters_t *resumed_transport_params,
void *appdata);
quicly_error_t quicly_connect(quicly_conn_t **conn, quicly_context_t *ctx, const char *server_name, struct sockaddr *dest_addr,
struct sockaddr *src_addr, const quicly_cid_plaintext_t *new_cid, ptls_iovec_t address_token,
ptls_handshake_properties_t *handshake_properties,
const quicly_transport_parameters_t *resumed_transport_params, void *appdata);
/**
* accepts a new connection
* @param new_cid The CID to be used for the connection. When an error is being returned, the application can reuse the CID
Expand All @@ -1236,9 +1237,10 @@ int quicly_connect(quicly_conn_t **conn, quicly_context_t *ctx, const char *serv
* validated.
* @param appdata initial value to be set to `*quicly_get_data(conn)`
*/
int quicly_accept(quicly_conn_t **conn, quicly_context_t *ctx, struct sockaddr *dest_addr, struct sockaddr *src_addr,
quicly_decoded_packet_t *packet, quicly_address_token_plaintext_t *address_token,
const quicly_cid_plaintext_t *new_cid, ptls_handshake_properties_t *handshake_properties, void *appdata);
quicly_error_t quicly_accept(quicly_conn_t **conn, quicly_context_t *ctx, struct sockaddr *dest_addr, struct sockaddr *src_addr,
quicly_decoded_packet_t *packet, quicly_address_token_plaintext_t *address_token,
const quicly_cid_plaintext_t *new_cid, ptls_handshake_properties_t *handshake_properties,
void *appdata);
/**
*
*/
Expand All @@ -1256,15 +1258,15 @@ quicly_stream_id_t quicly_get_ingress_max_streams(quicly_conn_t *conn, int uni);
* Iterates through each stream. When the callback returns a non-zero value, bails out from the iteration, returning the returned
* value.
*/
int quicly_foreach_stream(quicly_conn_t *conn, void *thunk, int (*cb)(void *thunk, quicly_stream_t *stream));
int64_t quicly_foreach_stream(quicly_conn_t *conn, void *thunk, int64_t (*cb)(void *thunk, quicly_stream_t *stream));
/**
*
*/
quicly_stream_t *quicly_get_stream(quicly_conn_t *conn, quicly_stream_id_t stream_id);
/**
*
*/
int quicly_open_stream(quicly_conn_t *conn, quicly_stream_t **stream, int unidirectional);
quicly_error_t quicly_open_stream(quicly_conn_t *conn, quicly_stream_t **stream, int unidirectional);
/**
* This function returns a stream that is already open, or if the given ID refers to a stream that can be opened by the peer but is
* yet-to-be opened, the functions opens that stream and returns it. Otherwise, `*stream` is set to NULL.
Expand All @@ -1273,15 +1275,15 @@ int quicly_open_stream(quicly_conn_t *conn, quicly_stream_t **stream, int unidir
* initiated stream for which the peer has not yet sent anything.
* Invocation of this function might open not only the stream that is referred to by the `stream_id` but also other streams.
*/
int quicly_get_or_open_stream(quicly_conn_t *conn, uint64_t stream_id, quicly_stream_t **stream);
quicly_error_t quicly_get_or_open_stream(quicly_conn_t *conn, uint64_t stream_id, quicly_stream_t **stream);
/**
*
*/
void quicly_reset_stream(quicly_stream_t *stream, int err);
void quicly_reset_stream(quicly_stream_t *stream, quicly_error_t err);
/**
*
*/
void quicly_request_stop(quicly_stream_t *stream, int err);
void quicly_request_stop(quicly_stream_t *stream, quicly_error_t err);
/**
*
*/
Expand Down Expand Up @@ -1348,15 +1350,15 @@ void quicly_amend_ptls_context(ptls_context_t *ptls);
* the identifier of the AEAD key being used.
* @param plaintext the token to be encrypted
*/
int quicly_encrypt_address_token(void (*random_bytes)(void *, size_t), ptls_aead_context_t *aead, ptls_buffer_t *buf,
size_t start_off, const quicly_address_token_plaintext_t *plaintext);
quicly_error_t quicly_encrypt_address_token(void (*random_bytes)(void *, size_t), ptls_aead_context_t *aead, ptls_buffer_t *buf,
size_t start_off, const quicly_address_token_plaintext_t *plaintext);
/**
* Decrypts an address token.
* If decryption succeeds, returns zero. If the token is unusable due to decryption failure, returns PTLS_DECODE_ERROR. If the token
* is unusable and the connection should be reset, returns QUICLY_ERROR_INVALID_TOKEN.
*/
int quicly_decrypt_address_token(ptls_aead_context_t *aead, quicly_address_token_plaintext_t *plaintext, const void *src,
size_t len, size_t prefix_len, const char **err_desc);
quicly_error_t quicly_decrypt_address_token(ptls_aead_context_t *aead, quicly_address_token_plaintext_t *plaintext, const void *src,
size_t len, size_t prefix_len, const char **err_desc);
/**
* Builds authentication data for TLS session ticket. 0-RTT can be accepted only when the auth_data of the original connection and
* the new connection are identical.
Expand All @@ -1381,7 +1383,7 @@ char *quicly_hexdump(const uint8_t *bytes, size_t len, size_t indent);
/**
*
*/
void quicly_stream_noop_on_destroy(quicly_stream_t *stream, int err);
void quicly_stream_noop_on_destroy(quicly_stream_t *stream, quicly_error_t err);
/**
*
*/
Expand All @@ -1393,15 +1395,15 @@ void quicly_stream_noop_on_send_emit(quicly_stream_t *stream, size_t off, void *
/**
*
*/
void quicly_stream_noop_on_send_stop(quicly_stream_t *stream, int err);
void quicly_stream_noop_on_send_stop(quicly_stream_t *stream, quicly_error_t err);
/**
*
*/
void quicly_stream_noop_on_receive(quicly_stream_t *stream, size_t off, const void *src, size_t len);
/**
*
*/
void quicly_stream_noop_on_receive_reset(quicly_stream_t *stream, int err);
void quicly_stream_noop_on_receive_reset(quicly_stream_t *stream, quicly_error_t err);

extern const quicly_stream_callbacks_t quicly_stream_noop_callbacks;

Expand Down
26 changes: 18 additions & 8 deletions include/quicly/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,23 @@ extern "C" {
#define QUICLY_EPOCH_1RTT 3
#define QUICLY_NUM_EPOCHS 4

/* coexists with picotls error codes, assuming that int is at least 32-bits */
#define QUICLY_ERROR_IS_QUIC(e) (((e) & ~0x1ffff) == 0x20000)
#define QUICLY_ERROR_IS_QUIC_TRANSPORT(e) (((e) & ~0xffff) == 0x20000)
#define QUICLY_ERROR_IS_QUIC_APPLICATION(e) (((e) & ~0xffff) == 0x30000)
#define QUICLY_ERROR_GET_ERROR_CODE(e) ((uint16_t)(e))
#define QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(e) ((uint16_t)(e) + 0x20000)
#define QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(e) ((uint16_t)(e) + 0x30000)
/**
* Error code used by quicly. The code coalesces the following to an int64_t.
* * 0..0x2ff: picotls error codes (of type int)
* * 0x30000..0x400000000002ffff: QUIC application error codes
* * 0x4000000000030000..0x800000000002ffff...: QUIC protocol error codes
* Internal error codes should be allocated from the unused space below 0x30000 (i.e., unused space of picotls error codes);
* quicly itself uses 0xffxx. `quicly_error_t` is defined as a signed type so that the picotls error code space can be mapped
* without sign conversion.
*/
typedef int64_t quicly_error_t;

#define QUICLY_ERROR_IS_QUIC(e) ((uint64_t)(quicly_error_t)(e) - 0x30000u < 0x8000000000000000u)
#define QUICLY_ERROR_IS_QUIC_TRANSPORT(e) ((uint64_t)(quicly_error_t)(e) - 0x4000000000030000u < 0x4000000000000000u)
#define QUICLY_ERROR_IS_QUIC_APPLICATION(e) ((uint64_t)(quicly_error_t)(e) - 0x30000u < 0x4000000000000000u)
#define QUICLY_ERROR_GET_ERROR_CODE(e) (((uint64_t)(quicly_error_t)(e) - 0x30000u) & 0x3fffffffffffffffu)
#define QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(e) ((quicly_error_t)((uint64_t)(e) + 0x4000000000030000u))
#define QUICLY_ERROR_FROM_APPLICATION_ERROR_CODE(e) ((quicly_error_t)(uint64_t)(e) + 0x30000)
/**
* PTLS_ERROR_NO_MEMORY and QUICLY_ERROR_STATE_EXHAUSTION are special error codes that are internal but can be passed to
* quicly_close. These are converted to QUICLY_TRANSPORT_ERROR_INTERNAL when sent over the wire.
Expand All @@ -96,7 +106,7 @@ extern "C" {
#define QUICLY_TRANSPORT_ERROR_CRYPTO_BUFFER_EXCEEDED QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0xd)
#define QUICLY_TRANSPORT_ERROR_KEY_UPDATE QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0xe)
#define QUICLY_TRANSPORT_ERROR_AEAD_LIMIT_REACHED QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0xf)
#define QUICLY_TRANSPORT_ERROR_TLS_ALERT_BASE QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0x100)
#define QUICLY_TRANSPORT_ERROR_CRYPTO(tls_alert) QUICLY_ERROR_FROM_TRANSPORT_ERROR_CODE(0x100 + (tls_alert))

/* internal error codes, used purely for signaling status to the application */
#define QUICLY_ERROR_PACKET_IGNORED 0xff01
Expand Down
Loading

0 comments on commit fc5beb1

Please sign in to comment.