Skip to content

Commit

Permalink
ffi: 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 authored Nov 27, 2023
1 parent 177b0ca commit 5796adc
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 0 deletions.
48 changes: 48 additions & 0 deletions quiche/include/quiche.h
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,54 @@ uint64_t quiche_conn_new_scid(quiche_conn *conn,
const uint8_t *scid, size_t scid_len,
const uint8_t *reset_token, bool retire_if_needed);

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_validation(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);

// Requests the retirement of the destination Connection ID used by the
// host to reach its peer.
int quiche_conn_retire_dcid(quiche_conn *conn, uint64_t dcid_seq);
Expand Down
134 changes: 134 additions & 0 deletions quiche/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,140 @@ pub extern fn quiche_conn_retired_scid_next(
}
}

#[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 5796adc

Please sign in to comment.