#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
#![warn(unused_must_use)]
use core::ffi::c_void;
use bun_core::ZStr;
pub use bun_uws_sys::{
AnyWebSocket, BodyReaderMixin, ConnectingSocket, ListenSocket, NewApp, RawWebSocket, Request,
Timer, WebSocketBehavior, us_socket_stream_buffer_t, us_socket_t, uws_res,
};
pub use bun_jsc_macros::uws_callback;
pub use bun_uws_sys::response::State;
pub use bun_uws_sys::{h3 as H3, quic, udp, vtable};
pub type Socket = us_socket_t;
pub mod dispatch {}
pub mod WindowsNamedPipe {}
pub mod UpgradedDuplex {}
pub type SslCtx = bun_boringssl::c::SSL_CTX;
pub use bun_uws_sys::WebSocketUpgradeContext;
#[repr(i32)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum ResponseKind {
Tcp = 0,
Ssl = 1,
H3 = 2,
}
impl ResponseKind {
pub const fn from(ssl: bool, http3: bool) -> ResponseKind {
if http3 {
ResponseKind::H3
} else if ssl {
ResponseKind::Ssl
} else {
ResponseKind::Tcp
}
}
}
pub(crate) const _COMPRESSOR_MASK: i32 = 255;
pub(crate) const _DECOMPRESSOR_MASK: i32 = 3840;
pub const SHARED_COMPRESSOR: i32 = 1;
pub const SHARED_DECOMPRESSOR: i32 = 256;
pub const DEDICATED_DECOMPRESSOR: i32 = 3840;
pub const DEDICATED_COMPRESSOR_3KB: i32 = 145;
pub const DEDICATED_COMPRESSOR_4KB: i32 = 146;
pub const DEDICATED_COMPRESSOR_8KB: i32 = 163;
pub const DEDICATED_COMPRESSOR_16KB: i32 = 180;
pub const DEDICATED_COMPRESSOR_32KB: i32 = 197;
pub const DEDICATED_COMPRESSOR_64KB: i32 = 214;
pub const DEDICATED_COMPRESSOR_128KB: i32 = 231;
pub const DEDICATED_COMPRESSOR_256KB: i32 = 248;
pub const DEDICATED_COMPRESSOR: i32 = 248;
pub use bun_uws_sys::{
LIBUS_LISTEN_DEFAULT, LIBUS_LISTEN_DISALLOW_REUSE_PORT_FAILURE, LIBUS_LISTEN_EXCLUSIVE_PORT,
LIBUS_LISTEN_REUSE_ADDR, LIBUS_LISTEN_REUSE_PORT, LIBUS_SOCKET_ALLOW_HALF_OPEN,
LIBUS_SOCKET_IPV6_ONLY,
};
pub use bun_uws_sys::{Opcode, SendStatus, create_bun_socket_error_t, us_bun_verify_error_t};
pub struct SocketAddress {
pub ip: Box<[u8]>,
pub port: i32,
pub is_ipv6: bool,
}
unsafe extern "C" {
safe fn bun_clear_loop_at_thread_exit();
}
pub fn on_thread_exit() {
bun_clear_loop_at_thread_exit()
}
pub use bun_uws_sys::LIBUS_SOCKET_DESCRIPTOR;
mod c {
unsafe extern "C" {
pub(crate) safe fn us_get_default_ciphers() -> *const core::ffi::c_char;
}
}
pub fn get_default_ciphers() -> &'static ZStr {
unsafe {
let p = c::us_get_default_ciphers();
let len = bun_core::ffi::cstr(p).to_bytes().len();
ZStr::from_raw(p.cast::<u8>(), len)
}
}
pub mod ssl_wrapper {
use core::ffi::{c_int, c_void};
use core::ptr::NonNull;
mod boring_sys {
pub(super) use bun_boringssl::c::{
BIO_ctrl_pending, BIO_free, BIO_new, BIO_read, BIO_s_mem, BIO_set_mem_eof_return,
BIO_write, ERR_clear_error, SSL, SSL_CTX, SSL_CTX_free, SSL_CTX_get_verify_mode,
SSL_ERROR_SSL, SSL_ERROR_SYSCALL, SSL_ERROR_WANT_READ, SSL_ERROR_WANT_RENEGOTIATE,
SSL_ERROR_WANT_WRITE, SSL_ERROR_ZERO_RETURN, SSL_RECEIVED_SHUTDOWN, SSL_VERIFY_NONE,
SSL_VERIFY_PEER, SSL_do_handshake, SSL_free, SSL_get_error, SSL_get_rbio,
SSL_get_shutdown, SSL_get_wbio, SSL_is_init_finished, SSL_new, SSL_read,
SSL_renegotiate, SSL_set_accept_state, SSL_set_bio, SSL_set_connect_state,
SSL_set_renegotiate_mode, SSL_set_verify, SSL_set0_verify_cert_store, SSL_shutdown,
SSL_write, X509_STORE, X509_STORE_CTX, ssl_renegotiate_explicit, ssl_renegotiate_never,
};
}
use crate::us_bun_verify_error_t;
use bun_ptr::LaunderedSelf;
bun_core::define_scoped_log!(log, SSLWrapper, hidden);
const BUFFER_SIZE: usize = 65536;
const MAX_RENEGOTIATIONS: u8 = 3;
const MAX_RENEGOTIATION_WINDOW: core::time::Duration = core::time::Duration::from_secs(600);
pub struct SSLWrapper<T: Copy> {
pub handlers: Handlers<T>,
pub ssl: Option<NonNull<boring_sys::SSL>>,
pub ctx: Option<NonNull<boring_sys::SSL_CTX>>,
pub flags: Flags,
pub renegotiation_count: u8,
pub renegotiation_window_start: Option<std::time::Instant>,
}
pub type SslWrapper<T> = SSLWrapper<T>;
#[repr(transparent)]
#[derive(Default)]
pub struct Flags(core::cell::Cell<u8>);
impl Flags {
const HANDSHAKE_MASK: u8 = 0b0000_0011;
const RECEIVED_SSL_SHUTDOWN: u8 = 1 << 2;
const SENT_SSL_SHUTDOWN: u8 = 1 << 3;
const IS_CLIENT: u8 = 1 << 4;
const AUTHORIZED: u8 = 1 << 5;
const FATAL_ERROR: u8 = 1 << 6;
const CLOSED_NOTIFIED: u8 = 1 << 7;
#[inline(always)]
fn bits(&self) -> u8 {
self.0.get()
}
#[inline(always)]
fn set_bit(&self, mask: u8, v: bool) {
let b = self.0.get();
self.0.set(if v { b | mask } else { b & !mask });
}
#[inline]
pub fn handshake_state(&self) -> HandshakeState {
match self.bits() & Self::HANDSHAKE_MASK {
0 => HandshakeState::HandshakePending,
1 => HandshakeState::HandshakeCompleted,
2 => HandshakeState::HandshakeRenegotiationPending,
n => unreachable!("invalid HandshakeState {n}"),
}
}
#[inline]
pub fn set_handshake_state(&self, s: HandshakeState) {
self.0
.set((self.bits() & !Self::HANDSHAKE_MASK) | (s as u8));
}
#[inline]
pub fn received_ssl_shutdown(&self) -> bool {
self.bits() & Self::RECEIVED_SSL_SHUTDOWN != 0
}
#[inline]
pub fn set_received_ssl_shutdown(&self, v: bool) {
self.set_bit(Self::RECEIVED_SSL_SHUTDOWN, v)
}
#[inline]
pub fn sent_ssl_shutdown(&self) -> bool {
self.bits() & Self::SENT_SSL_SHUTDOWN != 0
}
#[inline]
pub fn set_sent_ssl_shutdown(&self, v: bool) {
self.set_bit(Self::SENT_SSL_SHUTDOWN, v)
}
#[inline]
pub fn is_client(&self) -> bool {
self.bits() & Self::IS_CLIENT != 0
}
#[inline]
pub fn set_is_client(&self, v: bool) {
self.set_bit(Self::IS_CLIENT, v)
}
#[inline]
pub fn authorized(&self) -> bool {
self.bits() & Self::AUTHORIZED != 0
}
#[inline]
pub fn set_authorized(&self, v: bool) {
self.set_bit(Self::AUTHORIZED, v)
}
#[inline]
pub fn fatal_error(&self) -> bool {
self.bits() & Self::FATAL_ERROR != 0
}
#[inline]
pub fn set_fatal_error(&self, v: bool) {
self.set_bit(Self::FATAL_ERROR, v)
}
#[inline]
pub fn closed_notified(&self) -> bool {
self.bits() & Self::CLOSED_NOTIFIED != 0
}
#[inline]
pub fn set_closed_notified(&self, v: bool) {
self.set_bit(Self::CLOSED_NOTIFIED, v)
}
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum HandshakeState {
HandshakePending = 0,
HandshakeCompleted = 1,
HandshakeRenegotiationPending = 2,
}
pub struct Handlers<T: Copy> {
pub ctx: T,
pub on_open: fn(T),
pub on_handshake: fn(T, bool, us_bun_verify_error_t),
pub write: fn(T, &[u8]),
pub on_data: fn(T, &[u8]),
pub on_close: fn(T),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::IntoStaticStr)]
pub enum InitError {
OutOfMemory,
InvalidOptions,
}
bun_core::named_error_set!(InitError);
#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::IntoStaticStr)]
pub enum WriteDataError {
ConnectionClosed,
WantRead,
WantWrite,
}
bun_core::named_error_set!(WriteDataError);
unsafe impl<T: Copy> bun_ptr::LaunderedSelf for SSLWrapper<T> {}
impl<T: Copy> SSLWrapper<T> {
pub fn init_with_ctx(
ctx: NonNull<boring_sys::SSL_CTX>,
is_client: bool,
handlers: Handlers<T>,
) -> Result<Self, InitError> {
bun_boringssl::load();
let ssl = NonNull::new(unsafe { boring_sys::SSL_new(ctx.as_ptr()) })
.ok_or(InitError::OutOfMemory)?;
let ssl_guard = scopeguard::guard(ssl, |ssl| {
unsafe { boring_sys::SSL_free(ssl.as_ptr()) };
});
unsafe {
if is_client {
boring_sys::SSL_set_renegotiate_mode(
ssl.as_ptr(),
boring_sys::ssl_renegotiate_explicit,
);
boring_sys::SSL_set_connect_state(ssl.as_ptr());
if boring_sys::SSL_CTX_get_verify_mode(ctx.as_ptr())
== boring_sys::SSL_VERIFY_NONE
{
boring_sys::SSL_set_verify(
ssl.as_ptr(),
boring_sys::SSL_VERIFY_PEER,
Some(always_continue_verify),
);
if let Some(roots) = NonNull::new(us_get_shared_default_ca_store()) {
let _ = boring_sys::SSL_set0_verify_cert_store(
ssl.as_ptr(),
roots.as_ptr(),
);
}
}
} else {
boring_sys::SSL_set_renegotiate_mode(
ssl.as_ptr(),
boring_sys::ssl_renegotiate_never,
);
boring_sys::SSL_set_accept_state(ssl.as_ptr());
}
}
let input = NonNull::new(unsafe { boring_sys::BIO_new(boring_sys::BIO_s_mem()) })
.ok_or(InitError::OutOfMemory)?;
let input_guard = scopeguard::guard(input, |bio| {
unsafe {
let _ = boring_sys::BIO_free(bio.as_ptr());
}
});
let output = NonNull::new(unsafe { boring_sys::BIO_new(boring_sys::BIO_s_mem()) })
.ok_or(InitError::OutOfMemory)?;
unsafe {
let _ = boring_sys::BIO_set_mem_eof_return(input.as_ptr(), -1);
let _ = boring_sys::BIO_set_mem_eof_return(output.as_ptr(), -1);
boring_sys::SSL_set_bio(ssl.as_ptr(), input.as_ptr(), output.as_ptr());
}
let _ = scopeguard::ScopeGuard::into_inner(input_guard);
let ssl = scopeguard::ScopeGuard::into_inner(ssl_guard);
let flags = Flags::default();
flags.set_is_client(is_client);
Ok(Self {
handlers,
flags,
ctx: Some(ctx),
ssl: Some(ssl),
renegotiation_count: 0,
renegotiation_window_start: None,
})
}
pub fn init_from_options(
ctx_opts: &crate::SocketContext::BunSocketContextOptions,
is_client: bool,
handlers: Handlers<T>,
) -> Result<Self, InitError> {
bun_boringssl::load();
let mut err = crate::create_bun_socket_error_t::none;
let Some(ssl_ctx) = ctx_opts.create_ssl_context(&mut err).and_then(NonNull::new) else {
return Err(InitError::InvalidOptions);
};
let ctx_guard = scopeguard::guard(ssl_ctx, |c| {
unsafe { boring_sys::SSL_CTX_free(c.as_ptr()) };
});
let this = Self::init_with_ctx(ssl_ctx, is_client, handlers)?;
let _ = scopeguard::ScopeGuard::into_inner(ctx_guard);
Ok(this)
}
pub fn start(&mut self) {
(self.handlers.on_open)(self.handlers.ctx);
self.handle_traffic();
}
pub fn start_with_payload(&mut self, payload: &[u8]) {
(self.handlers.on_open)(self.handlers.ctx);
self.receive_data(payload);
self.handle_traffic();
}
pub fn shutdown_read(&mut self) {
fn dummy_on_data<T: Copy>(_: T, _: &[u8]) {}
self.handlers.on_data = dummy_on_data::<T>;
}
pub fn shutdown(&mut self, fast_shutdown: bool) -> bool {
let this: *mut Self = core::hint::black_box(core::ptr::from_mut(self));
let Some(ssl) = Self::r(this).ssl else {
return false;
};
if Self::r(this).flags.sent_ssl_shutdown() || Self::r(this).flags.fatal_error() {
return Self::r(this).flags.received_ssl_shutdown();
}
let ret = unsafe { boring_sys::SSL_shutdown(ssl.as_ptr()) };
if fast_shutdown {
unsafe {
let _ = boring_sys::SSL_shutdown(ssl.as_ptr());
}
Self::r(this).flags.set_received_ssl_shutdown(true);
if Self::r(this).flags.handshake_state() != HandshakeState::HandshakeCompleted {
Self::r(this)
.flags
.set_handshake_state(HandshakeState::HandshakeCompleted);
let verify = Self::r(this).get_verify_error();
Self::r(this).trigger_handshake_callback(false, verify);
}
Self::r(this).trigger_close_callback();
return false;
}
Self::r(this).flags.set_sent_ssl_shutdown(ret >= 0);
if ret < 0 {
let err = unsafe { boring_sys::SSL_get_error(ssl.as_ptr(), ret) };
boring_sys::ERR_clear_error();
if err == boring_sys::SSL_ERROR_SSL || err == boring_sys::SSL_ERROR_SYSCALL {
Self::r(this).flags.set_fatal_error(true);
Self::r(this).trigger_close_callback();
return false;
}
}
ret == 1 }
pub fn flush(&mut self) -> usize {
self.handle_traffic();
let Some(ssl) = self.ssl else { return 0 };
unsafe { boring_sys::BIO_ctrl_pending(boring_sys::SSL_get_wbio(ssl.as_ptr())) }
}
pub fn has_pending_data(&self) -> bool {
let Some(ssl) = self.ssl else { return false };
unsafe {
boring_sys::BIO_ctrl_pending(boring_sys::SSL_get_wbio(ssl.as_ptr())) > 0
|| boring_sys::BIO_ctrl_pending(boring_sys::SSL_get_rbio(ssl.as_ptr())) > 0
}
}
fn has_pending_read(&self) -> bool {
let Some(ssl) = self.ssl else { return false };
unsafe { boring_sys::BIO_ctrl_pending(boring_sys::SSL_get_rbio(ssl.as_ptr())) > 0 }
}
pub fn is_shutdown(&self) -> bool {
self.flags.closed_notified()
|| self.flags.received_ssl_shutdown()
|| self.flags.sent_ssl_shutdown()
}
pub fn is_closed(&self) -> bool {
self.flags.received_ssl_shutdown() && self.flags.sent_ssl_shutdown()
}
pub fn is_authorized(&self) -> bool {
if self.flags.handshake_state() == HandshakeState::HandshakeCompleted {
return self.flags.authorized();
}
false
}
pub fn receive_data(&mut self, data: &[u8]) {
let Some(ssl) = self.ssl else { return };
let Some(input) = NonNull::new(unsafe { boring_sys::SSL_get_rbio(ssl.as_ptr()) })
else {
return;
};
let written = unsafe {
boring_sys::BIO_write(
input.as_ptr(),
data.as_ptr().cast::<c_void>(),
c_int::try_from(data.len()).expect("int cast"),
)
};
if written > -1 {
self.handle_traffic();
}
}
pub fn write_data(&mut self, data: &[u8]) -> Result<usize, WriteDataError> {
let Some(ssl) = self.ssl else {
return Err(WriteDataError::ConnectionClosed);
};
if self.flags.sent_ssl_shutdown() {
return Err(WriteDataError::ConnectionClosed);
}
if data.is_empty() {
self.handle_traffic();
return Ok(0);
}
let written = unsafe {
boring_sys::SSL_write(
ssl.as_ptr(),
data.as_ptr().cast::<c_void>(),
c_int::try_from(data.len()).expect("int cast"),
)
};
if written <= 0 {
let err = unsafe { boring_sys::SSL_get_error(ssl.as_ptr(), written) };
boring_sys::ERR_clear_error();
if err == boring_sys::SSL_ERROR_WANT_READ {
self.handle_traffic();
return Err(WriteDataError::WantRead);
}
if err == boring_sys::SSL_ERROR_WANT_WRITE {
self.handle_traffic();
return Err(WriteDataError::WantWrite);
}
self.flags.set_fatal_error(
err == boring_sys::SSL_ERROR_SSL || err == boring_sys::SSL_ERROR_SYSCALL,
);
self.trigger_close_callback();
return Err(WriteDataError::ConnectionClosed);
}
self.handle_traffic();
Ok(usize::try_from(written).expect("int cast"))
}
pub fn deinit(&mut self) {
self.flags.set_closed_notified(true);
if let Some(ssl) = self.ssl.take() {
unsafe { boring_sys::SSL_free(ssl.as_ptr()) };
}
if let Some(ctx) = self.ctx.take() {
unsafe { boring_sys::SSL_CTX_free(ctx.as_ptr()) };
}
}
fn trigger_handshake_callback(&mut self, success: bool, result: us_bun_verify_error_t) {
if self.flags.closed_notified() {
return;
}
self.flags.set_authorized(success);
(self.handlers.on_handshake)(self.handlers.ctx, success, result);
}
fn trigger_wanna_write_callback(&mut self, data: &[u8]) {
if self.flags.closed_notified() {
return;
}
(self.handlers.write)(self.handlers.ctx, data);
}
fn trigger_data_callback(&mut self, data: &[u8]) {
if self.flags.closed_notified() {
return;
}
(self.handlers.on_data)(self.handlers.ctx, data);
}
fn trigger_close_callback(&mut self) {
if self.flags.closed_notified() {
return;
}
self.flags.set_closed_notified(true);
(self.handlers.on_close)(self.handlers.ctx);
}
fn get_verify_error(&self) -> us_bun_verify_error_t {
if self.is_shutdown() {
return us_bun_verify_error_t::default();
}
let Some(ssl) = self.ssl else {
return us_bun_verify_error_t::default();
};
unsafe { us_ssl_socket_verify_error_from_ssl(ssl.as_ptr()) }
}
fn update_handshake_state(&mut self) -> bool {
let this: *mut Self = core::hint::black_box(core::ptr::from_mut(self));
if Self::r(this).flags.closed_notified() {
return false;
}
let Some(ssl) = Self::r(this).ssl else {
return false;
};
if unsafe { boring_sys::SSL_is_init_finished(ssl.as_ptr()) } != 0 {
if (unsafe { boring_sys::SSL_get_shutdown(ssl.as_ptr()) }
& boring_sys::SSL_RECEIVED_SHUTDOWN)
!= 0
{
Self::r(this).flags.set_received_ssl_shutdown(true);
let _ = Self::r(this).shutdown(false);
Self::r(this).trigger_close_callback();
return false;
}
return true;
}
if Self::r(this).flags.handshake_state()
== HandshakeState::HandshakeRenegotiationPending
{
return true;
}
let result = unsafe { boring_sys::SSL_do_handshake(ssl.as_ptr()) };
if result <= 0 {
let err = unsafe { boring_sys::SSL_get_error(ssl.as_ptr(), result) };
boring_sys::ERR_clear_error();
if err == boring_sys::SSL_ERROR_ZERO_RETURN {
Self::r(this).flags.set_received_ssl_shutdown(true);
let _ = Self::r(this).shutdown(false);
Self::r(this).handle_end_of_renegotiation();
return false;
}
if err != boring_sys::SSL_ERROR_WANT_READ && err != boring_sys::SSL_ERROR_WANT_WRITE
{
Self::r(this).flags.set_fatal_error(
err == boring_sys::SSL_ERROR_SSL || err == boring_sys::SSL_ERROR_SYSCALL,
);
Self::r(this)
.flags
.set_handshake_state(HandshakeState::HandshakeCompleted);
let verify = Self::r(this).get_verify_error();
Self::r(this).trigger_handshake_callback(false, verify);
if Self::r(this).flags.fatal_error() {
Self::r(this).trigger_close_callback();
return false;
}
return true;
}
Self::r(this)
.flags
.set_handshake_state(HandshakeState::HandshakePending);
return true;
}
Self::r(this)
.flags
.set_handshake_state(HandshakeState::HandshakeCompleted);
let verify = Self::r(this).get_verify_error();
Self::r(this).trigger_handshake_callback(true, verify);
true
}
fn handle_end_of_renegotiation(&mut self) {
if self.flags.handshake_state() == HandshakeState::HandshakeRenegotiationPending
&& (self.ssl.is_none()
|| unsafe { boring_sys::SSL_is_init_finished(self.ssl.unwrap().as_ptr()) } != 0)
{
self.flags
.set_handshake_state(HandshakeState::HandshakeCompleted);
let verify = self.get_verify_error();
self.trigger_handshake_callback(true, verify);
}
}
fn handle_reading(&mut self, buffer: &mut [u8; BUFFER_SIZE]) -> bool {
let this: *mut Self = core::hint::black_box(core::ptr::from_mut(self));
let mut read: usize = 0;
loop {
log!("handleReading");
let Some(ssl) = Self::r(this).ssl else {
return false;
};
let available = &mut buffer[read..];
let just_read = unsafe {
boring_sys::SSL_read(
ssl.as_ptr(),
available.as_mut_ptr().cast::<c_void>(),
c_int::try_from(available.len()).expect("int cast"),
)
};
log!("just read {}", just_read);
if just_read <= 0 {
let err = unsafe { boring_sys::SSL_get_error(ssl.as_ptr(), just_read) };
boring_sys::ERR_clear_error();
if err != boring_sys::SSL_ERROR_WANT_READ
&& err != boring_sys::SSL_ERROR_WANT_WRITE
{
if err == boring_sys::SSL_ERROR_WANT_RENEGOTIATE {
Self::r(this)
.flags
.set_handshake_state(HandshakeState::HandshakeRenegotiationPending);
let now = std::time::Instant::now();
match Self::r(this).renegotiation_window_start {
Some(start)
if now.duration_since(start) < MAX_RENEGOTIATION_WINDOW => {}
_ => {
Self::r(this).renegotiation_window_start = Some(now);
Self::r(this).renegotiation_count = 0;
}
}
let renegotiation_allowed =
Self::r(this).renegotiation_count < MAX_RENEGOTIATIONS;
Self::r(this).renegotiation_count =
Self::r(this).renegotiation_count.saturating_add(1);
let renegotiated = renegotiation_allowed
&& unsafe { boring_sys::SSL_renegotiate(ssl.as_ptr()) } != 0;
if !renegotiated {
Self::r(this)
.flags
.set_handshake_state(HandshakeState::HandshakeCompleted);
let verify = Self::r(this).get_verify_error();
Self::r(this).trigger_handshake_callback(false, verify);
Self::r(this).trigger_close_callback();
return false;
}
continue;
} else if err == boring_sys::SSL_ERROR_ZERO_RETURN {
Self::r(this).flags.set_received_ssl_shutdown(true);
let _ = Self::r(this).shutdown(false);
Self::r(this).handle_end_of_renegotiation();
}
Self::r(this).flags.set_fatal_error(
err == boring_sys::SSL_ERROR_SSL
|| err == boring_sys::SSL_ERROR_SYSCALL,
);
if read > 0 {
log!("triggering data callback (read {})", read);
Self::r(this).trigger_data_callback(&buffer[0..read]);
if Self::r(this).ssl.is_none() || Self::r(this).flags.closed_notified()
{
return false;
}
}
Self::r(this).trigger_close_callback();
return false;
} else {
log!("wanna read/write just break");
break;
}
}
Self::r(this).handle_end_of_renegotiation();
read += usize::try_from(just_read).expect("int cast");
if read == buffer.len() {
log!(
"triggering data callback (read {}) and resetting read buffer",
read
);
Self::r(this).trigger_data_callback(&buffer[0..read]);
if Self::r(this).ssl.is_none() || Self::r(this).flags.closed_notified() {
return false;
}
read = 0;
}
}
if read > 0 {
log!("triggering data callback (read {})", read);
Self::r(this).trigger_data_callback(&buffer[0..read]);
if Self::r(this).ssl.is_none() || Self::r(this).flags.closed_notified() {
return false;
}
}
true
}
fn handle_writing(&mut self, buffer: &mut [u8; BUFFER_SIZE]) {
let this: *mut Self = core::hint::black_box(core::ptr::from_mut(self));
let mut read: usize = 0;
loop {
let Some(ssl) = Self::r(this).ssl else { return };
let Some(output) = NonNull::new(unsafe { boring_sys::SSL_get_wbio(ssl.as_ptr()) })
else {
return;
};
let available = &mut buffer[read..];
let just_read = unsafe {
boring_sys::BIO_read(
output.as_ptr(),
available.as_mut_ptr().cast::<c_void>(),
c_int::try_from(available.len()).expect("int cast"),
)
};
if just_read > 0 {
read += usize::try_from(just_read).expect("int cast");
if read == buffer.len() {
Self::r(this).trigger_wanna_write_callback(&buffer[0..read]);
read = 0;
}
} else {
break;
}
}
if read > 0 {
Self::r(this).trigger_wanna_write_callback(&buffer[0..read]);
}
}
fn handle_traffic(&mut self) {
let this: *mut Self = core::hint::black_box(core::ptr::from_mut(self));
if Self::r(this).update_handshake_state() {
let mut buffer = [0u8; BUFFER_SIZE];
Self::r(this).handle_writing(&mut buffer);
while Self::r(this).has_pending_read() && Self::r(this).handle_reading(&mut buffer)
{
Self::r(this).handle_writing(&mut buffer);
}
}
}
}
impl<T: Copy> Drop for SSLWrapper<T> {
fn drop(&mut self) {
self.deinit();
}
}
extern "C" fn always_continue_verify(_: c_int, _: *mut boring_sys::X509_STORE_CTX) -> c_int {
1
}
unsafe extern "C" {
safe fn us_get_shared_default_ca_store() -> *mut boring_sys::X509_STORE;
fn us_ssl_socket_verify_error_from_ssl(ssl: *mut boring_sys::SSL) -> us_bun_verify_error_t;
}
}
pub use bun_uws_sys::loop_::{LoopHandler, us_wakeup_loop};
pub use bun_uws_sys::{InternalLoopData, Loop, PosixLoop, Timespec, WindowsLoop};
pub trait ParentEventLoopHandle {
fn into_tag_ptr(self) -> (core::ffi::c_char, *mut c_void);
}
pub trait InternalLoopDataExt {
fn set_parent_event_loop<H: ParentEventLoopHandle>(&mut self, parent: H);
fn get_parent(&self) -> (core::ffi::c_char, *mut c_void);
}
impl InternalLoopDataExt for InternalLoopData {
#[inline]
fn set_parent_event_loop<H: ParentEventLoopHandle>(&mut self, parent: H) {
let (tag, ptr) = parent.into_tag_ptr();
self.set_parent_raw(tag, ptr);
}
#[inline]
fn get_parent(&self) -> (core::ffi::c_char, *mut c_void) {
self.get_parent_raw()
}
}
pub use bun_uws_sys::socket_group::VTable as SocketGroupVTable;
pub use bun_uws_sys::{ConnectResult, SocketGroup};
pub mod SocketContext {
pub use bun_uws_sys::BunSocketContextOptions;
}
pub use SocketContext as socket_context;
pub type us_bun_socket_context_options_t = SocketContext::BunSocketContextOptions;
pub use bun_uws_sys::SocketKind;
pub type DispatchKind = SocketKind;
pub use bun_uws_sys::CloseCode;
pub type CloseKind = CloseCode;
pub use bun_uws_sys::socket::{
AnySocket, ConnectError, InternalSocket, NewSocketHandler, SocketHandler, SocketTCP, SocketTLS,
SocketTcp, SocketTls,
};
pub enum MaybeAnySocket {
Tcp(SocketTCP),
Ssl(SocketTLS),
None,
}
impl MaybeAnySocket {
#[inline]
pub fn from_generic<const IS_SSL: bool>(socket: NewSocketHandler<IS_SSL>) -> Self {
if IS_SSL {
MaybeAnySocket::Ssl(socket.assume_ssl())
} else {
MaybeAnySocket::Tcp(socket.assume_tcp())
}
}
#[inline]
pub fn write(&self, data: &[u8]) -> i32 {
match self {
MaybeAnySocket::Tcp(s) => s.write(data),
MaybeAnySocket::Ssl(s) => s.write(data),
MaybeAnySocket::None => 0,
}
}
#[inline]
pub fn is_closed(&self) -> bool {
match self {
MaybeAnySocket::Tcp(s) => s.is_closed(),
MaybeAnySocket::Ssl(s) => s.is_closed(),
MaybeAnySocket::None => true,
}
}
}
pub use bun_uws_sys::AnyRequest;
pub type Response<const SSL: bool> = bun_uws_sys::response::Response<SSL>;
pub use bun_uws_sys::AnyResponse;
pub use bun_uws_sys::response::WriteResult;
pub mod ws_codec;
pub mod ws_handshake;
pub mod ws_client;
pub mod ws_server;
pub use ws_client::{parse_ws_url, ws_connect, RecvOutcome, WebSocketClient, WsClientError};
pub use ws_codec::{
apply_mask, gen_mask_key, FrameDecoder, FrameEncoder, FrameHeader, Message,
};
pub use ws_handshake::{
client_handshake, compute_accept, generate_sec_websocket_key, server_handshake, HandshakeError,
};
pub use ws_server::{
bind_nonblocking, read_message, ReadOutcome, ReplayStream, WsServerConnection,
};