Skip to content

Commit

Permalink
Expose C api to handle PathEvent
Browse files Browse the repository at this point in the history
Motivation:

There was no C api exposed to allow handling PathEvent.

Modifications:

Expose c functions to handle PathEvent

Result:

Be able to handle and consume PathEvent
  • Loading branch information
normanmaurer committed Nov 24, 2023
1 parent 89aba91 commit 3980108
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 8 deletions.
64 changes: 56 additions & 8 deletions quiche/include/quiche.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,15 +268,15 @@ typedef struct quiche_conn quiche_conn;
// Creates a new server-side connection.
quiche_conn *quiche_accept(const uint8_t *scid, size_t scid_len,
const uint8_t *odcid, size_t odcid_len,
const struct sockaddr *local, size_t local_len,
const struct sockaddr *peer, size_t peer_len,
const struct sockaddr *local, socklen_t local_len,
const struct sockaddr *peer, socklen_t peer_len,
quiche_config *config);

// Creates a new client-side connection.
quiche_conn *quiche_connect(const char *server_name,
const uint8_t *scid, size_t scid_len,
const struct sockaddr *local, size_t local_len,
const struct sockaddr *peer, size_t peer_len,
const struct sockaddr *local, socklen_t local_len,
const struct sockaddr *peer, socklen_t peer_len,
quiche_config *config);

// Writes a version negotiation packet.
Expand All @@ -296,8 +296,8 @@ bool quiche_version_is_supported(uint32_t version);

quiche_conn *quiche_conn_new_with_tls(const uint8_t *scid, size_t scid_len,
const uint8_t *odcid, size_t odcid_len,
const struct sockaddr *local, size_t local_len,
const struct sockaddr *peer, size_t peer_len,
const struct sockaddr *local, socklen_t local_len,
const struct sockaddr *peer, socklen_t peer_len,
const quiche_config *config, void *ssl,
bool is_server);

Expand Down Expand Up @@ -675,8 +675,56 @@ ssize_t quiche_conn_send_ack_eliciting(quiche_conn *conn);

// Schedule an ack-eliciting packet on the specified path.
ssize_t quiche_conn_send_ack_eliciting_on_path(quiche_conn *conn,
const struct sockaddr *local, size_t local_len,
const struct sockaddr *peer, size_t peer_len);
const struct sockaddr *local, socklen_t local_len,
const struct sockaddr *peer, socklen_t peer_len);

enum quiche_path_event_type {
QUICHE_PATH_EVENT_NEW,
QUICHE_PATH_EVENT_VALIDATED,
QUICHE_PATH_EVENT_FAILED_VALIDATION,
QUICHE_PATH_EVENT_CLOSED,
QUICHE_PATH_EVENT_REUSED_SOURCE_CONNECTION_ID,
QUICHE_PATH_EVENT_PEER_MIGRATED,
};

typedef struct quiche_path_event quiche_path_event;

// Retrieves the next event. Returns NULL if there is no event to process.
const quiche_path_event *quiche_conn_path_event_next(quiche_conn *conn);

// Returns the type of the event.
enum quiche_path_event_type quiche_path_event_type(quiche_path_event *ev);

// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_NEW.
void quiche_path_event_new(quiche_path_event *ev,
struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len);

// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_VALIDATED.
void quiche_path_event_validated(quiche_path_event *ev,
struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len);

// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_FAILED_VALIDATION.
void quiche_path_event_failed_validated(quiche_path_event *ev,
struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len);

// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_CLOSED.
void quiche_path_event_closed(quiche_path_event *ev,
struct sockaddr_storage *local, socklen_t *local_len, struct sockaddr_storage *peer, socklen_t *peer_len);

// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_REUSED_SOURCE_CONNECTION_ID.
void quiche_path_event_reused_source_connection_id(quiche_path_event *ev, uint64_t *id,
struct sockaddr_storage *old_local, socklen_t *old_local_len,
struct sockaddr_storage *old_peer, socklen_t *old_peer_len,
struct sockaddr_storage *local, socklen_t *local_len,
struct sockaddr_storage *peer, socklen_t *peer_len);

// Should be called if the quiche_path_event_type(...) returns QUICHE_PATH_EVENT_PEER_MIGRATED.
void quiche_path_event_peer_migrated(quiche_path_event *ev,
struct sockaddr_storage *local, socklen_t *local_len,
struct sockaddr_storage *peer, socklen_t *peer_len);

// Frees the path event object.
void quiche_path_event_free(quiche_path_event *ev);

// Frees the connection object.
void quiche_conn_free(quiche_conn *conn);
Expand Down
134 changes: 134 additions & 0 deletions quiche/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,140 @@ pub extern fn quiche_conn_send_quantum(conn: &Connection) -> size_t {
conn.send_quantum() as size_t
}

#[no_mangle]
pub extern fn quiche_conn_path_event_next(
conn: &mut Connection,
) -> *const PathEvent {
match conn.path_event_next() {
Some(v) => Box::into_raw(Box::new(v)),
None => ptr::null(),
}
}

#[no_mangle]
pub extern fn quiche_path_event_type(ev: &PathEvent) -> u32 {
match ev {
PathEvent::New { .. } => 0,

PathEvent::Validated { .. } => 1,

PathEvent::FailedValidation { .. } => 2,

PathEvent::Closed { .. } => 3,

PathEvent::ReusedSourceConnectionId { .. } => 4,

PathEvent::PeerMigrated { .. } => 5,
}
}

#[no_mangle]
pub extern fn quiche_path_event_new(
ev: &PathEvent, local_addr: &mut sockaddr_storage,
local_addr_len: &mut socklen_t, peer_addr: &mut sockaddr_storage,
peer_addr_len: &mut socklen_t,
) {
match ev {
PathEvent::New(local, peer) => {
*local_addr_len = std_addr_to_c(local, local_addr);
*peer_addr_len = std_addr_to_c(peer, peer_addr)
},

_ => unreachable!(),
}
}

#[no_mangle]
pub extern fn quiche_path_event_validated(
ev: &PathEvent, local_addr: &mut sockaddr_storage,
local_addr_len: &mut socklen_t, peer_addr: &mut sockaddr_storage,
peer_addr_len: &mut socklen_t,
) {
match ev {
PathEvent::Validated(local, peer) => {
*local_addr_len = std_addr_to_c(local, local_addr);
*peer_addr_len = std_addr_to_c(peer, peer_addr)
},

_ => unreachable!(),
}
}

#[no_mangle]
pub extern fn quiche_path_event_failed_validation(
ev: &PathEvent, local_addr: &mut sockaddr_storage,
local_addr_len: &mut socklen_t, peer_addr: &mut sockaddr_storage,
peer_addr_len: &mut socklen_t,
) {
match ev {
PathEvent::FailedValidation(local, peer) => {
*local_addr_len = std_addr_to_c(local, local_addr);
*peer_addr_len = std_addr_to_c(peer, peer_addr)
},

_ => unreachable!(),
}
}

#[no_mangle]
pub extern fn quiche_path_event_closed(
ev: &PathEvent, local_addr: &mut sockaddr_storage,
local_addr_len: &mut socklen_t, peer_addr: &mut sockaddr_storage,
peer_addr_len: &mut socklen_t,
) {
match ev {
PathEvent::Closed(local, peer) => {
*local_addr_len = std_addr_to_c(local, local_addr);
*peer_addr_len = std_addr_to_c(peer, peer_addr)
},

_ => unreachable!(),
}
}

#[no_mangle]
pub extern fn quiche_path_event_reused_source_connection_id(
ev: &PathEvent, cid_sequence_number: &mut u64,
old_local_addr: &mut sockaddr_storage, old_local_addr_len: &mut socklen_t,
old_peer_addr: &mut sockaddr_storage, old_peer_addr_len: &mut socklen_t,
local_addr: &mut sockaddr_storage, local_addr_len: &mut socklen_t,
peer_addr: &mut sockaddr_storage, peer_addr_len: &mut socklen_t,
) {
match ev {
PathEvent::ReusedSourceConnectionId(id, old, new) => {
*cid_sequence_number = *id;
*old_local_addr_len = std_addr_to_c(&old.0, old_local_addr);
*old_peer_addr_len = std_addr_to_c(&old.1, old_peer_addr);

*local_addr_len = std_addr_to_c(&new.0, local_addr);
*peer_addr_len = std_addr_to_c(&new.1, peer_addr)
},

_ => unreachable!(),
}
}

#[no_mangle]
pub extern fn quiche_path_event_peer_migrated(
ev: &PathEvent, local_addr: &mut sockaddr_storage,
local_addr_len: &mut socklen_t, peer_addr: &mut sockaddr_storage,
peer_addr_len: &mut socklen_t,
) {
match ev {
PathEvent::PeerMigrated(local, peer) => {
*local_addr_len = std_addr_to_c(local, local_addr);
*peer_addr_len = std_addr_to_c(peer, peer_addr);
},

_ => unreachable!(),
}
}

#[no_mangle]
pub extern fn quiche_path_event_free(ev: *mut PathEvent) {
drop(unsafe { Box::from_raw(ev) });
}

#[no_mangle]
pub extern fn quiche_put_varint(
buf: *mut u8, buf_len: size_t, val: u64,
Expand Down

0 comments on commit 3980108

Please sign in to comment.