picoquic 0.1.1

Tokio aware picoquic bindings. Picoquic is a minimalist implementation of the QUIC protocol of the IETF.
Documentation
use super::quic_ctx::socket_addr_from_c;
use picoquic_sys::picoquic::{self, picoquic_delete_stateless_packet,
                             picoquic_dequeue_stateless_packet, picoquic_quic_t,
                             picoquic_stateless_packet_t};

use std::iter::Iterator;
use std::mem;
use std::slice;
use std::net::SocketAddr;
use std::marker::PhantomData;

use libc;

pub struct StatelessPacket {
    packet: *mut picoquic_stateless_packet_t,
}

impl StatelessPacket {
    fn new(packet: *mut picoquic_stateless_packet_t) -> StatelessPacket {
        StatelessPacket { packet }
    }

    pub fn get_peer_addr(&self) -> SocketAddr {
        let addr = unsafe {
            mem::transmute::<&mut picoquic::sockaddr_storage, *mut picoquic::sockaddr>(
                &mut (*self.packet).addr_to,
            )
        };
        let socket_family = unsafe { (*self.packet).addr_to.ss_family };

        let socket_len = if socket_family as i32 == libc::AF_INET {
            mem::size_of::<libc::sockaddr_in>()
        } else {
            mem::size_of::<libc::sockaddr_in6>()
        };

        socket_addr_from_c(addr, socket_len as i32)
    }

    pub fn get_data(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(mem::transmute(&(*self.packet).bytes), (*self.packet).length)
        }
    }
}

impl Drop for StatelessPacket {
    fn drop(&mut self) {
        unsafe {
            picoquic_delete_stateless_packet(self.packet);
        }
    }
}

pub struct StatelessPacketIter<'a> {
    quic: *mut picoquic_quic_t,
    _marker: PhantomData<&'a i32>,
}

impl<'a> StatelessPacketIter<'a> {
    pub fn new(quic: *mut picoquic_quic_t) -> StatelessPacketIter<'a> {
        StatelessPacketIter {
            quic,
            _marker: Default::default(),
        }
    }
}

impl<'a> Iterator for StatelessPacketIter<'a> {
    type Item = StatelessPacket;

    fn next(&mut self) -> Option<Self::Item> {
        let res = unsafe { picoquic_dequeue_stateless_packet(self.quic) };
        if res.is_null() {
            None
        } else {
            Some(StatelessPacket::new(res))
        }
    }
}