diff --git a/dcsctp-cxx/examples/main.cpp b/dcsctp-cxx/examples/main.cpp index e9c8023..c4b8f24 100644 --- a/dcsctp-cxx/examples/main.cpp +++ b/dcsctp-cxx/examples/main.cpp @@ -13,28 +13,104 @@ // limitations under the License. #include "dcsctp.h" + +#include #include +#include +#include + +// Polls for the next event and expects it to be a SendPacket. +// Returns the packet payload. Throws a runtime_error if the event is not a +// SendPacket. +rust::Vec expect_send_packet(dcsctp_cxx::DcSctpSocket& socket, + const std::string& socket_name) { + dcsctp_cxx::Event event = dcsctp_cxx::poll_event(socket); + if (event.event_type != dcsctp_cxx::EventType::SendPacket) { + throw std::runtime_error("Expected SendPacket from " + socket_name + + ", but got something else."); + } + std::cout << "Polled SendPacket from " << socket_name + << " (size: " << event.packet.size() << ")" << std::endl; + return event.packet; +} + +// Polls for the next event and expects it to be OnConnected. +// Throws a runtime_error if the event is not OnConnected. +void expect_on_connected(dcsctp_cxx::DcSctpSocket& socket, + const std::string& socket_name) { + dcsctp_cxx::Event event = dcsctp_cxx::poll_event(socket); + if (event.event_type != dcsctp_cxx::EventType::OnConnected) { + throw std::runtime_error("Expected OnConnected from " + socket_name + + ", but got something else."); + } + std::cout << "Polled OnConnected from " << socket_name << std::endl; +} + +// Polls for the next event and expects it to be Nothing. +void expect_no_event(dcsctp_cxx::DcSctpSocket& socket, + const std::string& socket_name) { + dcsctp_cxx::Event event = dcsctp_cxx::poll_event(socket); + if (event.event_type != dcsctp_cxx::EventType::Nothing) { + throw std::runtime_error("Expected Nothing from " + socket_name + + ", but got something else."); + } +} int main() { std::cout << "dcsctp version: " << dcsctp_cxx::version().c_str() << std::endl; - dcsctp_cxx::DcSctpSocket *socket = dcsctp_cxx::new_socket(); + dcsctp_cxx::DcSctpSocket* socket_a = dcsctp_cxx::new_socket(); + dcsctp_cxx::DcSctpSocket* socket_z = dcsctp_cxx::new_socket(); + std::cout << "Created two sockets: A and Z" << std::endl; - if (socket) { - std::cout << "Successfully created a socket." << std::endl; - } else { - std::cout << "Failed to create a socket." << std::endl; - return 1; - } + try { + dcsctp_cxx::connect(*socket_a); + + // A -> INIT -> Z + rust::Vec init_packet = expect_send_packet(*socket_a, "A"); + dcsctp_cxx::handle_input(*socket_z, + {init_packet.data(), init_packet.size()}); + + // A <- INIT_ACK <- Z + rust::Vec init_ack_packet = expect_send_packet(*socket_z, "Z"); + dcsctp_cxx::handle_input(*socket_a, {init_ack_packet.data(), + init_ack_packet.size()}); + + // A -> COOKIE_ECHO -> Z + rust::Vec cookie_echo_packet = expect_send_packet(*socket_a, "A"); + dcsctp_cxx::handle_input( + *socket_z, {cookie_echo_packet.data(), cookie_echo_packet.size()}); + + // Z becomes connected + expect_on_connected(*socket_z, "Z"); + + // A <- COOKIE_ACK <- Z + rust::Vec cookie_ack_packet = expect_send_packet(*socket_z, "Z"); + dcsctp_cxx::handle_input( + *socket_a, {cookie_ack_packet.data(), cookie_ack_packet.size()}); + + // A becomes connected + expect_on_connected(*socket_a, "A"); + + expect_no_event(*socket_a, "A"); + expect_no_event(*socket_z, "Z"); + + if (dcsctp_cxx::state(*socket_a) == dcsctp_cxx::SocketState::Connected && + dcsctp_cxx::state(*socket_z) == dcsctp_cxx::SocketState::Connected) { + std::cout << "Both sockets connected successfully!" << std::endl; + } else { + std::cout << "Connection failed: sockets are not in Connected state." + << std::endl; + return 1; + } - if (dcsctp_cxx::state(*socket) == dcsctp_cxx::SocketState::Closed) { - std::cout << "Socket is initially closed" << std::endl; - } else { - std::cout << "Socket is in an unexpected state" << std::endl; + } catch (const std::runtime_error& e) { + std::cerr << "Caught an exception: " << e.what() << std::endl; return 1; } - std::cout << "Socket is about to be deleted." << std::endl; - dcsctp_cxx::delete_socket(socket); + std::cout << "Sockets are about to be deleted." << std::endl; + dcsctp_cxx::delete_socket(socket_a); + dcsctp_cxx::delete_socket(socket_z); return 0; } diff --git a/dcsctp-cxx/src/lib.rs b/dcsctp-cxx/src/lib.rs index 2c7ca38..e787e94 100644 --- a/dcsctp-cxx/src/lib.rs +++ b/dcsctp-cxx/src/lib.rs @@ -14,6 +14,7 @@ use dcsctp::api::DcSctpSocket as DcSctpSocketTrait; use dcsctp::api::Options; +use dcsctp::api::SocketEvent as DcSctpSocketEvent; use dcsctp::api::SocketState as DcSctpSocketState; use std::time::Instant; @@ -27,6 +28,18 @@ mod ffi { ShuttingDown, } + #[derive(Debug)] + enum EventType { + Nothing, + OnConnected, + SendPacket, + } + + struct Event { + event_type: EventType, + packet: Vec, + } + extern "Rust" { type DcSctpSocket; @@ -34,6 +47,9 @@ mod ffi { fn new_socket() -> *mut DcSctpSocket; unsafe fn delete_socket(socket: *mut DcSctpSocket); fn state(socket: &DcSctpSocket) -> SocketState; + fn connect(socket: &mut DcSctpSocket); + fn handle_input(socket: &mut DcSctpSocket, data: &[u8]); + fn poll_event(socket: &mut DcSctpSocket) -> Event; } } @@ -66,3 +82,23 @@ fn state(socket: &DcSctpSocket) -> ffi::SocketState { DcSctpSocketState::ShuttingDown => ffi::SocketState::ShuttingDown, } } + +fn connect(socket: &mut DcSctpSocket) { + socket.0.connect(); +} + +fn handle_input(socket: &mut DcSctpSocket, data: &[u8]) { + socket.0.handle_input(data) +} + +fn poll_event(socket: &mut DcSctpSocket) -> ffi::Event { + match socket.0.poll_event() { + Some(DcSctpSocketEvent::SendPacket(p)) => { + ffi::Event { event_type: ffi::EventType::SendPacket, packet: p } + } + Some(DcSctpSocketEvent::OnConnected()) => { + ffi::Event { event_type: ffi::EventType::OnConnected, packet: Vec::new() } + } + _ => ffi::Event { event_type: ffi::EventType::Nothing, packet: Vec::new() }, + } +}