use std::ptr;
use std::fs::File;
use std::pin::Pin;
use std::sync::Arc;
use std::path::Path;
use std::cell::RefCell;
use std::future::Future;
use std::result::Result as GenResult;
use std::task::{Context, Poll, Waker};
use std::sync::atomic::{AtomicU8, Ordering};
use std::io::{BufReader, Result, Error, ErrorKind};
use pi_async_rt::{lock::spin_lock::SpinLock,
rt::serial::AsyncWaitResult};
use quinn_proto::{ConnectionHandle, StreamId};
use rustls::{Certificate, PrivateKey};
use crate::SocketHandle;
#[derive(Debug, Clone, Copy)]
pub struct Token(pub u64);
unsafe impl Send for Token {}
unsafe impl Sync for Token {}
#[derive(Debug, Clone, Copy)]
pub enum QuicSocketStatus {
UdpAccepted = 0, Handshaking, Connecting, Connected, Closeing, Disconnect, }
impl From<u8> for QuicSocketStatus {
fn from(src: u8) -> Self {
match src {
0 => QuicSocketStatus::UdpAccepted,
1 => QuicSocketStatus::Handshaking,
2 => QuicSocketStatus::Connecting,
3 => QuicSocketStatus::Connected,
4 => QuicSocketStatus::Closeing,
_ => QuicSocketStatus::Disconnect,
}
}
}
impl From<QuicSocketStatus> for u8 {
fn from(src: QuicSocketStatus) -> Self {
match src {
QuicSocketStatus::UdpAccepted => 0,
QuicSocketStatus::Handshaking => 1,
QuicSocketStatus::Connecting => 2,
QuicSocketStatus::Connected => 3,
QuicSocketStatus::Closeing => 4,
QuicSocketStatus::Disconnect => 5,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum QuicSocketReady {
Readable = 1, Writable = 2, ReadWrite = 3, }
impl From<u8> for QuicSocketReady {
fn from(src: u8) -> Self {
match src {
1 => QuicSocketReady::Readable,
2 => QuicSocketReady::Writable,
3 => QuicSocketReady::ReadWrite,
_ => panic!("Invalid number, {}", src),
}
}
}
impl From<QuicSocketReady> for u8 {
fn from(src: QuicSocketReady) -> Self {
match src {
QuicSocketReady::Readable => 1,
QuicSocketReady::Writable => 2,
QuicSocketReady::ReadWrite => 3,
}
}
}
impl QuicSocketReady {
pub fn is_readable(&self) -> bool {
let x: u8 = self.clone().into();
let y: u8 = QuicSocketReady::Readable.into();
(x & y) != 0
}
pub fn is_writable(&self) -> bool {
let x: u8 = self.clone().into();
let y: u8 = QuicSocketReady::Writable.into();
(x & y) != 0
}
pub fn add(self, other: Self) -> Self {
let x: u8 = self.into();
let y: u8 = other.into();
(x | y).into()
}
pub fn remove(self, other: Self) -> Self {
let x: u8 = self.into();
let y: u8 = other.into();
(x & !y).into()
}
}
pub enum QuicCloseEvent {
CloseStream(ConnectionHandle, Option<StreamId>, u32), CloseConnect(ConnectionHandle), }
pub fn load_certs_file<P: AsRef<Path>>(file_path: P) -> Result<Vec<Certificate>> {
let certfile = match File::open(&file_path) {
Err(e) => {
return Err(Error::new(ErrorKind::Other,
format!("Open certs failed, path: {:?}, reason: {:?}",
file_path.as_ref(), e)));
},
Ok(file) => {
file
},
};
let mut reader = BufReader::new(certfile);
match rustls_pemfile::certs(&mut reader) {
Err(e) => {
Err(Error::new(ErrorKind::Other,
format!("Load certs failed, path: {:?}, reason: {:?}",
file_path.as_ref(), e)))
},
Ok(certs) => {
Ok(certs.iter()
.map(|v| {
Certificate(v.clone())
})
.collect())
},
}
}
#[inline]
pub fn load_cert(bin: Vec<u8>) -> Certificate {
Certificate(bin)
}
pub fn load_key_file<P: AsRef<Path>>(file_path: P) -> Result<PrivateKey> {
let keyfile = match File::open(&file_path) {
Err(e) => {
return Err(Error::new(ErrorKind::Other,
format!("Open private key failed, path: {:?}, reason: {:?}",
file_path.as_ref(),
e)));
},
Ok(file) => {
file
},
};
let mut reader = BufReader::new(keyfile);
loop {
match rustls_pemfile::read_one(&mut reader) {
Ok(Some(rustls_pemfile::Item::RSAKey(key))) => return Ok(PrivateKey(key)),
Ok(Some(rustls_pemfile::Item::PKCS8Key(key))) => return Ok(PrivateKey(key)),
Ok(Some(rustls_pemfile::Item::ECKey(key))) => return Ok(PrivateKey(key)),
Ok(None) => break,
Err(e) => {
return Err(Error::new(ErrorKind::Other,
format!("Load private key failed, path: {:?}, reason: {:?}",
file_path.as_ref(),
e)));
},
_ => {
return Err(Error::new(ErrorKind::Other,
format!("Load private key failed, path: {:?}, reason: cannot parse private key .pem file",
file_path.as_ref())))
},
}
}
Err(Error::new(ErrorKind::Other,
format!("no keys found in {:?} (encrypted keys not supported)",
file_path.as_ref())))
}
#[inline]
pub fn load_key(bin: Vec<u8>) -> PrivateKey {
PrivateKey(bin)
}
pub struct Hibernate(Arc<InnerHibernate>);
impl Clone for Hibernate {
fn clone(&self) -> Self {
Hibernate(self.0.clone())
}
}
impl Future for Hibernate {
type Output = Result<()>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut locked = self.0.waker.lock();
let result = self
.0
.result
.0
.borrow_mut()
.take();
if let Some(result) = result {
self
.0
.handle
.set_ready(self.0.stream_id,
self.0.ready); self.0.handle.run_hibernated_tasks();
Poll::Ready(result)
} else {
self
.0
.handle
.set_ready(self.0.stream_id,
self.0.ready);
if self.0.handle.set_hibernate(self.clone()) {
*locked = Some(cx.waker().clone());
} else {
self
.0
.handle
.set_hibernate_wakers(cx.waker().clone());
self.0.waker_status.store(1, Ordering::Relaxed); }
Poll::Pending
}
}
}
impl Hibernate {
pub fn new(handle: SocketHandle,
stream_id: StreamId,
ready: QuicSocketReady) -> Self {
let inner = InnerHibernate {
handle,
stream_id,
ready,
waker: SpinLock::new(None),
waker_status: AtomicU8::new(0),
result: AsyncWaitResult(Arc::new(RefCell::new(None))),
};
Hibernate(Arc::new(inner))
}
pub(crate) fn wakeup(&self, result: Result<()>) -> bool {
let mut locked = self
.0
.waker
.lock();
if let Some(waker) = locked.take() {
if self.0.waker_status.load(Ordering::Relaxed) > 0 {
self.0.waker_status.store(0, Ordering::Relaxed); waker.wake();
false
} else {
*self.0.result.0.borrow_mut() = Some(result);
waker.wake();
true
}
} else {
if self.0.result.0.borrow().is_none() {
false
} else {
true
}
}
}
}
struct InnerHibernate {
handle: SocketHandle, stream_id: StreamId, ready: QuicSocketReady, waker: SpinLock<Option<Waker>>, waker_status: AtomicU8, result: AsyncWaitResult<()>, }
#[derive(Debug)]
pub enum QuicClientTimerEvent {
UdpConnect(usize), QuicConnect(usize), }
pub struct ContextHandle<T: 'static>(Option<Arc<T>>);
unsafe impl<T: 'static> Send for ContextHandle<T> {}
impl<T: 'static> Drop for ContextHandle<T> {
fn drop(&mut self) {
if let Some(shared) = self.0.take() {
let _ = Arc::into_raw(shared);
}
}
}
impl<T: 'static> ContextHandle<T> {
pub fn as_ref(&self) -> &T {
self.0.as_ref().unwrap().as_ref()
}
pub fn as_mut(&mut self) -> Option<&mut T> {
if let Some(shared) = self.0.as_mut() {
return Arc::get_mut(shared);
}
None
}
}
pub struct SocketContext {
inner: *const (), }
unsafe impl Send for SocketContext {}
impl SocketContext {
pub fn empty() -> Self {
SocketContext {
inner: ptr::null(),
}
}
pub fn is_empty(&self) -> bool {
self.inner.is_null()
}
pub fn get<T>(&self) -> Option<ContextHandle<T>> {
if self.is_empty() {
return None;
}
Some(unsafe { ContextHandle(Some(Arc::from_raw(self.inner as *const T))) })
}
pub fn set<T>(&mut self, context: T) -> bool {
if !self.is_empty() {
return false;
}
self.inner = Arc::into_raw(Arc::new(context)) as *const ();
true
}
pub fn remove<T>(&mut self) -> GenResult<Option<T>, &str> {
if self.is_empty() {
return Ok(None);
}
let inner = unsafe { Arc::from_raw(self.inner as *const T) };
if Arc::strong_count(&inner) > 1 {
let _= Arc::into_raw(inner); Err("Remove context failed, reason: context shared exist")
} else {
match Arc::try_unwrap(inner) {
Err(inner) => {
let _ = Arc::into_raw(inner); Err("Remove context failed, reason: invalid shared")
},
Ok(context) => {
self.inner = ptr::null();
Ok(Some(context))
},
}
}
}
}