use std::ptr;
use std::sync::Arc;
use std::task::Waker;
use std::time::Duration;
use std::net::SocketAddr;
use std::cell::UnsafeCell;
use std::result::Result as GenResult;
use std::io::{Error, Result, ErrorKind};
use std::sync::atomic::{AtomicU8, Ordering};
use futures::future::LocalBoxFuture;
use quinn_proto::{ConnectionHandle, ConnectionEvent, Dir, StreamId, Transmit};
use crossbeam_channel::Sender;
use crossbeam_utils::atomic::AtomicCell;
use bytes::BytesMut;
use pi_async_rt::{lock::spin_lock::SpinLock,
rt::{AsyncValue,
serial_local_thread::LocalTaskRuntime}};
use udp::SocketHandle as UdpSocketHandle;
pub mod acceptor;
pub mod connect;
pub mod connect_pool;
pub mod server;
pub mod client;
pub mod utils;
use crate::connect::QuicSocket;
use crate::utils::{QuicSocketStatus, QuicSocketReady, Hibernate, ContextHandle};
#[cfg(all(test, feature = "runtime_metrics", not(target_arch = "wasm32")))]
std::thread_local! {
static QUIC_METRICS_TEST_RESULT: std::cell::RefCell<Option<(usize, String,
std::result::Result<pi_async_rt::runtime_metrics::RuntimeMetricId,
pi_async_rt::runtime_metrics::RuntimeMetricRegistrationError>)>> = const { std::cell::RefCell::new(None) };
}
fn register_local_runtime_metrics(runtime: &LocalTaskRuntime<()>) {
#[cfg(all(feature = "runtime_metrics", not(target_arch = "wasm32")))]
{
let metric_name = format!("pi_quic-local-{}", runtime.get_id());
let registration = pi_async_rt::runtime_metrics::register_runtime_metrics(runtime, &metric_name);
#[cfg(test)]
QUIC_METRICS_TEST_RESULT.with(|value| {
*value.borrow_mut() = Some((runtime.get_id(), metric_name.clone(), registration));
});
if let Err(error) = registration {
log::warn!("QUIC 运行时指标注册失败, 名称: {}, 原因: {}", metric_name, error);
}
}
#[cfg(not(all(feature = "runtime_metrics", not(target_arch = "wasm32"))))]
let _ = runtime;
}
#[cfg(all(test, feature = "runtime_metrics", not(target_arch = "wasm32")))]
mod batch_runtime_metrics_tests {
use super::*;
#[test]
fn test_quic_registers_runtime_metrics() {
QUIC_METRICS_TEST_RESULT.with(|value| { value.borrow_mut().take(); });
let runner = pi_async_rt::rt::serial_local_thread::LocalTaskRunner::<()>::new();
let runtime = runner.get_runtime();
let expected_id = runtime.get_id();
register_local_runtime_metrics(&runtime);
let observed = QUIC_METRICS_TEST_RESULT.with(|value| value.borrow_mut().take());
if let Some((_, _, Ok(id))) = &observed {
let _ = pi_async_rt::runtime_metrics::unregister_runtime_metrics(*id);
}
let (actual_id, actual_name, registration) = observed.expect("实际冷登记必须发生");
assert_eq!(actual_id, expected_id);
assert_eq!(actual_name, format!("pi_quic-local-{}", expected_id));
assert!(registration.is_ok(), "真实登记必须成功: {:?}", registration);
}
}
pub trait AsyncService: Send + Sync + 'static {
fn handle_connected(&self,
handle: SocketHandle,
result: Result<()>) -> LocalBoxFuture<'static, ()>;
fn handle_opened_expanding_stream(&self,
handle: SocketHandle,
stream_id: StreamId,
stream_type: Dir,
result: Result<()>) -> LocalBoxFuture<'static, ()>;
fn handle_readed(&self,
handle: SocketHandle,
stream_id: StreamId,
result: Result<usize>) -> LocalBoxFuture<'static, ()>;
fn handle_writed(&self,
handle: SocketHandle,
stream_id: StreamId,
result: Result<()>) -> LocalBoxFuture<'static, ()>;
fn handle_closed(&self,
handle: SocketHandle,
stream_id: Option<StreamId>,
code: u32,
result: Result<()>) -> LocalBoxFuture<'static, ()>;
fn handle_timeouted(&self,
handle: SocketHandle,
result: Result<SocketEvent>) -> LocalBoxFuture<'static, ()>;
}
pub struct SocketHandle(Arc<InnerSocketHandle>);
unsafe impl Send for SocketHandle {}
unsafe impl Sync for SocketHandle {}
impl Clone for SocketHandle {
fn clone(&self) -> Self {
SocketHandle(self.0.clone())
}
}
impl SocketHandle {
pub fn new(uid: usize,
status: Arc<AtomicU8>,
socket: Arc<UnsafeCell<QuicSocket>>,
local: SocketAddr,
remote: SocketAddr,
sender: Sender<QuicEvent>) -> Self {
let inner = InnerSocketHandle {
uid,
status,
inner: socket,
local: AtomicCell::new(local),
remote,
sender,
};
SocketHandle(Arc::new(inner))
}
pub fn broadcast(handles: &[SocketHandle],
payload: Vec<u8>) -> Result<()> {
if handles.len() == 0 {
return Ok(());
}
for handle in handles {
for stream_id in handle.get_stream_ids() {
handle.write_ready(stream_id, payload.clone())?;
}
}
Ok(())
}
pub fn get_uid(&self) -> usize {
self.0.uid
}
pub fn get_status(&self) -> QuicSocketStatus {
self
.0
.status
.load(Ordering::Acquire)
.into()
}
pub fn get_local_udp(&self) -> &SocketAddr {
unsafe {
(&*self.0.inner.get())
.get_udp_handle()
.get_local()
}
}
pub fn get_remote_udp(&self) -> Option<&SocketAddr> {
unsafe {
(&*self.0.inner.get())
.get_udp_handle()
.get_remote()
}
}
pub fn get_local(&self) -> SocketAddr {
self
.0
.local
.load()
}
pub fn set_local(&self, local: SocketAddr) {
self
.0
.local
.store(local);
}
pub fn get_remote(&self) -> SocketAddr {
self.0.remote
}
pub fn get_udp_uid(&self) -> usize {
unsafe {
(&*self.0.inner.get()).get_udp_handle().get_uid()
}
}
pub fn is_client(&self) -> bool {
unsafe {
(&*self.0.inner.get()).is_client()
}
}
pub fn get_connection_handle(&self) -> &ConnectionHandle {
unsafe {
(&*self.0.inner.get()).get_connection_handle()
}
}
pub fn get_session<T>(&self) -> Option<ContextHandle<T>> {
unsafe {
(&*(&*self.0.inner.get()).get_context().get()).get::<T>()
}
}
pub fn set_session<T>(&self, context: T) {
unsafe {
(&mut *(&*self.0.inner.get()).get_context().get()).set::<T>(context);
}
}
pub fn remove_session<T>(&self) -> Result<Option<T>> {
unsafe {
match (&mut *(&*self.0.inner.get()).get_context().get()).remove::<T>() {
Err(e) => Err(Error::new(ErrorKind::Other, e)),
Ok(r) => Ok(r)
}
}
}
pub fn is_0rtt(&self) -> bool {
unsafe {
(&*self.0.inner.get()).is_0rtt()
}
}
pub fn is_closed(&self) -> bool {
unsafe {
(&*self.0.inner.get()).is_closed()
}
}
pub fn get_latency(&self) -> Duration {
unsafe {
(&*self.0.inner.get()).get_latency()
}
}
pub fn get_main_stream_id(&self) -> Option<&StreamId> {
unsafe {
(&*self.0.inner.get()).get_main_stream_id()
}
}
pub(crate) fn open_main_streams(&self) -> Result<()> {
unsafe {
(&mut *self.0.inner.get()).open_main_streams()
}
}
pub async fn open_expanding_stream(&self, stream_type: Dir) -> Result<StreamId> {
unsafe {
(&*self.0.inner.get()).open_expanding_stream(stream_type).await
}
}
pub fn set_ready(&self,
stream_id: StreamId,
ready: QuicSocketReady) {
unsafe {
(&*self.0.inner.get()).set_ready(stream_id, ready);
}
}
pub fn get_stream_ids(&self) -> Vec<StreamId> {
unsafe {
(&*self.0.inner.get()).get_stream_ids()
}
}
pub fn read_ready(&self,
stream_id: &StreamId,
adjust: usize) -> GenResult<AsyncValue<usize>, usize> {
unsafe {
(&mut *self.0.inner.get()).read_ready(stream_id, adjust)
}
}
pub fn read_buffer_remaining(&self, stream_id: &StreamId) -> Option<usize> {
unsafe {
(&*self.0.inner.get()).read_buffer_remaining(stream_id)
}
}
pub fn get_read_buffer(&self,
stream_id: &StreamId) -> Option<Arc<SpinLock<Option<BytesMut>>>> {
unsafe {
(&*self.0.inner.get()).get_read_buffer(stream_id)
}
}
pub fn write_ready<B>(&self,
stream_id: StreamId,
buf: B) -> Result<()>
where B: AsRef<[u8]> + 'static {
unsafe {
(&*self.0.inner.get()).write_ready(stream_id, buf)
}
}
pub fn set_timeout(&self, timeout: usize, event: SocketEvent) {
unsafe {
(&*self.0.inner.get()).set_timeout(timeout, event);
}
}
pub fn unset_timeout(&self) {
unsafe {
(&*self.0.inner.get()).unset_timeout();
}
}
pub fn run_hibernated_tasks(&self) {
unsafe {
(&*self.0.inner.get()).run_hibernated_tasks();
}
}
pub fn hibernate(&self,
stream_id: StreamId,
ready: QuicSocketReady) -> Option<Hibernate> {
unsafe {
(&*self.0.inner.get()).hibernate(self.clone(),
stream_id,
ready)
}
}
pub fn set_hibernate(&self, hibernate: Hibernate) -> bool {
unsafe {
(&*self.0.inner.get()).set_hibernate(hibernate)
}
}
pub fn set_hibernate_wakers(&self, waker: Waker) {
unsafe {
(&*self.0.inner.get()).set_hibernate_wakers(waker);
}
}
pub fn wakeup(&self, result: Result<()>) -> bool {
unsafe {
(&mut *self.0.inner.get()).wakeup(result)
}
}
pub fn get_runtime(&self) -> Option<LocalTaskRuntime<()>> {
unsafe {
(&*self.0.inner.get()).get_runtime()
}
}
pub fn spawn(&self, task: LocalBoxFuture<'static, ()>) {
unsafe {
(&*self.0.inner.get()).spawn(task);
}
}
pub fn close_expanding_stream(&self, stream_id: StreamId) -> Result<()> {
unsafe {
(&*self.0.inner.get()).close_expanding_stream(stream_id)
}
}
pub fn close(&self, code: u32, reason: Result<()>) -> Result<()> {
unsafe {
(&mut *self.0.inner.get()).close(code, reason)
}
}
pub fn force_close(&mut self, code: u32, reason: String) {
unsafe {
(&mut *self.0.inner.get()).force_close(code, reason);
}
}
}
struct InnerSocketHandle {
uid: usize, status: Arc<AtomicU8>, inner: Arc<UnsafeCell<QuicSocket>>, local: AtomicCell<SocketAddr>, remote: SocketAddr, sender: Sender<QuicEvent>, }
#[derive(Debug)]
pub struct SocketEvent {
inner: *mut (), }
unsafe impl Send for SocketEvent {}
impl SocketEvent {
pub fn empty() -> Self {
SocketEvent {
inner: ptr::null_mut(),
}
}
pub fn is_empty(&self) -> bool {
self.inner.is_null()
}
pub fn get<T: 'static>(&self) -> Option<T> {
if self.is_empty() {
return None;
}
Some(unsafe { *Box::from_raw(self.inner as *mut T) })
}
pub fn set<T: 'static>(&mut self, event: T) -> bool {
if !self.is_empty() {
return false;
}
self.inner = Box::into_raw(Box::new(event)) as *mut ();
true
}
pub fn remove<T: 'static>(&mut self) -> Option<T> {
if self.is_empty() {
return None;
}
let result = self.get();
self.inner = ptr::null_mut();
result
}
}
#[derive(Debug)]
pub enum QuicEvent {
Accepted(QuicSocket), ConnectionReceived(ConnectionHandle, ConnectionEvent), ConnectionSend(ConnectionHandle, Transmit), StreamOpen(ConnectionHandle, Dir, AsyncValue<Result<StreamId>>), StreamReady(ConnectionHandle, StreamId, QuicSocketReady), StreamWrite(ConnectionHandle, StreamId, Vec<u8>), RebindUdp(UdpSocketHandle), Timeout(ConnectionHandle, Option<(usize, SocketEvent)>), StreamClose(ConnectionHandle, Option<StreamId>, u32), ConnectionClose(ConnectionHandle), }