pi_quic 0.5.1

Quic client/server
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
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 {}

///
/// Quic连接状态
///
#[derive(Debug, Clone, Copy)]
pub enum QuicSocketStatus {
    UdpAccepted = 0,    //Udp连接已建立
    Handshaking,        //正在进行Quic握手
    Connecting,         //Quic连接已建立,正在打开初始化流
    Connected,          //Quic连接已建立,并打开初始化流
    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,
        }
    }
}

///
/// Quic连接就绪状态
///
#[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
    }

    /// 增加Quic连接就绪状态
    pub fn add(self, other: Self) -> Self {
        let x: u8 = self.into();
        let y: u8 = other.into();
        (x | y).into()
    }

    /// 移除Quic连接就绪状态
    pub fn remove(self, other: Self) -> Self {
        let x: u8 = self.into();
        let y: u8 = other.into();
        (x & !y).into()
    }
}

/// Quic连接关闭事件
pub enum QuicCloseEvent {
    CloseStream(ConnectionHandle, Option<StreamId>, u32),   //关闭流
    CloseConnect(ConnectionHandle),                         //关闭连接
}

// 加载指定Pem文件的证书
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())
        },
    }
}

// 加载指定Pem证书数据
#[inline]
pub fn load_cert(bin: Vec<u8>) -> Certificate {
    Certificate(bin)
}

// 加载指定Pem文件的私钥
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())))
}

// 加载指定Pem私钥数据
#[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,               //当前Quic连接的句柄
    stream_id:      StreamId,                   //当前Quicl连接的指定流
    ready:          QuicSocketReady,            //唤醒后感兴趣的事件
    waker:          SpinLock<Option<Waker>>,    //休眠唤醒器
    waker_status:   AtomicU8,                   //唤醒状态
    result:         AsyncWaitResult<()>,        //结果值
}

///
/// Quic客户端定时器事件
///
#[derive(Debug)]
pub enum QuicClientTimerEvent {
    UdpConnect(usize),  //建立Udp连接
    QuicConnect(usize), //建立Quic连接
}

///
/// 上下文句柄
///
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))
                },
            }
        }
    }
}