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 20, 2023
1 parent 89aba91 commit 8a3d847
Show file tree
Hide file tree
Showing 2 changed files with 192 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 @@ -678,6 +678,54 @@ 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);

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 true if there was an event and ev is et, false otherwise.
bool quiche_conn_path_event_next(quiche_conn *conn, quiche_path_event **ev);

// Returns the type of the event.
enum quiche_path_event_type quiche_conn_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, size_t *local_len, struct sockaddr_storage *peer, size_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, size_t *local_len, struct sockaddr_storage *peer, size_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, size_t *local_len, struct sockaddr_storage *peer, size_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, size_t *local_len, struct sockaddr_storage *peer, size_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, size_t *old_local_len,
struct sockaddr_storage *old_peer, size_t *old_peer_len,
struct sockaddr_storage *local, size_t *local_len,
struct sockaddr_storage *peer, size_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 *old_addr, size_t *old_len,
struct sockaddr_storage *new_addr, size_t *new_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
144 changes: 144 additions & 0 deletions quiche/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,150 @@ 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, ev: *mut *const PathEvent,
) -> bool {
match conn.path_event_next() {
Some(v) => {
unsafe {
*ev = Box::into_raw(Box::new(v));
}

true
},

None => false,
}
}

#[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, connection_id: &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) => {
*connection_id = *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, old_addr: &mut sockaddr_storage,
old_addr_len: &mut socklen_t,
new_addr: &mut sockaddr_storage,
new_addr_len: &mut socklen_t,
) {
match ev {
PathEvent::PeerMigrated(old, new) => {
*old_addr_len = std_addr_to_c(&old, old_addr);
*new_addr_len = std_addr_to_c(&new, new_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 8a3d847

Please sign in to comment.