elaeis4/tarpaulin-report.html

660 lines
350 KiB
HTML

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>html, body {
margin: 0;
padding: 0;
}
.app {
margin: 10px;
padding: 0;
}
.files-list {
margin: 10px 0 0;
width: 100%;
border-collapse: collapse;
}
.files-list__head {
border: 1px solid #999;
}
.files-list__head > tr > th {
padding: 10px;
border: 1px solid #999;
text-align: left;
font-weight: normal;
background: #ddd;
}
.files-list__body {
}
.files-list__file {
cursor: pointer;
}
.files-list__file:hover {
background: #ccf;
}
.files-list__file > td {
padding: 10px;
border: 1px solid #999;
}
.files-list__file > td:first-child::before {
content: '\01F4C4';
margin-right: 1em;
}
.files-list__file_low {
background: #fcc;
}
.files-list__file_medium {
background: #ffc;
}
.files-list__file_high {
background: #cfc;
}
.files-list__file_folder > td:first-child::before {
content: '\01F4C1';
margin-right: 1em;
}
.file-header {
border: 1px solid #999;
display: flex;
justify-content: space-between;
align-items: center;
}
.file-header__back {
margin: 10px;
cursor: pointer;
flex-shrink: 0;
flex-grow: 0;
text-decoration: underline;
color: #338;
}
.file-header__name {
margin: 10px;
flex-shrink: 2;
flex-grow: 2;
}
.file-header__stat {
margin: 10px;
flex-shrink: 0;
flex-grow: 0;
}
.file-content {
margin: 10px 0 0;
border: 1px solid #999;
padding: 10px;
}
.code-line {
margin: 0;
padding: 0.3em;
height: 1em;
}
.code-line_covered {
background: #cfc;
}
.code-line_uncovered {
background: #fcc;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
var data = {"files":[{"path":["/","home","core","prj","e3t","elaeis4","quicktap","build.rs"],"content":"fn main() {\n build_info_build::build_script();\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","device","mod.rs"],"content":"//! A high-level implementation of the `WireGuard` protocol; does everything the kernel module does except for interfacing with the networking interfaces.\n//! Use the appropriate glue layer in `quicktap::drivers` to provide the tun/tap interface, and the mechanism in `quicktap::drivers::udp_listener` for working with the `UdpSocket`.","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","error.rs"],"content":"//! Defines the error type for the glue layer\nuse std::error::Error;\nuse std::fmt::{Display, Formatter};\n\n#[derive(Debug)]\n#[allow(clippy::module_name_repetitions)]\n/// Represents an error in the driver (glue) portion of quicktap\npub enum DriverError {\n /// An invalid packet type has been received on the interface, and quicktap does not know how to process it\n /// This is raised in the PREENTRY stage of packet processing\n InvalidPacketTypeRecvOnInterface\n}\nimpl Error for DriverError {}\nimpl Display for DriverError {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n match self {\n Self::InvalidPacketTypeRecvOnInterface =\u003e write!(f, \"Invalid packet type received on interface\")\n }\n }\n}","traces":[{"line":15,"address":[440608],"length":1,"stats":{"Line":0},"fn_name":"fmt"},{"line":17,"address":[440627],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":2},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","linux.rs"],"content":"//! A Linux implementation of the traits from `drivers::tungeneric`\n\nuse std::error::Error;\nuse std::io;\nuse std::io::{Read, Write};\n\nuse etherparse::IpHeader;\nuse tun::platform::Device;\n\nuse crate::drivers::tungeneric::{GenericDriver, GenericInterface, TunPacket};\n\n#[allow(clippy::module_name_repetitions)]\n/// Represents the internal state of a tun driver.\npub struct TunDevice {\n /// Contains the device handle of the tun device\n device: Device,\n /// A packet read buffer\n read_buf: [u8; 4096],\n /// Currently unused, for storing the offset into the read buffer to write to\n read_offset: usize,\n /// Another packet read buffer\n packet_buf: [u8; 4096],\n}\nimpl GenericDriver for TunDevice {\n fn new(config: \u0026GenericInterface) -\u003e Result\u003cSelf, Box\u003cdyn Error\u003e\u003e {\n let mut device_config = tun::Configuration::default();\n\n for address in \u0026config.addresses {\n device_config.address(address.address()).netmask(address.mask());\n }\n\n device_config.name(\u0026config.name);\n if let Some(mtu) = config.mtu {\n device_config.mtu(mtu);\n }\n let device = tun::create(\u0026device_config)?;\n device.set_nonblock()?;\n\n Ok(Self {\n device,\n read_buf: [0u8; 4096],\n read_offset: 0,\n packet_buf: [0u8; 4096],\n })\n }\n\n fn read(\u0026mut self) -\u003e Result\u003cTunPacket, io::Error\u003e {\n self.packet_buf = [0u8; 4096];\n let _ = self.device.read(\u0026mut self.packet_buf)?;\n let ip_header = IpHeader::from_slice(\u0026self.packet_buf);\n if let Ok((packet_header, _, _)) = ip_header {\n // Found a packet. Clear read buffers\n self.read_offset = 0;\n self.read_buf = [0u8; 4096];\n return Ok(TunPacket {\n header: packet_header,\n packet: self.packet_buf,\n })\n }\n\n Err(io::Error::new(io::ErrorKind::WouldBlock, \"No packets detected yet\"))\n }\n\n fn clear(\u0026mut self) {\n self.read_buf = [0u8; 4096];\n self.read_offset = 0;\n }\n\n fn write(\u0026mut self, packet: TunPacket) -\u003e Result\u003c(), io::Error\u003e {\n let _ = self.device.write(\u0026packet.packet)?;\n Ok(())\n }\n}\n\n","traces":[{"line":25,"address":[1557262,1556064],"length":1,"stats":{"Line":0},"fn_name":"new"},{"line":26,"address":[1556100],"length":1,"stats":{"Line":0},"fn_name":null},{"line":28,"address":[1556187,1556290,1556115],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[1556311],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[1556270],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[1556417],"length":1,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[1556441,1556481],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[1556483,1556698,1556457],"length":1,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[1556666,1556914,1557179],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[513937],"length":1,"stats":{"Line":0},"fn_name":null},{"line":40,"address":[513871],"length":1,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[1556997],"length":1,"stats":{"Line":0},"fn_name":null},{"line":43,"address":[1557017],"length":1,"stats":{"Line":0},"fn_name":null},{"line":47,"address":[1557312,1557900],"length":1,"stats":{"Line":0},"fn_name":"read"},{"line":48,"address":[1557356],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[1557486,1557380],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[1557456],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[1557527],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[1557586],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[514489],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[514561],"length":1,"stats":{"Line":0},"fn_name":null},{"line":56,"address":[514505],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[514536],"length":1,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[514765,514679],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[514832],"length":1,"stats":{"Line":0},"fn_name":"clear"},{"line":65,"address":[514846],"length":1,"stats":{"Line":0},"fn_name":null},{"line":66,"address":[514867],"length":1,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[514880],"length":1,"stats":{"Line":0},"fn_name":"write"},{"line":70,"address":[514895,514971],"length":1,"stats":{"Line":0},"fn_name":null},{"line":71,"address":[514960],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":30},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","mod.rs"],"content":"//! Cross-platform tun/tap drivers for various platforms.\n\n#[cfg(unix)]\n#[path = \"linux.rs\"]\npub mod tun; // Tun/tap drivers for Linux\n\npub mod tungeneric;\n\npub mod udp_listener;\npub mod error;\n\n#[cfg(test)]\npub mod tests;","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // we want to panic, this is a test file\n#![allow(clippy::missing_errors_doc)]\n#![allow(clippy::missing_panics_doc)]\n#![allow(clippy::missing_safety_doc)]\n\nuse crate::drivers::error::DriverError;\n\n#[cfg(test)]\npub fn error_tests() {\n assert_eq!(format!(\"{}\", DriverError::InvalidPacketTypeRecvOnInterface), \"Invalid packet type received on interface\".to_string());\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","tungeneric.rs"],"content":"//! Generic traits and modules to represent a tun/tap device\n\nuse std::error::Error;\nuse std::io;\n\nuse cidr::IpInet;\nuse etherparse::IpHeader;\n\n#[derive(Debug)]\n/// A parsed packet from an interface\npub struct TunPacket {\n /// The parsed IPv4 or IPv6 header\n pub header: IpHeader,\n /// The raw packet data\n pub packet: [u8; 4096]\n}\n\n/// A trait to implement R/W on a tun driver\npub trait GenericDriver {\n /// Create a new device with the provided generic interface configuration\n /// # Errors\n /// This function may error if there is an error creating the device.\n fn new(config: \u0026GenericInterface) -\u003e Result\u003cSelf, Box\u003cdyn Error\u003e\u003e where Self: Sized;\n\n /// Attempt to read a packet from the interface. If no packet is found, append it to an internal buffer and return `WouldBlock`.\n /// Upon finding a successful packet inside the internal buffer, or the .clear() method being called, the internal buffer will be cleared.\n /// # Errors\n /// This function will return `WouldBlock` if a packet could not be read. This function may error if there is an error reading the interface.\n fn read(\u0026mut self) -\u003e Result\u003cTunPacket, io::Error\u003e;\n\n /// Clear any internal state of this interface.\n fn clear(\u0026mut self);\n\n /// Attempt to write a packet to the interface.\n /// # Errors\n /// This function will error if an error occured writing to the device.\n fn write(\u0026mut self, packet: TunPacket) -\u003e Result\u003c(), io::Error\u003e;\n}\n\n/// Generic interface config\npub struct GenericInterface {\n /// The ipv4/ipv6 addresses to be assigned to the interface\n pub addresses: Vec\u003cIpInet\u003e,\n /// The mtu to be assigned to the interface\n pub mtu: Option\u003ci32\u003e,\n /// The name of the virtual interface\n pub name: String\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","udp_listener.rs"],"content":"//! The logic for the WireGuard UDP socket.\n\nuse std::error::Error;\nuse std::io;\nuse std::net::UdpSocket;\nuse crate::drivers::error::DriverError;\nuse crate::stack::entry::PacketEntryStage;\nuse crate::stack::PacketProcessingStage;\n\n/// The maximum amount of bytes that can be taken up by a Handshake Initiation packet.\npub const MSG1_MAX_BYTES: usize = 148;\n/// The maximum amount of bytes that can be taken up by a Handshake Response packet.\npub const MSG2_MAX_BYTES: usize = 92;\n/// The maximum amount of bytes that can be taken up by a data packet.\npub const MSGDATA_MAX_BYTES: usize = 65567;\n/// The maximum amount of bytes that can be taken up by a cookie reply packet.\npub const MSGCOOKIE_MAX_BYTES: usize = 64;\n\n/// Represents the result of a socket processing round\npub enum SocketRoundResult {\n /// Represents that an io-specific error was received\n IoError(io::Error),\n /// Represents that a non-io-specific error was received\n GenericAnyError(Box\u003cdyn Error\u003e)\n}\n\n/// Run a socket update round on the (nonblocking!) UDP socket provided. Checks for any packets that may be present and send them off to get processed.\n/// **Warning!** This only runs *one* update round - therefore only one packet will be processed if any are present.\n/// If you're writing a frontend, this is probably not what you want. Use `qtap_socket_rounds_until_empty` instead.\n/// # Errors\n/// This function will error if a socket read fails or the processing of the packet fails. See `PacketEntryStage::process_packet()` for more details on packet processing.\npub fn qtap_socket_round(socket: \u0026mut UdpSocket) -\u003e Result\u003c(), SocketRoundResult\u003e {\n let mut packet_id = [0u8; 1];\n match socket.peek(\u0026mut packet_id) {\n Ok(_) =\u003e (),\n Err(e) =\u003e return Err(SocketRoundResult::IoError(e))\n }; // Intentionally peek into a 1-byte vector. This will NOT remove the datagram from the queue.\n // We WANT to discard the rest of the packet; right now we only care about the first byte so we know how much memory we need to allocate for the buffer.\n // The packet type tells us this.\n\n let buf_size = match packet_id[0] {\n 1 =\u003e MSG1_MAX_BYTES,\n 2 =\u003e MSG2_MAX_BYTES,\n 4 =\u003e MSGDATA_MAX_BYTES,\n 3 =\u003e MSGCOOKIE_MAX_BYTES,\n _ =\u003e return Err(SocketRoundResult::GenericAnyError(DriverError::InvalidPacketTypeRecvOnInterface.into()))\n };\n\n let mut packet_buf = vec![0u8; buf_size];\n let (read_bytes, from) = match socket.recv_from(\u0026mut packet_buf) {\n Ok(r) =\u003e r,\n Err(e) =\u003e return Err(SocketRoundResult::IoError(e))\n };\n\n let packet = packet_buf[..read_bytes].to_vec();\n\n match PacketEntryStage::process_packet(packet, \u0026from) {\n Ok(_) =\u003e Ok(()),\n Err(e) =\u003e Err(SocketRoundResult::GenericAnyError(e))\n }\n}\n\n/// Run several socket update rounds on the (nonblocking!) UDP socket provided. Will continually call `qtap_socket_round` in a loop until `io::WouldBlock` is returned.\n/// **Warning!** This runs as many socket rounds are needed to clear the UDP datagram queue. If there is a long queue, this function will take a very long time.\n/// If you only want to run one update, use `qtap_socket_round` instead.\n/// # Errors\n/// See `qtap_socket_round`\npub fn qtap_socket_rounds_until_empty(socket: \u0026mut UdpSocket) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n loop {\n match qtap_socket_round(socket) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n match e {\n SocketRoundResult::IoError(e) if matches!(e.kind(), io::ErrorKind::WouldBlock) =\u003e break,\n SocketRoundResult::GenericAnyError(e) =\u003e return Err(e),\n SocketRoundResult::IoError(e) =\u003e return Err(e.into())\n }\n }\n }\n }\n Ok(())\n}","traces":[{"line":32,"address":[418219,417296],"length":1,"stats":{"Line":0},"fn_name":"qtap_socket_round"},{"line":33,"address":[417326],"length":1,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[417348],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[417429],"length":1,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[417385],"length":1,"stats":{"Line":0},"fn_name":null},{"line":42,"address":[417517],"length":1,"stats":{"Line":0},"fn_name":null},{"line":43,"address":[417531],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[417545],"length":1,"stats":{"Line":0},"fn_name":null},{"line":45,"address":[417559],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[417588,417500],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[417640],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[417895,417663,417751],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[417799],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[417996],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[418100,417943],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[418107,418245],"length":1,"stats":{"Line":0},"fn_name":null},{"line":58,"address":[418252],"length":1,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[418266],"length":1,"stats":{"Line":0},"fn_name":null},{"line":68,"address":[418368,418780,418749],"length":1,"stats":{"Line":0},"fn_name":"qtap_socket_rounds_until_empty"},{"line":69,"address":[418421,418385],"length":1,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[418395],"length":1,"stats":{"Line":0},"fn_name":null},{"line":72,"address":[418423],"length":1,"stats":{"Line":0},"fn_name":null},{"line":73,"address":[418438],"length":1,"stats":{"Line":0},"fn_name":null},{"line":74,"address":[418585,418460,418654],"length":1,"stats":{"Line":0},"fn_name":null},{"line":75,"address":[418484],"length":1,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[418727,418619],"length":1,"stats":{"Line":0},"fn_name":null},{"line":81,"address":[418690],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":27},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","lib.rs"],"content":"//! A simple, almost pure-rust, cross-platform `WireGuard` implementation.\n//! Designed to function similarly to boringtun, this crate has modules for cross-platform device drivers, the `Noise_IKpsk2` handshake, and cryptography constructs required for the above.\n\n#![deny(missing_docs)]\n\n#![warn(clippy::pedantic)]\n#![warn(clippy::nursery)]\n#![deny(clippy::unwrap_used)]\n#![deny(clippy::expect_used)]\n\n// This is an annoyance\n#![allow(clippy::must_use_candidate)]\n#![allow(clippy::module_name_repetitions)]\n\npub use cidr;\n\npub mod drivers;\npub mod qcrypto;\npub mod noise;\npub mod stack;\npub mod device;\n\n#[cfg(test)]\npub mod tests;\n\n/// Gets the compile-time versioning information for the engine build.\npub const fn version() -\u003e \u0026'static str {\n build_info::format!(\"quicktap engine v{} ({}) built at {} with {}\", $.crate_info.version, $.version_control.unwrap().git().unwrap().commit_short_id, $.timestamp, $.compiler)\n}\n","traces":[{"line":27,"address":[506720],"length":1,"stats":{"Line":1},"fn_name":"version"}],"covered":1,"coverable":1},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","data.rs"],"content":"//! `WireGuard` transport data messages. see 5.4.6\n\nuse crate::noise::error::{NoiseError, NoisePacketParseError};\nuse crate::noise::handshake::HandshakeState;\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt};\n\nfn pad_packet(p: \u0026Vec\u003cu8\u003e) -\u003e Vec\u003cu8\u003e {\n let mut padded = p.clone();\n padded.append(\u0026mut vec![0u8; 16 - (p.len() % 16)]);\n padded\n}\nfn unpad_packet(p: \u0026[u8]) -\u003e Vec\u003cu8\u003e {\n p.iter().rev().skip_while(|x| **x == 0).copied().collect::\u003cVec\u003cu8\u003e\u003e()\n}\n\n/// Given any arbitrary IP packet, pad and encrypt it with the current handshake state.\n/// # Errors\n/// This function will error if the encryption step is unsuccessful.\npub fn encapsulate(state: \u0026mut HandshakeState, packet: \u0026Vec\u003cu8\u003e) -\u003e Result\u003cVec\u003cu8\u003e, NoiseError\u003e {\n let packet = pad_packet(packet);\n let counter = state.n_send + 1;\n let packet_data = match qcrypto_aead(\u0026state.t_send, state.n_send + 1, \u0026packet, \u0026[]) {\n Ok(d) =\u003e d,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n let i_other = if state.we_are_initiator { state.i_r } else { state.i_i };\n\n let mut res = vec![4u8; 16 + packet_data.len()];\n res[1..4].copy_from_slice(\u0026[0u8; 3]);\n res[4..8].copy_from_slice(\u0026i_other.to_le_bytes());\n res[8..16].copy_from_slice(\u0026counter.to_le_bytes());\n res[16..16+packet_data.len()].copy_from_slice(\u0026packet_data);\n\n state.n_send += 1;\n\n Ok(res)\n}\n\n/// Given an encrypted, encapsulated IP packet, decrypt and unpad it with the current handshake state.\n/// # Errors\n/// This function will error if the decryption step is unsuccessful.\n/// # Panics\n/// This function, while containing unwraps for type conversions, is safe and will never panic.\n#[allow(clippy::unwrap_used)]\npub fn deencapsulate(state: \u0026mut HandshakeState, packet: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, NoiseError\u003e {\n if packet[0] != 4u8 {\n return Err(NoiseError::PacketParseError(NoisePacketParseError::WrongPacketType(4, packet[0] as usize)))\n }\n if packet[1..4] != [0u8; 3] {\n return Err(NoiseError::PacketParseError(NoisePacketParseError::MissingReserved))\n }\n let index_me = if state.we_are_initiator { state.i_i } else { state.i_r };\n if packet[4..8] != index_me.to_le_bytes() {\n return Err(NoiseError::PacketParseError(NoisePacketParseError::WrongIndex(index_me as usize, usize::from_le_bytes(packet[4..8].try_into().unwrap()))))\n }\n let counter = u64::from_le_bytes(packet[8..16].try_into().unwrap());\n\n if !state.bitfield.check_replay_window(counter) {\n // this packet is not okay! replayed or too old\n return Err(NoiseError::PacketReplayed)\n }\n\n let packet = match qcrypto_aead_decrypt(\u0026state.t_recv, counter, \u0026packet[16..], \u0026[]) {\n Ok(p) =\u003e p,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n state.bitfield.update_replay_window(counter);\n state.n_recv = counter;\n\n Ok(unpad_packet(\u0026packet))\n}","traces":[{"line":7,"address":[483744,483975,483996],"length":1,"stats":{"Line":1},"fn_name":"pad_packet"},{"line":8,"address":[483771],"length":1,"stats":{"Line":1},"fn_name":null},{"line":9,"address":[483834,483782],"length":1,"stats":{"Line":2},"fn_name":null},{"line":12,"address":[484016],"length":1,"stats":{"Line":1},"fn_name":"unpad_packet"},{"line":13,"address":[1606797,1606784],"length":1,"stats":{"Line":3},"fn_name":"{closure#0}"},{"line":19,"address":[484176,485942,485972],"length":1,"stats":{"Line":1},"fn_name":"encapsulate"},{"line":20,"address":[484242],"length":1,"stats":{"Line":1},"fn_name":null},{"line":21,"address":[484353,484263],"length":1,"stats":{"Line":1},"fn_name":null},{"line":22,"address":[484310,484429],"length":1,"stats":{"Line":2},"fn_name":null},{"line":23,"address":[484591],"length":1,"stats":{"Line":1},"fn_name":null},{"line":24,"address":[484706],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[484799,484687],"length":1,"stats":{"Line":1},"fn_name":null},{"line":29,"address":[484910,484843],"length":1,"stats":{"Line":2},"fn_name":null},{"line":30,"address":[485128,484990],"length":1,"stats":{"Line":2},"fn_name":null},{"line":31,"address":[485158],"length":1,"stats":{"Line":1},"fn_name":null},{"line":32,"address":[485358],"length":1,"stats":{"Line":1},"fn_name":null},{"line":33,"address":[485548],"length":1,"stats":{"Line":1},"fn_name":null},{"line":35,"address":[485909,485782],"length":1,"stats":{"Line":1},"fn_name":null},{"line":37,"address":[485827],"length":1,"stats":{"Line":1},"fn_name":null},{"line":46,"address":[486000,487921],"length":1,"stats":{"Line":1},"fn_name":"deencapsulate"},{"line":47,"address":[486071],"length":1,"stats":{"Line":1},"fn_name":null},{"line":48,"address":[486228,486397],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[486146,486451],"length":1,"stats":{"Line":2},"fn_name":null},{"line":51,"address":[486514],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[486630,486491],"length":1,"stats":{"Line":2},"fn_name":null},{"line":54,"address":[486682],"length":1,"stats":{"Line":1},"fn_name":null},{"line":55,"address":[486922],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[486838,487236],"length":1,"stats":{"Line":2},"fn_name":null},{"line":59,"address":[487334],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[487445],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[487381,487525],"length":1,"stats":{"Line":2},"fn_name":null},{"line":65,"address":[487593],"length":1,"stats":{"Line":1},"fn_name":null},{"line":66,"address":[487676],"length":1,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[487657],"length":1,"stats":{"Line":1},"fn_name":null},{"line":70,"address":[487793],"length":1,"stats":{"Line":1},"fn_name":null},{"line":72,"address":[487797],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":30,"coverable":36},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","error.rs"],"content":"//! `Noise_IKpsk2` handshake errors\n#![allow(clippy::module_name_repetitions)]\n\nuse std::error::Error;\nuse std::fmt::{Display, Formatter};\n\n/// Represents a error while doing Noise handshake operations\n#[derive(Debug, Clone)]\npub enum NoiseError {\n /// Represents an error while parsing a Noise packet\n PacketParseError(NoisePacketParseError),\n /// Represents an opaque error from ChaCha\n ChaCha20Error(chacha20poly1305::Error),\n /// Represents that the packet had a missing or incorrect cookie MAC.\n PacketUnauthenticated,\n /// Represents that the packet had the wrong i_i value\n UnrelatedHandshakePacket,\n /// Represents that the packet has been replayed and should be dropped\n PacketReplayed\n}\nimpl Error for NoiseError {}\nimpl Display for NoiseError {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n match \u0026self {\n Self::PacketParseError(err) =\u003e write!(f, \"{}\", err),\n Self::ChaCha20Error(error) =\u003e write!(f, \"Encryption error: {}\", error),\n Self::PacketUnauthenticated =\u003e write!(f, \"Unauthenticated packet\"),\n Self::UnrelatedHandshakePacket =\u003e write!(f, \"Unrelated handshake packet\"),\n Self::PacketReplayed =\u003e write!(f, \"Packet was replayed\")\n }\n }\n}\n\n/// Represents and error while parsing a Noise packet\n#[derive(Debug, Clone)]\npub enum NoisePacketParseError {\n /// Represents an invalid packet length while parsing a packet. The first was the expected length, the second was the actual length\n InvalidLength(usize, usize),\n /// Represents that the packet being parsed is of the incorrect type. The first value is the expected packet type, the second was the actual packet type\n WrongPacketType(usize, usize),\n /// Represents that the expected 3 bytes of reserved space are missing\n MissingReserved,\n /// Represents that the index expected to be present on the message is incorrect\n WrongIndex(usize, usize),\n /// Indicates that this packet has been replayed and should be ignored.\n ReplayAttack,\n}\nimpl Display for NoisePacketParseError {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n match \u0026self {\n Self::InvalidLength(expected, got) =\u003e write!(f, \"Invalid packet length: expected {} got {}\", expected, got),\n Self::WrongPacketType(expected, got) =\u003e write!(f, \"Incorrect packet type: expected {} got {}\", expected, got),\n Self::MissingReserved =\u003e write!(f, \"Missing reserved bytes\"),\n Self::WrongIndex(expected, got) =\u003e write!(f, \"Incorrect session index: expected {} got {}\", expected, got),\n Self::ReplayAttack =\u003e write!(f, \"!!! !!! THIS PACKET HAS BEEN REPLAYED !!! !!! Something fishy is going on.\")\n }\n }\n}","traces":[{"line":23,"address":[429440],"length":1,"stats":{"Line":0},"fn_name":"fmt"},{"line":24,"address":[429465],"length":1,"stats":{"Line":0},"fn_name":null},{"line":25,"address":[429522,429913],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[429820,429557],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[429789,429597],"length":1,"stats":{"Line":0},"fn_name":null},{"line":28,"address":[429639,429762],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[429678],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[429984],"length":1,"stats":{"Line":0},"fn_name":"fmt"},{"line":50,"address":[430009],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[430668,430045],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[430108,430525],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[430171,430500],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[430213,430352],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[430273],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":14},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","initiator.rs"],"content":"//! `Noise_IKpsk2` handshake initiator packets\n\nuse rand::{Rng, thread_rng};\nuse x25519_dalek::PublicKey;\n\nuse crate::noise::error::NoiseError;\nuse crate::noise::handshake::{HANDSHAKE_INITIATOR_CHAIN_KEY, HANDSHAKE_INITIATOR_CHAIN_KEY_HASH, HandshakeState, needs_cookie};\nuse crate::qcrypto::{LABEL_MAC1, timestamp};\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt};\nuse crate::qcrypto::hashes::{qcrypto_hash_twice, qcrypto_mac};\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm};\n\nstruct HandshakeInitiatorRaw {\n sender: [u8; 4],\n ephemeral: [u8; 32],\n static_pub: [u8; 32 + 16],\n timestamp: [u8; 12 + 16],\n mac1: [u8; 16],\n mac2: [u8; 16]\n}\nimpl HandshakeInitiatorRaw {\n fn to_bytes(\u0026self, session: \u0026HandshakeState) -\u003e [u8; 148] {\n let mut output = [0u8; 148];\n\n output[0] = 1u8;\n output[4..8].copy_from_slice(\u0026self.sender);\n output[8..40].copy_from_slice(\u0026self.ephemeral);\n output[40..88].copy_from_slice(\u0026self.static_pub);\n output[88..116].copy_from_slice(\u0026self.timestamp);\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026output[..116]);\n\n output[116..132].copy_from_slice(\u0026mac1);\n\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026output[..132]) } else { [0u8; 16] };\n\n output[132..148].copy_from_slice(\u0026mac2);\n\n output\n }\n\n #[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways\n fn from_bytes(bytes: [u8; 148]) -\u003e Self {\n Self {\n sender: bytes[4..8].try_into().unwrap(),\n ephemeral: bytes[8..40].try_into().unwrap(),\n static_pub: bytes[40..88].try_into().unwrap(),\n timestamp: bytes[88..116].try_into().unwrap(),\n mac1: bytes[116..132].try_into().unwrap(),\n mac2: bytes[132..148].try_into().unwrap()\n }\n }\n}\n\n/// Generate a handshake initiator packet and encrypt it using the given session state, starting a new handshake state\n/// # Errors\n/// This function will error if encryption was unsuccessful\n/// # Panics\n/// While containing unwraps, this function will never panic.\n#[allow(clippy::module_name_repetitions)]\n#[allow(clippy::unwrap_used)] // Safe because it is only used for type conversions in known safe ways\npub fn generate_handshake_init(session: \u0026mut HandshakeState) -\u003e Result\u003c[u8; 148], NoiseError\u003e {\n session.we_are_initiator = true;\n session.s_pub_i = PublicKey::from(session.s_priv_me);\n session.s_pub_r = session.s_pub_them;\n\n session.i_i = thread_rng().gen();\n\n let mut msg = HandshakeInitiatorRaw {\n sender: session.i_i.to_le_bytes(),\n ephemeral: [0u8; 32],\n static_pub: [0u8; 32 + 16],\n timestamp: [0u8; 12 + 16],\n mac1: [0u8; 16],\n mac2: [0u8; 16]\n };\n\n session.ck = HANDSHAKE_INITIATOR_CHAIN_KEY;\n session.h = HANDSHAKE_INITIATOR_CHAIN_KEY_HASH;\n session.h = qcrypto_hash_twice(\u0026session.h, session.s_pub_r.as_bytes());\n\n let eph_keypair = qcrypto_dh_generate_longterm();\n\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, eph_keypair.1.as_bytes())[0];\n session.e_pub_i = eph_keypair.1;\n session.e_priv_me = eph_keypair.0;\n\n msg.ephemeral = eph_keypair.1.to_bytes();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.ephemeral);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026session.ck, qcrypto_dh_longterm(\u0026session.e_priv_me, \u0026session.s_pub_r).as_bytes());\n session.ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n msg.static_pub = match qcrypto_aead(\u0026k, 0, session.s_pub_i.as_bytes(), \u0026session.h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }.try_into().unwrap();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.static_pub);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026session.ck, qcrypto_dh_longterm(session.s_priv_me, \u0026session.s_pub_r).as_bytes());\n session.ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n msg.timestamp = match qcrypto_aead(\u0026k, 0, \u0026timestamp().to_bytes(), \u0026session.h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }.try_into().unwrap();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.timestamp);\n\n Ok(msg.to_bytes(session))\n}\n\n/// Parse a handshake initiator packet and encrypt it using the given session state, updating the session state with decrypted and authenticated values\n/// # Errors\n/// This function will error if decryption was unsuccessful\n/// # Panics\n/// While containing unwraps, this function will never panic.\n#[allow(clippy::module_name_repetitions)]\n#[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways\npub fn parse_handshake_init(session: \u0026mut HandshakeState, packet: [u8; 148]) -\u003e Result\u003c(), NoiseError\u003e {\n let s_pub_i = session.s_pub_them;\n let s_pub_r = PublicKey::from(session.s_priv_me);\n\n let msg = HandshakeInitiatorRaw::from_bytes(packet);\n\n let i_i = u32::from_le_bytes(msg.sender);\n\n let ck = HANDSHAKE_INITIATOR_CHAIN_KEY;\n let h = HANDSHAKE_INITIATOR_CHAIN_KEY_HASH;\n let h = qcrypto_hash_twice(\u0026h, s_pub_r.as_bytes());\n\n let ephemeral_public = msg.ephemeral;\n let eph_pub = PublicKey::from(ephemeral_public);\n let e_pub_i = eph_pub;\n\n let ck = qcrypto_hkdf::\u003c1\u003e(\u0026ck, eph_pub.as_bytes())[0];\n\n let h = qcrypto_hash_twice(\u0026h, \u0026msg.ephemeral);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026ck, qcrypto_dh_longterm(session.s_priv_me, \u0026eph_pub).as_bytes());\n let ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n\n\n session.s_pub_i = PublicKey::from(\u003cVec\u003cu8\u003e as TryInto\u003c[u8; 32]\u003e\u003e::try_into(match qcrypto_aead_decrypt(\u0026k, 0, \u0026msg.static_pub, \u0026h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }).unwrap());\n\n let h = qcrypto_hash_twice(\u0026h, \u0026msg.static_pub);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026ck, qcrypto_dh_longterm(session.s_priv_me, \u0026session.s_pub_i).as_bytes());\n let ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n let _sent_timestamp: [u8; 12] = match qcrypto_aead_decrypt(\u0026k, 0, \u0026msg.timestamp, \u0026h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }.try_into().unwrap();\n\n let h = qcrypto_hash_twice(\u0026h, \u0026msg.timestamp);\n\n // we need to check mac1 and mac2\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026packet[..116]);\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026packet[..132]) } else { [0u8; 16] };\n\n if mac1 != msg.mac1 || mac2 != msg.mac2 {\n return Err(NoiseError::PacketUnauthenticated)\n }\n\n session.h = h;\n session.ck = ck;\n session.e_pub_i = e_pub_i;\n session.s_pub_i = s_pub_i;\n session.s_pub_r = s_pub_r;\n session.i_i = i_i;\n session.we_are_initiator = false;\n\n Ok(())\n}","traces":[{"line":23,"address":[474096],"length":1,"stats":{"Line":1},"fn_name":"to_bytes"},{"line":24,"address":[474154],"length":1,"stats":{"Line":2},"fn_name":null},{"line":26,"address":[474174],"length":1,"stats":{"Line":1},"fn_name":null},{"line":27,"address":[474177],"length":1,"stats":{"Line":1},"fn_name":null},{"line":28,"address":[474295],"length":1,"stats":{"Line":2},"fn_name":null},{"line":29,"address":[474417],"length":1,"stats":{"Line":1},"fn_name":null},{"line":30,"address":[474539],"length":1,"stats":{"Line":2},"fn_name":null},{"line":32,"address":[474737],"length":1,"stats":{"Line":1},"fn_name":null},{"line":34,"address":[474885],"length":1,"stats":{"Line":2},"fn_name":null},{"line":36,"address":[474991],"length":1,"stats":{"Line":1},"fn_name":null},{"line":38,"address":[475254],"length":1,"stats":{"Line":1},"fn_name":null},{"line":44,"address":[475376],"length":1,"stats":{"Line":2},"fn_name":"from_bytes"},{"line":46,"address":[475406],"length":1,"stats":{"Line":1},"fn_name":null},{"line":47,"address":[475598],"length":1,"stats":{"Line":2},"fn_name":null},{"line":48,"address":[475716],"length":1,"stats":{"Line":1},"fn_name":null},{"line":49,"address":[475834],"length":1,"stats":{"Line":2},"fn_name":null},{"line":50,"address":[475952],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[476072],"length":1,"stats":{"Line":2},"fn_name":null},{"line":63,"address":[476384,476739],"length":1,"stats":{"Line":1},"fn_name":"generate_handshake_init"},{"line":64,"address":[476417],"length":1,"stats":{"Line":2},"fn_name":null},{"line":65,"address":[476432],"length":1,"stats":{"Line":1},"fn_name":null},{"line":66,"address":[476514],"length":1,"stats":{"Line":2},"fn_name":null},{"line":68,"address":[476634],"length":1,"stats":{"Line":1},"fn_name":null},{"line":71,"address":[476770],"length":1,"stats":{"Line":2},"fn_name":null},{"line":72,"address":[476802],"length":1,"stats":{"Line":1},"fn_name":null},{"line":73,"address":[476822],"length":1,"stats":{"Line":2},"fn_name":null},{"line":74,"address":[476842],"length":1,"stats":{"Line":1},"fn_name":null},{"line":75,"address":[476862],"length":1,"stats":{"Line":2},"fn_name":null},{"line":76,"address":[476882],"length":1,"stats":{"Line":1},"fn_name":null},{"line":79,"address":[477141],"length":1,"stats":{"Line":2},"fn_name":null},{"line":80,"address":[477197],"length":1,"stats":{"Line":1},"fn_name":null},{"line":81,"address":[477253],"length":1,"stats":{"Line":2},"fn_name":null},{"line":83,"address":[477381],"length":1,"stats":{"Line":1},"fn_name":null},{"line":85,"address":[477503,477407],"length":1,"stats":{"Line":3},"fn_name":null},{"line":86,"address":[477580],"length":1,"stats":{"Line":2},"fn_name":null},{"line":87,"address":[477642],"length":1,"stats":{"Line":1},"fn_name":null},{"line":89,"address":[477827],"length":1,"stats":{"Line":2},"fn_name":null},{"line":91,"address":[477895],"length":1,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[477961],"length":1,"stats":{"Line":2},"fn_name":null},{"line":94,"address":[478129],"length":1,"stats":{"Line":1},"fn_name":null},{"line":95,"address":[478191],"length":1,"stats":{"Line":2},"fn_name":null},{"line":98,"address":[478510,478407,478223],"length":1,"stats":{"Line":4},"fn_name":null},{"line":99,"address":[478327],"length":1,"stats":{"Line":2},"fn_name":null},{"line":100,"address":[478419],"length":1,"stats":{"Line":0},"fn_name":null},{"line":101,"address":[478483],"length":1,"stats":{"Line":0},"fn_name":null},{"line":103,"address":[478601],"length":1,"stats":{"Line":1},"fn_name":null},{"line":105,"address":[478669],"length":1,"stats":{"Line":2},"fn_name":null},{"line":106,"address":[478830],"length":1,"stats":{"Line":1},"fn_name":null},{"line":107,"address":[478892],"length":1,"stats":{"Line":2},"fn_name":null},{"line":110,"address":[479247,478924,479136],"length":1,"stats":{"Line":4},"fn_name":null},{"line":111,"address":[479056],"length":1,"stats":{"Line":2},"fn_name":null},{"line":112,"address":[479148],"length":1,"stats":{"Line":0},"fn_name":null},{"line":113,"address":[479220],"length":1,"stats":{"Line":0},"fn_name":null},{"line":115,"address":[479322],"length":1,"stats":{"Line":1},"fn_name":null},{"line":117,"address":[479406],"length":1,"stats":{"Line":2},"fn_name":null},{"line":127,"address":[479488,480409],"length":1,"stats":{"Line":2},"fn_name":"parse_handshake_init"},{"line":128,"address":[479535],"length":1,"stats":{"Line":1},"fn_name":null},{"line":129,"address":[479595],"length":1,"stats":{"Line":2},"fn_name":null},{"line":131,"address":[479620],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[479659],"length":1,"stats":{"Line":1},"fn_name":null},{"line":135,"address":[479699],"length":1,"stats":{"Line":2},"fn_name":null},{"line":136,"address":[479759],"length":1,"stats":{"Line":1},"fn_name":null},{"line":137,"address":[479819],"length":1,"stats":{"Line":2},"fn_name":null},{"line":139,"address":[479878],"length":1,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[479942],"length":1,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[480028],"length":1,"stats":{"Line":1},"fn_name":null},{"line":143,"address":[480092],"length":1,"stats":{"Line":2},"fn_name":null},{"line":145,"address":[480215],"length":1,"stats":{"Line":1},"fn_name":null},{"line":147,"address":[480265],"length":1,"stats":{"Line":2},"fn_name":null},{"line":148,"address":[480435],"length":1,"stats":{"Line":1},"fn_name":null},{"line":149,"address":[480499],"length":1,"stats":{"Line":2},"fn_name":null},{"line":154,"address":[480563,480837,480743],"length":1,"stats":{"Line":4},"fn_name":null},{"line":155,"address":[480647],"length":1,"stats":{"Line":2},"fn_name":null},{"line":156,"address":[480774],"length":1,"stats":{"Line":0},"fn_name":null},{"line":159,"address":[480955],"length":1,"stats":{"Line":1},"fn_name":null},{"line":161,"address":[481007],"length":1,"stats":{"Line":2},"fn_name":null},{"line":162,"address":[481151],"length":1,"stats":{"Line":1},"fn_name":null},{"line":163,"address":[481215],"length":1,"stats":{"Line":2},"fn_name":null},{"line":166,"address":[481542,481459,481279],"length":1,"stats":{"Line":9},"fn_name":null},{"line":167,"address":[481363],"length":1,"stats":{"Line":3},"fn_name":null},{"line":168,"address":[481490],"length":1,"stats":{"Line":0},"fn_name":null},{"line":171,"address":[481570],"length":1,"stats":{"Line":3},"fn_name":null},{"line":175,"address":[481695],"length":1,"stats":{"Line":3},"fn_name":null},{"line":176,"address":[481840],"length":1,"stats":{"Line":3},"fn_name":null},{"line":178,"address":[482095],"length":1,"stats":{"Line":3},"fn_name":null},{"line":179,"address":[482883],"length":1,"stats":{"Line":0},"fn_name":null},{"line":182,"address":[482230],"length":1,"stats":{"Line":3},"fn_name":null},{"line":183,"address":[482354],"length":1,"stats":{"Line":3},"fn_name":null},{"line":184,"address":[482478],"length":1,"stats":{"Line":3},"fn_name":null},{"line":185,"address":[482602],"length":1,"stats":{"Line":3},"fn_name":null},{"line":186,"address":[482726],"length":1,"stats":{"Line":3},"fn_name":null},{"line":187,"address":[482850],"length":1,"stats":{"Line":3},"fn_name":null},{"line":188,"address":[482856],"length":1,"stats":{"Line":3},"fn_name":null},{"line":190,"address":[482863],"length":1,"stats":{"Line":3},"fn_name":null}],"covered":87,"coverable":94},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","mod.rs"],"content":"//! `Noise_IKpsk2` handshake, specifically the way `WireGuard` defines it\nuse std::fmt::{Debug, Formatter};\n\nuse rand::rngs::OsRng;\nuse tai64::Tai64N;\nuse x25519_dalek::{PublicKey, StaticSecret};\nuse crate::noise::rfc6479::ShiftWindow;\n\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::timestamp;\n\npub mod initiator;\npub mod response;\n\n#[cfg(test)]\npub mod tests;\n\n/// The Blake2s hash of the construction\npub const HANDSHAKE_INITIATOR_CHAIN_KEY: [u8; 32] = [\n 96, 226, 109, 174, 243, 39, 239, 192, 46, 195, 53, 226, 160, 37, 210, 208, 22, 235, 66, 6, 248,\n 114, 119, 245, 45, 56, 209, 152, 139, 120, 205, 54,\n];\n\n/// The hashed chaining key\npub const HANDSHAKE_INITIATOR_CHAIN_KEY_HASH: [u8; 32] = [\n 34, 17, 179, 97, 8, 26, 197, 102, 105, 18, 67, 219, 69, 138, 213, 50, 45, 156, 108, 102, 34,\n 147, 232, 183, 14, 225, 156, 101, 186, 7, 158, 243,\n];\n\n/// Represents a cookie we got from the other peer\n#[derive(Debug)]\npub struct Cookie {\n time: Tai64N,\n cookie: [u8; 16]\n}\n\n/// Represents the internal handshake state. This does not really need to be messed with by outside users\n#[allow(missing_docs)]\n#[allow(clippy::module_name_repetitions)]\npub struct HandshakeState\u003c'a\u003e {\n pub h: [u8; 32],\n pub ck: [u8; 32],\n\n pub e_pub_i: PublicKey,\n pub e_pub_r: PublicKey,\n\n pub s_pub_i: PublicKey,\n pub s_pub_r: PublicKey,\n\n pub e_priv_me: StaticSecret,\n pub s_priv_me: \u0026'a StaticSecret,\n pub s_pub_them: PublicKey,\n\n pub i_i: u32,\n pub i_r: u32,\n\n pub q: [u8; 32],\n\n pub cookies: Vec\u003cCookie\u003e,\n\n pub t_send: [u8; 32],\n pub t_recv: [u8; 32],\n\n pub n_send: u64,\n pub n_recv: u64,\n\n pub we_are_initiator: bool,\n\n pub bitfield: ShiftWindow\n}\nimpl\u003c'a\u003e HandshakeState\u003c'a\u003e {\n /// Determines if the state variables of this `HandshakeState` are the same as another\n #[allow(clippy::suspicious_operation_groupings)]\n pub fn is_eq(\u0026self, other: \u0026HandshakeState) -\u003e bool {\n self.h == other.h \u0026\u0026 self.ck == other.ck \u0026\u0026 self.e_pub_i == other.e_pub_i \u0026\u0026 self.s_pub_i == other.s_pub_i \u0026\u0026 self.s_pub_r == other.s_pub_r \u0026\u0026 self.i_i == other.i_i \u0026\u0026 self.i_r == other.i_r\n }\n\n /// Zeroes out handshake state and derives data transport keys. The handshake must be completed and the other party must do this at the same time otherwise the handshake will be trashed and you have to start over.\n pub fn derive_transport(\u0026mut self) {\n let t_send_recv = qcrypto_hkdf::\u003c2\u003e(\u0026self.ck, \u0026[]);\n if self.we_are_initiator {\n self.t_send = t_send_recv[0];\n self.t_recv = t_send_recv[1];\n } else {\n self.t_send = t_send_recv[1];\n self.t_recv = t_send_recv[0];\n }\n\n self.n_send = 0;\n self.n_recv = 0;\n\n self.e_pub_r = PublicKey::from([0u8; 32]);\n self.e_priv_me = StaticSecret::from([0u8; 32]);\n self.e_pub_i = PublicKey::from([0u8; 32]);\n self.ck = [0u8; 32];\n }\n\n /// Create a new handshake state representing a brand-new handshake.\n /// This function initializes the important values with their appropriate initialization vectors, and zeroes out all other values.\n pub fn new(private_key: \u0026'a StaticSecret, other_pubkey: PublicKey, pre_shared_key: Option\u003c[u8; 32]\u003e) -\u003e Self {\n Self {\n h: [0u8; 32],\n ck: [0u8; 32],\n e_pub_i: PublicKey::from([0u8; 32]),\n e_pub_r: PublicKey::from([0u8; 32]),\n s_pub_i: PublicKey::from([0u8; 32]),\n s_pub_r: PublicKey::from([0u8; 32]),\n e_priv_me: StaticSecret::new(OsRng),\n s_priv_me: private_key,\n s_pub_them: other_pubkey,\n i_i: 0,\n i_r: 0,\n q: pre_shared_key.unwrap_or([0u8; 32]),\n cookies: vec![],\n t_send: [0u8; 32],\n t_recv: [0u8; 32],\n n_send: 1,\n n_recv: 1,\n we_are_initiator: false,\n bitfield: ShiftWindow::new()\n }\n }\n}\nimpl\u003c'a\u003e Debug for HandshakeState\u003c'a\u003e {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n f.debug_struct(\"HandshakeState\")\n .field(\"h\", \u0026self.h)\n .field(\"ck\", \u0026self.ck)\n .field(\"e_pub_i\", \u0026self.e_pub_i)\n .field(\"s_pub_i\", \u0026self.s_pub_i)\n .field(\"s_pub_r\", \u0026self.s_pub_r)\n .field(\"s_pub_them\", \u0026self.s_pub_them)\n .field(\"i_i\", \u0026self.i_i)\n .field(\"i_r\", \u0026self.i_r)\n .field(\"cookies\", \u0026self.cookies).finish()\n }\n}\n\n/// Determines if a cookie MAC needs to be added to the packet being sent\npub fn needs_cookie(session: \u0026HandshakeState) -\u003e bool {\n if !session.cookies.is_empty() {\n let past_cookie_timeout = session.cookies[session.cookies.len()-1].time.duration_since(\u0026timestamp()).map_or(true, |t| t.as_secs() \u003e= 120);\n if !past_cookie_timeout {\n return true;\n }\n }\n false\n}","traces":[{"line":74,"address":[497728],"length":1,"stats":{"Line":1},"fn_name":"is_eq"},{"line":75,"address":[497752],"length":1,"stats":{"Line":1},"fn_name":null},{"line":79,"address":[498842,498112],"length":1,"stats":{"Line":1},"fn_name":"derive_transport"},{"line":80,"address":[498135],"length":1,"stats":{"Line":1},"fn_name":null},{"line":81,"address":[498416,498174],"length":1,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[498426],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[498514],"length":1,"stats":{"Line":1},"fn_name":null},{"line":85,"address":[498192],"length":1,"stats":{"Line":1},"fn_name":null},{"line":86,"address":[498304],"length":1,"stats":{"Line":1},"fn_name":null},{"line":89,"address":[498619],"length":1,"stats":{"Line":1},"fn_name":null},{"line":90,"address":[498627],"length":1,"stats":{"Line":1},"fn_name":null},{"line":92,"address":[498635],"length":1,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[498742,498884],"length":1,"stats":{"Line":2},"fn_name":null},{"line":94,"address":[498944],"length":1,"stats":{"Line":1},"fn_name":null},{"line":95,"address":[499051],"length":1,"stats":{"Line":1},"fn_name":null},{"line":100,"address":[499088,500359],"length":1,"stats":{"Line":2},"fn_name":"new"},{"line":102,"address":[499128],"length":1,"stats":{"Line":3},"fn_name":null},{"line":103,"address":[499145],"length":1,"stats":{"Line":2},"fn_name":null},{"line":104,"address":[499162],"length":1,"stats":{"Line":1},"fn_name":null},{"line":105,"address":[499201],"length":1,"stats":{"Line":2},"fn_name":null},{"line":106,"address":[499243],"length":1,"stats":{"Line":1},"fn_name":null},{"line":107,"address":[499285],"length":1,"stats":{"Line":2},"fn_name":null},{"line":108,"address":[499327],"length":1,"stats":{"Line":1},"fn_name":null},{"line":113,"address":[499373],"length":1,"stats":{"Line":2},"fn_name":null},{"line":114,"address":[499508],"length":1,"stats":{"Line":1},"fn_name":null},{"line":115,"address":[499515],"length":1,"stats":{"Line":2},"fn_name":null},{"line":116,"address":[499534],"length":1,"stats":{"Line":1},"fn_name":null},{"line":120,"address":[499558],"length":1,"stats":{"Line":2},"fn_name":null},{"line":125,"address":[500400],"length":1,"stats":{"Line":1},"fn_name":"fmt"},{"line":126,"address":[500647,500506,500419,500694,500454,500741,500553,500788,500600,500832],"length":1,"stats":{"Line":10},"fn_name":null},{"line":127,"address":[500447],"length":1,"stats":{"Line":1},"fn_name":null},{"line":128,"address":[500499],"length":1,"stats":{"Line":1},"fn_name":null},{"line":129,"address":[500546],"length":1,"stats":{"Line":1},"fn_name":null},{"line":130,"address":[500593],"length":1,"stats":{"Line":1},"fn_name":null},{"line":131,"address":[500640],"length":1,"stats":{"Line":1},"fn_name":null},{"line":132,"address":[500687],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[500734],"length":1,"stats":{"Line":1},"fn_name":null},{"line":134,"address":[500781],"length":1,"stats":{"Line":1},"fn_name":null},{"line":135,"address":[500828],"length":1,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[500896],"length":1,"stats":{"Line":2},"fn_name":"needs_cookie"},{"line":141,"address":[500910],"length":1,"stats":{"Line":1},"fn_name":null},{"line":142,"address":[500948],"length":1,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[501118],"length":1,"stats":{"Line":0},"fn_name":null},{"line":144,"address":[501129],"length":1,"stats":{"Line":0},"fn_name":null},{"line":147,"address":[500933],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":42,"coverable":45},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","response.rs"],"content":"//! `Noise_IKpsk2` handshake response packet\n\nuse x25519_dalek::PublicKey;\n\nuse crate::noise::error::NoiseError;\nuse crate::noise::handshake::{HandshakeState, needs_cookie};\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt};\nuse crate::qcrypto::hashes::{qcrypto_hash_twice, qcrypto_mac};\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::LABEL_MAC1;\nuse crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm};\n\nstruct HandshakeResponseRaw {\n sender: [u8; 4],\n receiver: [u8; 4],\n ephemeral: [u8; 32],\n empty: [u8; 16],\n mac1: [u8; 16],\n mac2: [u8; 16]\n}\nimpl HandshakeResponseRaw {\n fn to_bytes(\u0026self, session: \u0026mut HandshakeState) -\u003e [u8; 92] {\n let mut output_array = [0u8; 92];\n\n output_array[0] = 2u8;\n output_array[4..8].copy_from_slice(\u0026self.sender);\n output_array[8..12].copy_from_slice(\u0026self.receiver);\n output_array[12..44].copy_from_slice(\u0026self.ephemeral);\n output_array[44..60].copy_from_slice(\u0026self.empty);\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026output_array[..60]);\n\n output_array[60..76].copy_from_slice(\u0026mac1);\n\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026output_array[..76]) } else { [0u8; 16] };\n\n output_array[76..92].copy_from_slice(\u0026mac2);\n\n output_array\n }\n\n #[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways\n fn from_bytes(packet: [u8; 92]) -\u003e Self {\n Self {\n sender: packet[4..8].try_into().unwrap(),\n receiver: packet[8..12].try_into().unwrap(),\n ephemeral: packet[12..44].try_into().unwrap(),\n empty: packet[44..60].try_into().unwrap(),\n mac1: packet[60..76].try_into().unwrap(),\n mac2: packet[76..92].try_into().unwrap()\n }\n }\n}\n\n/// Creates a handshake response packet using the current active handshake session.\n/// # Errors\n/// This function will error if an encryption step is unsuccessful\n/// # Panics\n/// This function, while containing unwraps, will never panic.\n#[allow(clippy::unwrap_used)] // Used for known safe type conversions only\npub fn generate_handshake_response(session: \u0026mut HandshakeState) -\u003e Result\u003c[u8; 92], NoiseError\u003e {\n let eph_keypair = qcrypto_dh_generate_longterm();\n\n let mut msg = HandshakeResponseRaw {\n sender: [0u8; 4],\n receiver: [0u8; 4],\n ephemeral: [0u8; 32],\n empty: [0u8; 16],\n mac1: [0u8; 16],\n mac2: [0u8; 16]\n };\n\n msg.receiver = session.i_i.to_le_bytes();\n msg.sender = session.i_r.to_le_bytes();\n\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, eph_keypair.1.as_bytes())[0];\n\n msg.ephemeral = eph_keypair.1.to_bytes();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.ephemeral);\n\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, qcrypto_dh_longterm(\u0026eph_keypair.0, \u0026session.e_pub_i).as_bytes())[0];\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, qcrypto_dh_longterm(\u0026eph_keypair.0, \u0026session.s_pub_i).as_bytes())[0];\n\n let cr_t_k = qcrypto_hkdf::\u003c3\u003e(\u0026session.ck, \u0026session.q);\n session.ck = cr_t_k[0];\n let t = cr_t_k[1];\n let k = cr_t_k[2];\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026t);\n\n println!(\"{:?} {:?} {:?}\", k, 0, session.h);\n msg.empty = match qcrypto_aead(\u0026k, 0, \u0026[], \u0026session.h) {\n Ok(s) =\u003e s.try_into().unwrap(),\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.empty);\n\n Ok(msg.to_bytes(session))\n}\n\n/// Decrypts a handshake response packet using the current active handshake session.\n/// # Errors\n/// This function will error if a decryption step is unsuccessful\n/// # Panics\n/// This function, while containing unwraps, will never panic.\npub fn parse_handshake_response(session: \u0026mut HandshakeState, packet: [u8; 92]) -\u003e Result\u003c(), NoiseError\u003e {\n let msg = HandshakeResponseRaw::from_bytes(packet);\n\n let e_pub_r = PublicKey::from(msg.ephemeral);\n\n let mut ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, e_pub_r.as_bytes())[0];\n let mut h = qcrypto_hash_twice(\u0026session.h, \u0026msg.ephemeral);\n\n ck = qcrypto_hkdf::\u003c1\u003e(\u0026ck, qcrypto_dh_longterm(\u0026session.e_priv_me, \u0026e_pub_r).as_bytes())[0];\n ck = qcrypto_hkdf::\u003c1\u003e(\u0026ck, qcrypto_dh_longterm(session.s_priv_me, \u0026e_pub_r).as_bytes())[0];\n\n let cr_t_k = qcrypto_hkdf::\u003c3\u003e(\u0026ck, \u0026session.q);\n ck = cr_t_k[0];\n let t = cr_t_k[1];\n let k = cr_t_k[2];\n\n h = qcrypto_hash_twice(\u0026h, \u0026t);\n\n let empty = match qcrypto_aead_decrypt(\u0026k, 0, \u0026msg.empty, \u0026h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n if !empty.is_empty() {\n return Err(NoiseError::PacketUnauthenticated)\n }\n\n h = qcrypto_hash_twice(\u0026h, \u0026msg.empty);\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026packet[..60]);\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026packet[..76]) } else { [0u8; 16] };\n\n if mac1 != msg.mac1 || mac2 != msg.mac2 {\n return Err(NoiseError::PacketUnauthenticated)\n }\n\n if msg.receiver != session.i_i.to_le_bytes() {\n return Err(NoiseError::UnrelatedHandshakePacket)\n }\n\n session.e_pub_r = e_pub_r;\n session.ck = ck;\n session.h = h;\n\n Ok(())\n}","traces":[{"line":22,"address":[489952],"length":1,"stats":{"Line":2},"fn_name":"to_bytes"},{"line":23,"address":[490010],"length":1,"stats":{"Line":2},"fn_name":null},{"line":25,"address":[490030],"length":1,"stats":{"Line":2},"fn_name":null},{"line":26,"address":[490033],"length":1,"stats":{"Line":2},"fn_name":null},{"line":27,"address":[490151],"length":1,"stats":{"Line":2},"fn_name":null},{"line":28,"address":[490273],"length":1,"stats":{"Line":2},"fn_name":null},{"line":29,"address":[490395],"length":1,"stats":{"Line":2},"fn_name":null},{"line":31,"address":[490593],"length":1,"stats":{"Line":2},"fn_name":null},{"line":33,"address":[490741],"length":1,"stats":{"Line":2},"fn_name":null},{"line":35,"address":[490847],"length":1,"stats":{"Line":2},"fn_name":null},{"line":37,"address":[491110],"length":1,"stats":{"Line":2},"fn_name":null},{"line":43,"address":[491232],"length":1,"stats":{"Line":2},"fn_name":"from_bytes"},{"line":45,"address":[491262],"length":1,"stats":{"Line":2},"fn_name":null},{"line":46,"address":[491454],"length":1,"stats":{"Line":2},"fn_name":null},{"line":47,"address":[491649],"length":1,"stats":{"Line":2},"fn_name":null},{"line":48,"address":[491767],"length":1,"stats":{"Line":2},"fn_name":null},{"line":49,"address":[491887],"length":1,"stats":{"Line":2},"fn_name":null},{"line":50,"address":[492007],"length":1,"stats":{"Line":2},"fn_name":null},{"line":61,"address":[494493,492288,493219],"length":1,"stats":{"Line":2},"fn_name":"generate_handshake_response"},{"line":62,"address":[492327],"length":1,"stats":{"Line":2},"fn_name":null},{"line":65,"address":[492348],"length":1,"stats":{"Line":2},"fn_name":null},{"line":66,"address":[492359],"length":1,"stats":{"Line":2},"fn_name":null},{"line":67,"address":[492370],"length":1,"stats":{"Line":2},"fn_name":null},{"line":68,"address":[492389],"length":1,"stats":{"Line":2},"fn_name":null},{"line":69,"address":[492397],"length":1,"stats":{"Line":2},"fn_name":null},{"line":70,"address":[492405],"length":1,"stats":{"Line":2},"fn_name":null},{"line":73,"address":[492596,492521],"length":1,"stats":{"Line":4},"fn_name":null},{"line":74,"address":[492631],"length":1,"stats":{"Line":2},"fn_name":null},{"line":76,"address":[492701],"length":1,"stats":{"Line":2},"fn_name":null},{"line":78,"address":[492848],"length":1,"stats":{"Line":2},"fn_name":null},{"line":80,"address":[492919],"length":1,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[492988],"length":1,"stats":{"Line":2},"fn_name":null},{"line":83,"address":[493238],"length":1,"stats":{"Line":2},"fn_name":null},{"line":85,"address":[493477],"length":1,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[493526],"length":1,"stats":{"Line":2},"fn_name":null},{"line":87,"address":[493588],"length":1,"stats":{"Line":2},"fn_name":null},{"line":88,"address":[493620],"length":1,"stats":{"Line":2},"fn_name":null},{"line":90,"address":[493652],"length":1,"stats":{"Line":2},"fn_name":null},{"line":92,"address":[493737],"length":1,"stats":{"Line":2},"fn_name":null},{"line":93,"address":[493996,494316],"length":1,"stats":{"Line":4},"fn_name":null},{"line":94,"address":[494076,494278],"length":1,"stats":{"Line":4},"fn_name":null},{"line":95,"address":[494171],"length":1,"stats":{"Line":0},"fn_name":null},{"line":98,"address":[494340],"length":1,"stats":{"Line":2},"fn_name":null},{"line":100,"address":[494427],"length":1,"stats":{"Line":2},"fn_name":null},{"line":108,"address":[494512,495176],"length":1,"stats":{"Line":2},"fn_name":"parse_handshake_response"},{"line":109,"address":[494570],"length":1,"stats":{"Line":2},"fn_name":null},{"line":111,"address":[494609],"length":1,"stats":{"Line":2},"fn_name":null},{"line":113,"address":[494703],"length":1,"stats":{"Line":2},"fn_name":null},{"line":114,"address":[494848],"length":1,"stats":{"Line":2},"fn_name":null},{"line":116,"address":[494897],"length":1,"stats":{"Line":2},"fn_name":null},{"line":117,"address":[495210],"length":1,"stats":{"Line":2},"fn_name":null},{"line":119,"address":[495488],"length":1,"stats":{"Line":2},"fn_name":null},{"line":120,"address":[495525],"length":1,"stats":{"Line":2},"fn_name":null},{"line":121,"address":[495653],"length":1,"stats":{"Line":2},"fn_name":null},{"line":122,"address":[495717],"length":1,"stats":{"Line":2},"fn_name":null},{"line":124,"address":[495781],"length":1,"stats":{"Line":2},"fn_name":null},{"line":126,"address":[495883],"length":1,"stats":{"Line":2},"fn_name":null},{"line":127,"address":[495967],"length":1,"stats":{"Line":2},"fn_name":null},{"line":128,"address":[496061],"length":1,"stats":{"Line":0},"fn_name":null},{"line":131,"address":[496039,496175],"length":1,"stats":{"Line":4},"fn_name":null},{"line":132,"address":[496231],"length":1,"stats":{"Line":0},"fn_name":null},{"line":135,"address":[496181,496297],"length":1,"stats":{"Line":4},"fn_name":null},{"line":137,"address":[496445],"length":1,"stats":{"Line":2},"fn_name":null},{"line":138,"address":[496607],"length":1,"stats":{"Line":2},"fn_name":null},{"line":140,"address":[496867],"length":1,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[497012],"length":1,"stats":{"Line":0},"fn_name":null},{"line":144,"address":[496974,497073],"length":1,"stats":{"Line":4},"fn_name":null},{"line":145,"address":[497549],"length":1,"stats":{"Line":0},"fn_name":null},{"line":148,"address":[497143],"length":1,"stats":{"Line":2},"fn_name":null},{"line":149,"address":[497267],"length":1,"stats":{"Line":2},"fn_name":null},{"line":150,"address":[497391],"length":1,"stats":{"Line":2},"fn_name":null},{"line":152,"address":[497515],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":67,"coverable":72},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // this is a test harness, we want to panic\n\nuse crate::noise::handshake::HandshakeState;\nuse crate::noise::handshake::initiator::{parse_handshake_init, generate_handshake_init};\nuse crate::noise::handshake::response::{parse_handshake_response, generate_handshake_response};\nuse crate::qcrypto::pki::qcrypto_dh_generate_longterm;\n\n#[test]\nfn noise_halfhandshake_test() {\n let alice_keypair = qcrypto_dh_generate_longterm();\n let bob_keypair = qcrypto_dh_generate_longterm();\n\n let mut alice_session = HandshakeState::new(\u0026alice_keypair.0, bob_keypair.1, None);\n let mut bob_session = HandshakeState::new(\u0026bob_keypair.0, alice_keypair.1, None);\n\n let handshake_init = generate_handshake_init(\u0026mut alice_session).unwrap();\n parse_handshake_init(\u0026mut bob_session, handshake_init).unwrap();\n\n println!(\"{:?}\", alice_session);\n println!(\"{:?}\", bob_session);\n\n assert!(alice_session.is_eq(\u0026bob_session));\n}\n\n#[test]\nfn noise_nocookie_handshake_test() {\n let alice_keypair = qcrypto_dh_generate_longterm();\n let bob_keypair = qcrypto_dh_generate_longterm();\n\n let mut alice_session = HandshakeState::new(\u0026alice_keypair.0, bob_keypair.1, None);\n let mut bob_session = HandshakeState::new(\u0026bob_keypair.0, alice_keypair.1, None);\n\n let handshake_init = generate_handshake_init(\u0026mut alice_session).unwrap();\n parse_handshake_init(\u0026mut bob_session, handshake_init).unwrap();\n\n let handshake_response = generate_handshake_response(\u0026mut bob_session).unwrap();\n parse_handshake_response(\u0026mut alice_session, handshake_response).unwrap();\n\n println!(\"{:?}\", alice_session);\n println!(\"{:?}\", bob_session);\n\n assert!(alice_session.is_eq(\u0026bob_session));\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","mod.rs"],"content":"//! Contains structs and functions for serializing and deserializing different packets in the `Noise_IKpsk2` handshake and data frames\npub mod handshake;\npub mod error;\npub mod data;\n\n#[cfg(test)]\npub mod tests;\npub mod rfc6479;","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","rfc6479","mod.rs"],"content":"//! A Rust implementation of the anti-replay algorithm described in [RFC 6479](https://rfc-editor.org/rfc6479).\n\nconst SIZE_OF_INTEGER: usize = std::mem::size_of::\u003cusize\u003e() * 8;\nconst BITMAP_LEN: usize = 1024 / SIZE_OF_INTEGER;\nconst BITMAP_INDEX_MASK: u64 = BITMAP_LEN as u64 - 1;\nconst REDUNDANT_BIT_SHIFTS: u64 = 5;\nconst REDUNDANT_BITS: u64 = 1 \u003c\u003c REDUNDANT_BIT_SHIFTS;\nconst BITMAP_LOC_MASK: u64 = REDUNDANT_BITS - 1;\nconst WINDOW_SIZE: u64 = 512;\n\n#[derive(Default)]\n/// An implementation of the RFC6479 anti-replay algorithm\npub struct ShiftWindow {\n replaywin_lastseq: u64,\n replaywin_bitmap: [usize; BITMAP_LEN],\n}\n\nimpl ShiftWindow {\n /// Create a new ShiftWindow with default values\n pub fn new() -\u003e Self {\n Self::default()\n }\n\n /// Check if a given sequence value is okay given the current state of the shift window\n pub fn check_replay_window(\u0026self, seq: u64) -\u003e bool {\n println!(\"sequence {} {}\", seq, self.replaywin_lastseq);\n\n // first == 0 or wrapped\n if seq == 0 {\n return false;\n }\n\n // larger is always good\n if seq \u003e self.replaywin_lastseq {\n return true;\n }\n\n // too old\n if (seq + WINDOW_SIZE) \u003c self.replaywin_lastseq {\n return false;\n }\n\n let bit_location = seq \u0026 BITMAP_LOC_MASK;\n let index = (seq \u003e\u003e REDUNDANT_BIT_SHIFTS) \u0026 BITMAP_INDEX_MASK;\n\n self.replaywin_bitmap[index as usize] \u0026 (1 \u003c\u003c bit_location) == 0\n }\n\n /// Update the internal state of the replay window to mark the given sequence number as used and disallow future use of it.\n pub fn update_replay_window(\u0026mut self, seq: u64) {\n if !self.check_replay_window(seq) {\n return;\n }\n\n let index = seq \u003e\u003e REDUNDANT_BIT_SHIFTS;\n\n if seq \u003e self.replaywin_lastseq {\n let index_cur = self.replaywin_lastseq \u003e\u003e REDUNDANT_BIT_SHIFTS;\n let mut diff = index - index_cur;\n\n if diff \u003e BITMAP_LEN as u64 {\n diff = BITMAP_LEN as u64;\n }\n\n for id in 0..diff {\n let iindex = (id + index_cur + 1) \u0026 BITMAP_INDEX_MASK;\n self.replaywin_bitmap[iindex as usize] = 0;\n }\n\n self.replaywin_lastseq = seq;\n }\n\n let index = index \u0026 BITMAP_INDEX_MASK;\n let bit_location = seq \u0026 BITMAP_LOC_MASK;\n\n self.replaywin_bitmap[index as usize] |= 1 \u003c\u003c bit_location;\n }\n}\n\n#[cfg(test)]\nmod tests {\n use crate::noise::rfc6479::ShiftWindow;\n\n #[test]\n pub fn rfc6479_tests() {\n let mut shiftwin = ShiftWindow::new();\n\n assert!(!shiftwin.check_replay_window(0));\n assert!(shiftwin.check_replay_window(1));\n shiftwin.update_replay_window(1);\n assert!(!shiftwin.check_replay_window(1));\n shiftwin.update_replay_window(329_846_324_987);\n assert!(!shiftwin.check_replay_window(2));\n }\n}","traces":[{"line":20,"address":[1613392],"length":1,"stats":{"Line":1},"fn_name":"new"},{"line":21,"address":[1613400],"length":1,"stats":{"Line":1},"fn_name":null},{"line":25,"address":[1613424],"length":1,"stats":{"Line":1},"fn_name":"check_replay_window"},{"line":26,"address":[1613449],"length":1,"stats":{"Line":1},"fn_name":null},{"line":29,"address":[1613590],"length":1,"stats":{"Line":1},"fn_name":null},{"line":30,"address":[1613598],"length":1,"stats":{"Line":1},"fn_name":null},{"line":34,"address":[1613610],"length":1,"stats":{"Line":1},"fn_name":null},{"line":35,"address":[1613645],"length":1,"stats":{"Line":1},"fn_name":null},{"line":39,"address":[1613620,1613677],"length":1,"stats":{"Line":2},"fn_name":null},{"line":40,"address":[488728],"length":1,"stats":{"Line":1},"fn_name":null},{"line":43,"address":[488690],"length":1,"stats":{"Line":1},"fn_name":null},{"line":44,"address":[488712,488740],"length":1,"stats":{"Line":2},"fn_name":null},{"line":46,"address":[488757,488891],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[1613952],"length":1,"stats":{"Line":1},"fn_name":"update_replay_window"},{"line":51,"address":[1613985],"length":1,"stats":{"Line":1},"fn_name":null},{"line":55,"address":[1614044,1614010],"length":1,"stats":{"Line":2},"fn_name":null},{"line":57,"address":[489365,489027],"length":1,"stats":{"Line":2},"fn_name":null},{"line":58,"address":[489120],"length":1,"stats":{"Line":1},"fn_name":null},{"line":59,"address":[1614175,1614210],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[489175,489276],"length":1,"stats":{"Line":2},"fn_name":null},{"line":62,"address":[489267],"length":1,"stats":{"Line":1},"fn_name":null},{"line":65,"address":[489543,489375,489215,489288],"length":1,"stats":{"Line":4},"fn_name":null},{"line":66,"address":[489494,489391],"length":1,"stats":{"Line":1},"fn_name":null},{"line":67,"address":[489534,489481,489553],"length":1,"stats":{"Line":2},"fn_name":null},{"line":70,"address":[489362],"length":1,"stats":{"Line":1},"fn_name":null},{"line":73,"address":[489042],"length":1,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[489059],"length":1,"stats":{"Line":1},"fn_name":null},{"line":76,"address":[489659,489581,489071],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":28,"coverable":28},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","tests.rs"],"content":"#![allow(clippy::unwrap_used)]\n#![allow(clippy::pedantic)]\n\nuse crate::noise::data::{deencapsulate, encapsulate};\nuse crate::noise::handshake::HandshakeState;\nuse crate::noise::handshake::initiator::{parse_handshake_init, generate_handshake_init};\nuse crate::noise::handshake::response::{parse_handshake_response, generate_handshake_response};\nuse crate::qcrypto::pki::qcrypto_dh_generate_longterm;\n\n#[test]\npub fn noise_transport_test() {\n let alice_keypair = qcrypto_dh_generate_longterm();\n let bob_keypair = qcrypto_dh_generate_longterm();\n\n let mut alice_session = HandshakeState::new(\u0026alice_keypair.0, bob_keypair.1, None);\n let mut bob_session = HandshakeState::new(\u0026bob_keypair.0, alice_keypair.1, None);\n\n let handshake_init = generate_handshake_init(\u0026mut alice_session).unwrap();\n parse_handshake_init(\u0026mut bob_session, handshake_init).unwrap();\n\n let handshake_response = generate_handshake_response(\u0026mut bob_session).unwrap();\n parse_handshake_response(\u0026mut alice_session, handshake_response).unwrap();\n\n alice_session.derive_transport();\n bob_session.derive_transport();\n\n assert!(alice_session.is_eq(\u0026bob_session));\n\n let packet_abc = vec![42u8; 17];\n let packet_encapsulated = encapsulate(\u0026mut alice_session, \u0026packet_abc).unwrap();\n\n let packet_abc_deencapsulated = deencapsulate(\u0026mut bob_session, \u0026packet_encapsulated).unwrap();\n\n assert_eq!(packet_abc, packet_abc_deencapsulated)\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","aead.rs"],"content":"//! Various functions for `ChaCha20Poly1305` stream ciphers\n\nuse chacha20poly1305::{ChaCha20Poly1305, Error, KeyInit, XChaCha20Poly1305};\nuse chacha20poly1305::aead::{Aead, Nonce, Payload};\n\n/// Encrypt the plaintext with the given parameters using `ChaCha20Poly1305`\n/// # Errors\n/// This function will error if the encryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::module_name_repetitions)]\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_aead(key: \u0026[u8; 32], counter: u64, plaintext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut nonce_bytes = [0u8; 12];\n nonce_bytes[4..].copy_from_slice(\u0026counter.to_le_bytes());\n let mut payload = Payload::from(plaintext);\n payload.aad = authtext;\n\n cipher.encrypt(\u0026Nonce::\u003cChaCha20Poly1305\u003e::from(nonce_bytes), payload)\n}\n\n/// Decrypt the ciphertext with the given parameters using `ChaCha20Poly1305`\n/// # Errors\n/// This function will error if the decryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_aead_decrypt(key: \u0026[u8; 32], counter: u64, ciphertext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut nonce_bytes = [0u8; 12];\n nonce_bytes[4..].copy_from_slice(\u0026counter.to_le_bytes());\n let mut payload = Payload::from(ciphertext);\n payload.aad = authtext;\n\n cipher.decrypt(\u0026Nonce::\u003cChaCha20Poly1305\u003e::from(nonce_bytes), payload)\n}\n\n/// Encrypt the ciphertext with the given parameters using `XChaCha20Poly1305`\n/// # Errors\n/// This function will error if the decryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_xaead(key: \u0026[u8; 32], nonce: \u0026[u8; 24], plaintext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut payload = Payload::from(plaintext);\n payload.aad = authtext;\n\n cipher.encrypt(Nonce::\u003cXChaCha20Poly1305\u003e::from_slice(nonce), payload)\n}\n\n/// Decrypt the ciphertext with the given parameters using `XChaCha20Poly1305`\n/// # Errors\n/// This function will error if the decryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_xaead_decrypt(key: \u0026[u8; 32], nonce: \u0026[u8; 24], ciphertext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut payload = Payload::from(ciphertext);\n payload.aad = authtext;\n\n cipher.decrypt(Nonce::\u003cXChaCha20Poly1305\u003e::from_slice(nonce), payload)\n}","traces":[{"line":13,"address":[428037,427456],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_aead"},{"line":14,"address":[427554],"length":1,"stats":{"Line":1},"fn_name":null},{"line":15,"address":[427597],"length":1,"stats":{"Line":1},"fn_name":null},{"line":16,"address":[427738,427620],"length":1,"stats":{"Line":2},"fn_name":null},{"line":17,"address":[427830],"length":1,"stats":{"Line":1},"fn_name":null},{"line":18,"address":[427859],"length":1,"stats":{"Line":1},"fn_name":null},{"line":20,"address":[427965,427875],"length":1,"stats":{"Line":2},"fn_name":null},{"line":29,"address":[428080,428661],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_aead_decrypt"},{"line":30,"address":[428178],"length":1,"stats":{"Line":1},"fn_name":null},{"line":31,"address":[428221],"length":1,"stats":{"Line":1},"fn_name":null},{"line":32,"address":[428244,428362],"length":1,"stats":{"Line":2},"fn_name":null},{"line":33,"address":[428454],"length":1,"stats":{"Line":1},"fn_name":null},{"line":34,"address":[428483],"length":1,"stats":{"Line":1},"fn_name":null},{"line":36,"address":[428499,428589],"length":1,"stats":{"Line":2},"fn_name":null},{"line":45,"address":[428704,429027],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_xaead"},{"line":46,"address":[428802],"length":1,"stats":{"Line":1},"fn_name":null},{"line":47,"address":[428849],"length":1,"stats":{"Line":1},"fn_name":null},{"line":48,"address":[428920],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[428941],"length":1,"stats":{"Line":1},"fn_name":null},{"line":59,"address":[429395,429072],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_xaead_decrypt"},{"line":60,"address":[429170],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[429217],"length":1,"stats":{"Line":1},"fn_name":null},{"line":62,"address":[429288],"length":1,"stats":{"Line":1},"fn_name":null},{"line":64,"address":[429309],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":24,"coverable":24},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","hashes.rs"],"content":"//! Various hash functions\n\nuse blake2::{Blake2s256, Blake2sMac, Digest};\nuse blake2::digest::{FixedOutput, KeyInit, Update};\nuse hmac::SimpleHmac;\n\ntype HmacBlake2s = SimpleHmac\u003cBlake2s256\u003e;\n\n/// Given a varied length input, produce a 32-byte Blake2s hash digest\npub fn qcrypto_hash(input: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = Blake2s256::new();\n Update::update(\u0026mut hasher, input);\n hasher.finalize().into()\n}\n\n/// Given two varied length inputs, produce a 32-byte Blake2s hash digest\npub fn qcrypto_hash_twice(input: \u0026[u8], input2: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = Blake2s256::new();\n Update::update(\u0026mut hasher, input);\n Update::update(\u0026mut hasher, input2);\n hasher.finalize().into()\n}\n\n/// Given a varied length MAC key and a varied length input, produce a 16-byte MAC digest using Blake2s\n/// # Panics\n/// This function will panic if the key is an incorrect size.\n#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap\npub fn qcrypto_mac(key: \u0026[u8], input: \u0026[u8]) -\u003e [u8; 16] {\n let mut hasher = Blake2sMac::new_from_slice(key).unwrap();\n hasher.update(input);\n hasher.finalize_fixed().into()\n}\n\n/// Given a varied length HMAC key and a varied length input, produce a 32-byte HMAC digest using Blake2s\n/// # Panics\n/// This function will panic if the key is an incorrect size.\n#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap\npub fn qcrypto_hmac(key: \u0026[u8], input: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();\n Update::update(\u0026mut hasher, input);\n hasher.finalize_fixed().into()\n}\n\n/// Given a varied length HMAC key and two varied length inputs, produce a 32-byte HMAC digest using Blake2s.\n/// This does essentially the same thing as concatenating input2 to input and calling `qcrypto_hmac` on that.\n/// # Panics\n/// This function will panic if the key is an incorrect size.\n#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap\npub fn qcrypto_hmac_twice(key: \u0026[u8], input: \u0026[u8], input2: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();\n Update::update(\u0026mut hasher, input);\n Update::update(\u0026mut hasher, input2);\n hasher.finalize_fixed().into()\n}","traces":[{"line":10,"address":[1621392],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_hash"},{"line":11,"address":[1621435],"length":1,"stats":{"Line":1},"fn_name":null},{"line":12,"address":[1621456],"length":1,"stats":{"Line":1},"fn_name":null},{"line":13,"address":[1621467],"length":1,"stats":{"Line":1},"fn_name":null},{"line":17,"address":[1621552],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_hash_twice"},{"line":18,"address":[1621621],"length":1,"stats":{"Line":1},"fn_name":null},{"line":19,"address":[433225],"length":1,"stats":{"Line":1},"fn_name":null},{"line":20,"address":[433245],"length":1,"stats":{"Line":1},"fn_name":null},{"line":21,"address":[433255],"length":1,"stats":{"Line":1},"fn_name":null},{"line":28,"address":[433344],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_mac"},{"line":29,"address":[433402],"length":1,"stats":{"Line":1},"fn_name":null},{"line":30,"address":[433449],"length":1,"stats":{"Line":1},"fn_name":null},{"line":31,"address":[433459],"length":1,"stats":{"Line":1},"fn_name":null},{"line":38,"address":[433536],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_hmac"},{"line":39,"address":[433595],"length":1,"stats":{"Line":1},"fn_name":null},{"line":41,"address":[433682],"length":1,"stats":{"Line":1},"fn_name":null},{"line":49,"address":[433760],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_hmac_twice"},{"line":50,"address":[433852],"length":1,"stats":{"Line":2},"fn_name":null},{"line":53,"address":[433987],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":19,"coverable":19},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","hkdf.rs"],"content":"//! An implementation of the HKDF algorithm\n\nuse crate::qcrypto::hashes::{qcrypto_hmac, qcrypto_hmac_twice};\n\n#[allow(clippy::module_name_repetitions)]\n/// Given a constant order N, a varied length key and varied length input, perform the HKDF algorithm and produce an N-array of 32-byte arrays.\npub fn qcrypto_hkdf\u003cconst N: usize\u003e(key: \u0026[u8], input: \u0026[u8]) -\u003e [[u8; 32]; N] {\n let mut result_array = [[0u8; 32]; N];\n\n let t0 = qcrypto_hmac(key, input);\n let t1 = qcrypto_hmac(\u0026t0, \u0026[1u8]);\n\n result_array[0] = t1;\n\n for n in 1..N {\n result_array[n] = qcrypto_hmac_twice(\u0026t0, \u0026result_array[n-1], \u0026n.to_be_bytes());\n }\n\n result_array\n}","traces":[{"line":7,"address":[411728,412608,410848],"length":1,"stats":{"Line":4},"fn_name":"qcrypto_hkdf\u003c1\u003e"},{"line":8,"address":[410917,412677,411797],"length":1,"stats":{"Line":5},"fn_name":null},{"line":10,"address":[412822,411942,411062],"length":1,"stats":{"Line":4},"fn_name":null},{"line":11,"address":[411075,411955,412835],"length":1,"stats":{"Line":5},"fn_name":null},{"line":13,"address":[411114,412874,411994],"length":1,"stats":{"Line":4},"fn_name":null},{"line":15,"address":[411230,411681,412110,412561,412990,411377,413137,412257,413441],"length":1,"stats":{"Line":12},"fn_name":null},{"line":16,"address":[412278,413158,411398,411691,413451,412571],"length":1,"stats":{"Line":4},"fn_name":null},{"line":19,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":7,"coverable":8},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","mod.rs"],"content":"//! A module to implement all of the various cryptography constructs required to implement `WireGuard`\n\nuse tai64::Tai64N;\n\npub mod hashes;\npub mod pki;\npub mod aead;\n\n#[cfg(test)]\npub mod tests;\npub mod hkdf;\n\n/// Get the current TAI64N timestamp\npub fn timestamp() -\u003e Tai64N {\n Tai64N::now()\n}\n\n/// The cryptography handshake construction identifier\npub const CONSTURCTION: \u0026str = \"Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s\";\n/// The `WireGuard` protocol identifier\npub const IDENTIFIER: \u0026str = \"WireGuard v1 zx2c4 Jason@zx2c4.com\";\n/// The MAC1 cookie label\npub const LABEL_MAC1: \u0026str = \"mac1----\";\n/// The COOKIE1 cookie label\npub const LABEL_COOKIE: \u0026str = \"cookie--\";","traces":[{"line":14,"address":[467328],"length":1,"stats":{"Line":2},"fn_name":"timestamp"},{"line":15,"address":[467332],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":2,"coverable":2},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","pki.rs"],"content":"//! Various public-key cryptography functions\n\nuse rand::rngs::OsRng;\nuse x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret, StaticSecret};\n\ntype LongtermKeypair = (StaticSecret, PublicKey);\n\n/// Generate a X25519 keypair\npub fn qcrypto_dh_generate_longterm() -\u003e LongtermKeypair {\n let secret = StaticSecret::new(OsRng);\n let public = PublicKey::from(\u0026secret);\n (secret, public)\n}\n\n/// Perform Elliptic-Curve Diffie-Hellman between a secret and public key to get a shared secret value\npub fn qcrypto_dh_longterm(secret: \u0026StaticSecret, public: \u0026PublicKey) -\u003e SharedSecret {\n secret.diffie_hellman(public)\n}\n\n\ntype EphemeralKeypair = (EphemeralSecret, PublicKey);\n\n/// Generate a X25519 keypair\npub fn qcrypto_dh_generate_ephemeral() -\u003e EphemeralKeypair {\n let secret = EphemeralSecret::new(OsRng);\n let public = PublicKey::from(\u0026secret);\n (secret, public)\n}\n\n/// Perform Elliptic-Curve Diffie-Hellman between a secret and public key to get a shared secret value\npub fn qcrypto_dh_ephemeral(secret: EphemeralSecret, public: \u0026PublicKey) -\u003e SharedSecret {\n secret.diffie_hellman(public)\n}","traces":[{"line":9,"address":[439488,439764],"length":1,"stats":{"Line":3},"fn_name":"qcrypto_dh_generate_longterm"},{"line":10,"address":[439505],"length":1,"stats":{"Line":5},"fn_name":null},{"line":11,"address":[439515],"length":1,"stats":{"Line":3},"fn_name":null},{"line":12,"address":[439587],"length":1,"stats":{"Line":5},"fn_name":null},{"line":16,"address":[439792],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_dh_longterm"},{"line":17,"address":[439813],"length":1,"stats":{"Line":1},"fn_name":null},{"line":24,"address":[439840,440116],"length":1,"stats":{"Line":0},"fn_name":"qcrypto_dh_generate_ephemeral"},{"line":25,"address":[439857],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[439867],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[439939],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[440144],"length":1,"stats":{"Line":0},"fn_name":"qcrypto_dh_ephemeral"},{"line":32,"address":[440161],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":6,"coverable":12},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // we want to panic, this is a test file\n\nuse hex_lit::hex;\nuse x25519_dalek::PublicKey;\n\nuse crate::qcrypto::{CONSTURCTION, IDENTIFIER};\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt, qcrypto_xaead, qcrypto_xaead_decrypt};\nuse crate::qcrypto::hashes::{qcrypto_hash, qcrypto_hash_twice, qcrypto_hmac, qcrypto_mac};\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm};\n\n#[test]\nfn qcrypto_hash_test() {\n assert_eq!(qcrypto_hash(\u0026[0u8; 32]), hex!(\"320b5ea99e653bc2b593db4130d10a4efd3a0b4cc2e1a6672b678d71dfbd33ad\"));\n assert_eq!(qcrypto_hash(CONSTURCTION.as_bytes()), [\n 96, 226, 109, 174, 243, 39, 239, 192, 46, 195, 53, 226, 160, 37, 210, 208, 22, 235, 66, 6, 248,\n 114, 119, 245, 45, 56, 209, 152, 139, 120, 205, 54,\n ]);\n assert_eq!(qcrypto_hash_twice(\u0026qcrypto_hash(CONSTURCTION.as_bytes()), IDENTIFIER.as_bytes()), [\n 34, 17, 179, 97, 8, 26, 197, 102, 105, 18, 67, 219, 69, 138, 213, 50, 45, 156, 108, 102, 34,\n 147, 232, 183, 14, 225, 156, 101, 186, 7, 158, 243,\n ]);\n}\n#[test]\nfn qcrypto_mac_test() {\n assert_eq!(qcrypto_mac(\u0026[0u8; 32], \u0026[0u8; 32]), hex!(\"086de86cfb256a2bc40740062bcf4dcc\"));\n}\n#[test]\nfn qcrypto_hmac_test() {\n assert_eq!(qcrypto_hmac(\u0026[0u8; 32], \u0026[0u8; 32]), hex!(\"025108dc4694cac66d549e152b967e41e516cc7568111822bf1ca44cb89bcbca\"));\n}\n\n#[test]\nfn qcrypto_pki_generate_test() {\n let keypair = qcrypto_dh_generate_longterm();\n assert_eq!(keypair.1, PublicKey::from(\u0026keypair.0))\n}\n#[test]\nfn qcrypto_dh_test() {\n let alice = qcrypto_dh_generate_longterm();\n let bob = qcrypto_dh_generate_longterm();\n\n let secret = qcrypto_dh_longterm(\u0026alice.0, \u0026bob.1);\n let secret2 = qcrypto_dh_longterm(\u0026bob.0, \u0026alice.1);\n\n assert_eq!(secret.as_bytes(), secret2.as_bytes())\n}\n#[test]\nfn qcrypto_aead_test() {\n let ciphertext = qcrypto_aead(\u0026[0u8; 32], 0, \u0026[0u8; 32], \u0026[0u8; 32]).unwrap();\n assert_eq!(qcrypto_aead_decrypt(\u0026[0u8; 32], 0, \u0026ciphertext, \u0026[0u8; 32]).unwrap(), [0u8; 32].to_vec())\n}\n#[test]\nfn qcrypto_xaead_test() {\n let ciphertext = qcrypto_xaead(\u0026[0u8; 32], \u0026[0u8; 24], \u0026[0u8; 32], \u0026[0u8; 32]).unwrap();\n assert_eq!(qcrypto_xaead_decrypt(\u0026[0u8; 32], \u0026[0u8; 24], \u0026ciphertext, \u0026[0u8; 32]).unwrap(), [0u8; 32].to_vec());\n}\n#[test]\nfn qcrypto_hkdf_test() {\n let derived = qcrypto_hkdf::\u003c1\u003e(\u0026[0u8; 32], \u0026[0u8; 32]);\n assert_eq!(derived, [hex!(\"1090894613df8aef670b0b867e222daebc0d3e436cdddbc16c65855ab93cc91a\")]);\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","stack","entry.rs"],"content":"//! The ENTRY stage of the packet processing stack. Provides a `PacketEntryStage` which implements `PacketProcessingStage`.\n\nuse std::error::Error;\nuse std::net::SocketAddr;\nuse crate::stack::{PacketProcessingStage};\n\n/// The ENTRY stage of the packet processing stack\npub struct PacketEntryStage {}\n\nimpl PacketProcessingStage for PacketEntryStage {\n fn process_packet(pkt: Vec\u003cu8\u003e, from: \u0026SocketAddr) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n Ok(())\n }\n}","traces":[{"line":11,"address":[515024],"length":1,"stats":{"Line":0},"fn_name":"process_packet"},{"line":12,"address":[515033],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":2},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","stack","mod.rs"],"content":"//! quicktap's packet processing stack\n//! Packet processing is done in several *stages*:\n//! - ENTRY\n//! - CRYPT\n//! - ROUTING\n//! - PROCESSING\n//! - EXIT\n//! # UDP Packet Flow\n//! For a packet received on the UDP socket, the following route is taken through the processing stack:\n//! ```text\n//! UDP Socket -\u003e ENTRY -\u003e CRYPT -\u003e (drop) \u003c-----+\n//! | | ^ |\n//! | | | |\n//! | +-----\u003e ROUTING -\u003e CRYPT -\u003e EXIT\n//! | v\n//! +---\u003e PROCESSING -\u003e (end flow)\n//! ```\n//! # TUN Packet Flow\n//! For a packet received on the TUN interface, the following route is taken through the processing stack:\n//! ```text\n//! TUN Interface -\u003e ENTRY -\u003e ROUTING -\u003e CRYPT -\u003e EXIT\n//! | |\n//! v |\n//! (drop) \u003c----+\n//! ```\n\nuse std::error::Error;\nuse std::net::SocketAddr;\n\npub mod entry;\n\n/// The methods and functions that need to be implemented by a stage in the packet processor\npub trait PacketProcessingStage {\n /// Process a raw datagram. This should go down the WHOLE routing chain - assume previous steps have already done.\n /// For example, if you are the CRYPT layer, and are processing a tun packet, assume that the ENTRY and ROUTING stack stages have already been completed and you are being given the result of that processing.\n /// # Errors\n /// This function will error if an error occurs\n fn process_packet(pkt: Vec\u003cu8\u003e, from: \u0026SocketAddr) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e where Self: Sized;\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // we want to panic, this is a test file\n\nuse crate::version;\n\n#[test] // This is one of those good ol' \"just for codecov\" tests. This doesn't actually need to be tested, it's for frontends, but I want that juicy 100% codecov\npub const fn version_test() {\n version();\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","cli.rs"],"content":"use clap::{ArgAction, Parser};\n\n#[derive(Parser)]\n#[command(author = \"The Quicktap Maintainers\", version, about = \"A userspace WireGuard implementation written in Rust\", long_about = None)]\npub struct Cli {\n #[arg(short, long, action = ArgAction::SetTrue)]\n pub foreground: bool,\n pub interface_name: String\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","command.rs"],"content":"use std::error::Error;\nuse std::io;\nuse std::os::unix::net::SocketAddr;\nuse std::os::unix::net::{UnixListener, UnixStream};\n\npub enum PacketThreadCommand {\n UpdateConfig(UpdateConfigCommand),\n Stop\n}\n\npub struct UpdateConfigCommand {}\n\npub struct CommandClient {\n stream: UnixStream,\n addr: SocketAddr,\n current_command: CommandType\n}\npub enum CommandType {\n WaitingForCommand,\n Read,\n Write\n}\n\npub fn command_handler(listener: UnixListener) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n listener.set_nonblocking(true)?;\n\n let mut clients: Vec\u003cCommandClient\u003e = vec![];\n\n match listener.accept() {\n Ok((stream, addr)) =\u003e {\n clients.push(CommandClient { stream, addr, current_command: CommandType::WaitingForCommand })\n },\n Err(e) if matches!(e.kind(), io::ErrorKind::WouldBlock) =\u003e {\n // ignore.\n },\n Err(e) =\u003e {\n // okay, real error, knock it up\n return Err(e.into())\n }\n }\n\n // uh lets play ignorey ignorey for now\n\n Ok(())\n}","traces":[{"line":24,"address":[762400,763513,763567],"length":1,"stats":{"Line":0},"fn_name":"command_handler"},{"line":25,"address":[762547,762411,762487],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[762540],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[762646,762704],"length":1,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[762735],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[763475,762869],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[763159,763248,763342],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[763297],"length":1,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[763321,763424],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[763534],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":10},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","main.rs"],"content":"\nuse std::fs::File;\n\nuse std::os::unix::net::{UnixListener};\n\nuse std::sync::mpsc::channel;\nuse std::thread::{spawn};\n\nuse clap::Parser;\nuse daemonize::Daemonize;\nuse log::{error, info};\n\nuse quicktap::drivers::tun::TunDevice;\nuse quicktap::drivers::tungeneric::{GenericDriver, GenericInterface};\n\nuse crate::cli::Cli;\nuse crate::command::{command_handler, PacketThreadCommand};\nuse crate::pproc::packet_thread;\n\npub mod cli;\npub mod pproc;\npub mod command;\n\nfn main() {\n simple_logger::init().unwrap();\n\n let args = Cli::parse();\n\n info!(\"Hello, world! {}\", quicktap::version());\n info!(\"Starting up\");\n\n if !args.foreground {\n info!(\"Forking to background\");\n\n let stdout = match File::create(\"/var/log/e4.log\") {\n Ok(f) =\u003e f,\n Err(e) =\u003e {\n error!(\"Failed to open stdout file: {}\", e);\n std::process::exit(8);\n }\n };\n let stderr = match File::create(\"/var/log/e4.err\") {\n Ok(f) =\u003e f,\n Err(e) =\u003e {\n error!(\"Failed to open stderr file: {}\", e);\n std::process::exit(9);\n }\n };\n\n let daemon_opts = Daemonize::new()\n .stdout(stdout)\n .stderr(stderr);\n match daemon_opts.start() {\n Ok(_) =\u003e info!(\"Forked to background successfully\"),\n Err(e) =\u003e {\n error!(\"Failed to daemonize quicktap-cli worker process: {}\", e);\n std::process::exit(1);\n }\n }\n }\n\n info!(\"Creating unconfigured device\");\n\n let device = match TunDevice::new(\u0026GenericInterface {\n addresses: vec![],\n mtu: None,\n name: args.interface_name.clone(),\n }) {\n Ok(d) =\u003e d,\n Err(e) =\u003e {\n error!(\"Failed to create interface: {}\", e);\n std::process::exit(2);\n }\n };\n\n info!(\"Spawning packet processor thread\");\n\n let (tx, rx) = channel::\u003cPacketThreadCommand\u003e();\n\n let pproc_thread = spawn(|| {\n match packet_thread(device, rx) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Error in pproc_thread: {}\", e);\n }\n }\n });\n\n info!(\"Creating command listener\");\n match UnixListener::bind(format!(\"/var/run/{}.sock\", args.interface_name)) {\n Ok(l) =\u003e {\n // handle l\n match command_handler(l) {\n Ok(_) =\u003e (),\n Err(e) =\u003e error!(\"Error in command handler: {}\", e)\n }\n },\n Err(e) =\u003e {\n error!(\"Error creating command listener {}: {}\", format!(\"/var/run/{}.sock\", args.interface_name), e);\n }\n };\n\n\n match tx.send(PacketThreadCommand::Stop) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Error sending stop command to packet thread: {}\", e);\n std::process::exit(6);\n }\n }\n\n info!(\"Waiting for packet thread to stop\");\n match pproc_thread.join() {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Error joining thread: {:?}\", e);\n std::process::exit(5);\n }\n }\n\n info!(\"Cleaning up\");\n\n match std::fs::remove_file(format!(\"/var/run/{}.sock\", args.interface_name)) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Failed to remove existing socket: {}\", e);\n std::process::exit(7);\n }\n }\n\n info!(\"Cya!\");\n}\n","traces":[{"line":24,"address":[750132,740160,742009],"length":1,"stats":{"Line":0},"fn_name":"main"},{"line":25,"address":[740173],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[740255],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[740356,740268,740453,740561],"length":1,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[740517,740800,740980,740897],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[740961,743490],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[741127,741272,741363],"length":1,"stats":{"Line":0},"fn_name":null},{"line":35,"address":[741336,741469],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[741487],"length":1,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[741546],"length":1,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[741654,741834,741562,741751],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[741815],"length":1,"stats":{"Line":0},"fn_name":null},{"line":42,"address":[741516,742066],"length":1,"stats":{"Line":0},"fn_name":null},{"line":43,"address":[742084],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[742135],"length":1,"stats":{"Line":0},"fn_name":null},{"line":45,"address":[742151,742340,742423,742243],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[742404],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[742113,742711,742673],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[742642],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[742680],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[742754],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[742837,743313,743410,743495],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[742881],"length":1,"stats":{"Line":0},"fn_name":null},{"line":56,"address":[743054,742909,743145],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[743118],"length":1,"stats":{"Line":0},"fn_name":null},{"line":62,"address":[743825,741083,743649,743746],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[744010,744173],"length":1,"stats":{"Line":0},"fn_name":null},{"line":65,"address":[743818],"length":1,"stats":{"Line":0},"fn_name":null},{"line":66,"address":[743928],"length":1,"stats":{"Line":0},"fn_name":null},{"line":67,"address":[743939],"length":1,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[744250],"length":1,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[744316],"length":1,"stats":{"Line":0},"fn_name":null},{"line":71,"address":[744537,744440,744628,744348],"length":1,"stats":{"Line":0},"fn_name":null},{"line":72,"address":[744601],"length":1,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[745059,744835,744980],"length":1,"stats":{"Line":0},"fn_name":null},{"line":78,"address":[745052,745162],"length":1,"stats":{"Line":0},"fn_name":null},{"line":80,"address":[639296,639836],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":81,"address":[639339],"length":1,"stats":{"Line":0},"fn_name":null},{"line":83,"address":[639410],"length":1,"stats":{"Line":0},"fn_name":null},{"line":84,"address":[639436,639604,639522,639689],"length":1,"stats":{"Line":0},"fn_name":null},{"line":89,"address":[745478,745674,745392,745575],"length":1,"stats":{"Line":0},"fn_name":null},{"line":90,"address":[745639,745796],"length":1,"stats":{"Line":0},"fn_name":null},{"line":91,"address":[745949],"length":1,"stats":{"Line":0},"fn_name":null},{"line":93,"address":[745963,746860],"length":1,"stats":{"Line":0},"fn_name":null},{"line":95,"address":[747124,746903],"length":1,"stats":{"Line":0},"fn_name":null},{"line":98,"address":[745989],"length":1,"stats":{"Line":0},"fn_name":null},{"line":99,"address":[746097,746280,746005,746194],"length":1,"stats":{"Line":0},"fn_name":null},{"line":104,"address":[746803,747413],"length":1,"stats":{"Line":0},"fn_name":null},{"line":106,"address":[747487],"length":1,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[747646,747737,747501],"length":1,"stats":{"Line":0},"fn_name":null},{"line":108,"address":[747710],"length":1,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[747443,747905,748137,748002],"length":1,"stats":{"Line":0},"fn_name":null},{"line":113,"address":[748066,748259],"length":1,"stats":{"Line":0},"fn_name":null},{"line":115,"address":[748344],"length":1,"stats":{"Line":0},"fn_name":null},{"line":116,"address":[748656,748376,748468,748565],"length":1,"stats":{"Line":0},"fn_name":null},{"line":117,"address":[748629],"length":1,"stats":{"Line":0},"fn_name":null},{"line":121,"address":[748829,748300,748998,748911],"length":1,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[748969,749114],"length":1,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[749325],"length":1,"stats":{"Line":0},"fn_name":null},{"line":126,"address":[749341,749427,749509,749586],"length":1,"stats":{"Line":0},"fn_name":null},{"line":127,"address":[749567],"length":1,"stats":{"Line":0},"fn_name":null},{"line":131,"address":[749838,749284,749930,749756],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":62},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","pproc.rs"],"content":"use std::error::Error;\nuse std::io;\nuse std::sync::mpsc::Receiver;\n\nuse log::{error, info};\n\nuse quicktap::drivers::tun::TunDevice;\nuse quicktap::drivers::tungeneric::GenericDriver;\n\nuse crate::command::PacketThreadCommand;\n\npub fn packet_thread(mut device: TunDevice, rx: Receiver\u003cPacketThreadCommand\u003e) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n loop {\n // Check command channel\n let command = match rx.try_recv() {\n Ok(d) =\u003e Some(d),\n Err(e) if matches!(e, std::sync::mpsc::TryRecvError::Empty) =\u003e None,\n Err(e) =\u003e return Err(e.into())\n };\n if let Some(cmd) = command {\n if let PacketThreadCommand::Stop = cmd {\n info!(\"packet thread: recieved command to stop by control process\");\n return Ok(())\n }\n }\n\n let packet = match device.read() {\n Ok(p) =\u003e Some(p),\n Err(e) =\u003e match e.kind() {\n io::ErrorKind::WouldBlock =\u003e None,\n _ =\u003e {\n error!(\"Error while reading packets from interface: {}\", e);\n return Err(e.into());\n }\n }\n };\n\n if let Some(p) = packet {\n info!(\"recv_packet_on_tun {:?}\", p.header);\n\n // parse and route\n\n }\n }\n}","traces":[{"line":12,"address":[668768,669994,670766],"length":1,"stats":{"Line":0},"fn_name":"packet_thread"},{"line":13,"address":[668805],"length":1,"stats":{"Line":0},"fn_name":null},{"line":15,"address":[668896,668821],"length":1,"stats":{"Line":0},"fn_name":null},{"line":16,"address":[668928],"length":1,"stats":{"Line":0},"fn_name":null},{"line":17,"address":[668961,669070],"length":1,"stats":{"Line":0},"fn_name":null},{"line":18,"address":[669027,669142],"length":1,"stats":{"Line":0},"fn_name":null},{"line":20,"address":[669094,669176],"length":1,"stats":{"Line":0},"fn_name":null},{"line":21,"address":[669192],"length":1,"stats":{"Line":0},"fn_name":null},{"line":22,"address":[670606,669237,670531,670449],"length":1,"stats":{"Line":0},"fn_name":null},{"line":23,"address":[670589],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[669218,669281],"length":1,"stats":{"Line":0},"fn_name":null},{"line":28,"address":[669305],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[669482,669388],"length":1,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[669503],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[669770,669536,669672],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[669730,669941],"length":1,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[670035],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[670223,670099],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":18}]};
var previousData = {"files":[{"path":["/","home","core","prj","e3t","elaeis4","quicktap","build.rs"],"content":"fn main() {\n build_info_build::build_script();\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","device","mod.rs"],"content":"//! A high-level implementation of the `WireGuard` protocol; does everything the kernel module does except for interfacing with the networking interfaces.\n//! Use the appropriate glue layer in `quicktap::drivers` to provide the tun/tap interface, and the mechanism in `quicktap::drivers::udp_listener` for working with the `UdpSocket`.","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","error.rs"],"content":"//! Defines the error type for the glue layer\nuse std::error::Error;\nuse std::fmt::{Display, Formatter};\n\n#[derive(Debug)]\n#[allow(clippy::module_name_repetitions)]\n/// Represents an error in the driver (glue) portion of quicktap\npub enum DriverError {\n /// An invalid packet type has been received on the interface, and quicktap does not know how to process it\n /// This is raised in the PREENTRY stage of packet processing\n InvalidPacketTypeRecvOnInterface\n}\nimpl Error for DriverError {}\nimpl Display for DriverError {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n match self {\n Self::InvalidPacketTypeRecvOnInterface =\u003e write!(f, \"Invalid packet type received on interface\")\n }\n }\n}","traces":[{"line":15,"address":[440576],"length":1,"stats":{"Line":0},"fn_name":"fmt"},{"line":17,"address":[440595],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":2},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","linux.rs"],"content":"//! A Linux implementation of the traits from `drivers::tungeneric`\n\nuse std::error::Error;\nuse std::io;\nuse std::io::{Read, Write};\n\nuse etherparse::IpHeader;\nuse tun::platform::Device;\n\nuse crate::drivers::tungeneric::{GenericDriver, GenericInterface, TunPacket};\n\n#[allow(clippy::module_name_repetitions)]\n/// Represents the internal state of a tun driver.\npub struct TunDevice {\n /// Contains the device handle of the tun device\n device: Device,\n /// A packet read buffer\n read_buf: [u8; 4096],\n /// Currently unused, for storing the offset into the read buffer to write to\n read_offset: usize,\n /// Another packet read buffer\n packet_buf: [u8; 4096],\n}\nimpl GenericDriver for TunDevice {\n fn new(config: \u0026GenericInterface) -\u003e Result\u003cSelf, Box\u003cdyn Error\u003e\u003e {\n let mut device_config = tun::Configuration::default();\n\n for address in \u0026config.addresses {\n device_config.address(address.address()).netmask(address.mask());\n }\n\n device_config.name(\u0026config.name);\n if let Some(mtu) = config.mtu {\n device_config.mtu(mtu);\n }\n let device = tun::create(\u0026device_config)?;\n device.set_nonblock()?;\n\n Ok(Self {\n device,\n read_buf: [0u8; 4096],\n read_offset: 0,\n packet_buf: [0u8; 4096],\n })\n }\n\n fn read(\u0026mut self) -\u003e Result\u003cTunPacket, io::Error\u003e {\n self.packet_buf = [0u8; 4096];\n let _ = self.device.read(\u0026mut self.packet_buf)?;\n let ip_header = IpHeader::from_slice(\u0026self.packet_buf);\n if let Ok((packet_header, _, _)) = ip_header {\n // Found a packet. Clear read buffers\n self.read_offset = 0;\n self.read_buf = [0u8; 4096];\n return Ok(TunPacket {\n header: packet_header,\n packet: self.packet_buf,\n })\n }\n\n Err(io::Error::new(io::ErrorKind::WouldBlock, \"No packets detected yet\"))\n }\n\n fn clear(\u0026mut self) {\n self.read_buf = [0u8; 4096];\n self.read_offset = 0;\n }\n\n fn write(\u0026mut self, packet: TunPacket) -\u003e Result\u003c(), io::Error\u003e {\n let _ = self.device.write(\u0026packet.packet)?;\n Ok(())\n }\n}\n\n","traces":[{"line":25,"address":[1557262,1556064],"length":1,"stats":{"Line":0},"fn_name":"new"},{"line":26,"address":[1556100],"length":1,"stats":{"Line":0},"fn_name":null},{"line":28,"address":[1556187,1556290,1556115],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[1556311],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[1556270],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[1556417],"length":1,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[1556441,1556481],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[1556698,1556457,1556483],"length":1,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[1556914,1556666,1557179],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[513521],"length":1,"stats":{"Line":0},"fn_name":null},{"line":40,"address":[513455],"length":1,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[1556997],"length":1,"stats":{"Line":0},"fn_name":null},{"line":43,"address":[1557017],"length":1,"stats":{"Line":0},"fn_name":null},{"line":47,"address":[1557900,1557312],"length":1,"stats":{"Line":0},"fn_name":"read"},{"line":48,"address":[1557356],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[1557486,1557380],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[1557456],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[1557527],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[1557586],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[514073],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[514145],"length":1,"stats":{"Line":0},"fn_name":null},{"line":56,"address":[514089],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[514120],"length":1,"stats":{"Line":0},"fn_name":null},{"line":61,"address":[514263,514349],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[514416],"length":1,"stats":{"Line":0},"fn_name":"clear"},{"line":65,"address":[514430],"length":1,"stats":{"Line":0},"fn_name":null},{"line":66,"address":[514451],"length":1,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[514464],"length":1,"stats":{"Line":0},"fn_name":"write"},{"line":70,"address":[514555,514479],"length":1,"stats":{"Line":0},"fn_name":null},{"line":71,"address":[514544],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":30},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","mod.rs"],"content":"//! Cross-platform tun/tap drivers for various platforms.\n\n#[cfg(unix)]\n#[path = \"linux.rs\"]\npub mod tun; // Tun/tap drivers for Linux\n\npub mod tungeneric;\n\npub mod udp_listener;\npub mod error;\n\n#[cfg(test)]\npub mod tests;","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // we want to panic, this is a test file\n#![allow(clippy::missing_errors_doc)]\n#![allow(clippy::missing_panics_doc)]\n#![allow(clippy::missing_safety_doc)]\n\nuse crate::drivers::error::DriverError;\n\n#[cfg(test)]\npub fn error_tests() {\n assert_eq!(format!(\"{}\", DriverError::InvalidPacketTypeRecvOnInterface), \"Invalid packet type received on interface\".to_string());\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","tungeneric.rs"],"content":"//! Generic traits and modules to represent a tun/tap device\n\nuse std::error::Error;\nuse std::io;\n\nuse cidr::IpInet;\nuse etherparse::IpHeader;\n\n#[derive(Debug)]\n/// A parsed packet from an interface\npub struct TunPacket {\n /// The parsed IPv4 or IPv6 header\n pub header: IpHeader,\n /// The raw packet data\n pub packet: [u8; 4096]\n}\n\n/// A trait to implement R/W on a tun driver\npub trait GenericDriver {\n /// Create a new device with the provided generic interface configuration\n /// # Errors\n /// This function may error if there is an error creating the device.\n fn new(config: \u0026GenericInterface) -\u003e Result\u003cSelf, Box\u003cdyn Error\u003e\u003e where Self: Sized;\n\n /// Attempt to read a packet from the interface. If no packet is found, append it to an internal buffer and return `WouldBlock`.\n /// Upon finding a successful packet inside the internal buffer, or the .clear() method being called, the internal buffer will be cleared.\n /// # Errors\n /// This function will return `WouldBlock` if a packet could not be read. This function may error if there is an error reading the interface.\n fn read(\u0026mut self) -\u003e Result\u003cTunPacket, io::Error\u003e;\n\n /// Clear any internal state of this interface.\n fn clear(\u0026mut self);\n\n /// Attempt to write a packet to the interface.\n /// # Errors\n /// This function will error if an error occured writing to the device.\n fn write(\u0026mut self, packet: TunPacket) -\u003e Result\u003c(), io::Error\u003e;\n}\n\n/// Generic interface config\npub struct GenericInterface {\n /// The ipv4/ipv6 addresses to be assigned to the interface\n pub addresses: Vec\u003cIpInet\u003e,\n /// The mtu to be assigned to the interface\n pub mtu: Option\u003ci32\u003e,\n /// The name of the virtual interface\n pub name: String\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","drivers","udp_listener.rs"],"content":"//! The logic for the WireGuard UDP socket.\n\nuse std::error::Error;\nuse std::io;\nuse std::net::UdpSocket;\nuse crate::drivers::error::DriverError;\nuse crate::stack::entry::PacketEntryStage;\nuse crate::stack::PacketProcessingStage;\n\n/// The maximum amount of bytes that can be taken up by a Handshake Initiation packet.\npub const MSG1_MAX_BYTES: usize = 148;\n/// The maximum amount of bytes that can be taken up by a Handshake Response packet.\npub const MSG2_MAX_BYTES: usize = 92;\n/// The maximum amount of bytes that can be taken up by a data packet.\npub const MSGDATA_MAX_BYTES: usize = 65567;\n/// The maximum amount of bytes that can be taken up by a cookie reply packet.\npub const MSGCOOKIE_MAX_BYTES: usize = 64;\n\n/// Represents the result of a socket processing round\npub enum SocketRoundResult {\n /// Represents that an io-specific error was received\n IoError(io::Error),\n /// Represents that a non-io-specific error was received\n GenericAnyError(Box\u003cdyn Error\u003e)\n}\n\n/// Run a socket update round on the (nonblocking!) UDP socket provided. Checks for any packets that may be present and send them off to get processed.\n/// **Warning!** This only runs *one* update round - therefore only one packet will be processed if any are present.\n/// If you're writing a frontend, this is probably not what you want. Use `qtap_socket_rounds_until_empty` instead.\n/// # Errors\n/// This function will error if a socket read fails or the processing of the packet fails. See `PacketEntryStage::process_packet()` for more details on packet processing.\npub fn qtap_socket_round(socket: \u0026mut UdpSocket) -\u003e Result\u003c(), SocketRoundResult\u003e {\n let mut packet_id = [0u8; 1];\n match socket.peek(\u0026mut packet_id) {\n Ok(_) =\u003e (),\n Err(e) =\u003e return Err(SocketRoundResult::IoError(e))\n }; // Intentionally peek into a 1-byte vector. This will NOT remove the datagram from the queue.\n // We WANT to discard the rest of the packet; right now we only care about the first byte so we know how much memory we need to allocate for the buffer.\n // The packet type tells us this.\n\n let buf_size = match packet_id[0] {\n 1 =\u003e MSG1_MAX_BYTES,\n 2 =\u003e MSG2_MAX_BYTES,\n 4 =\u003e MSGDATA_MAX_BYTES,\n 3 =\u003e MSGCOOKIE_MAX_BYTES,\n _ =\u003e return Err(SocketRoundResult::GenericAnyError(DriverError::InvalidPacketTypeRecvOnInterface.into()))\n };\n\n let mut packet_buf = vec![0u8; buf_size];\n let (read_bytes, from) = match socket.recv_from(\u0026mut packet_buf) {\n Ok(r) =\u003e r,\n Err(e) =\u003e return Err(SocketRoundResult::IoError(e))\n };\n\n let packet = packet_buf[..read_bytes].to_vec();\n\n match PacketEntryStage::process_packet(packet, \u0026from) {\n Ok(_) =\u003e Ok(()),\n Err(e) =\u003e Err(SocketRoundResult::GenericAnyError(e))\n }\n}\n\n/// Run several socket update rounds on the (nonblocking!) UDP socket provided. Will continually call `qtap_socket_round` in a loop until `io::WouldBlock` is returned.\n/// **Warning!** This runs as many socket rounds are needed to clear the UDP datagram queue. If there is a long queue, this function will take a very long time.\n/// If you only want to run one update, use `qtap_socket_round` instead.\n/// # Errors\n/// See `qtap_socket_round`\npub fn qtap_socket_rounds_until_empty(socket: \u0026mut UdpSocket) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n loop {\n match qtap_socket_round(socket) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n match e {\n SocketRoundResult::IoError(e) if matches!(e.kind(), io::ErrorKind::WouldBlock) =\u003e break,\n SocketRoundResult::GenericAnyError(e) =\u003e return Err(e),\n SocketRoundResult::IoError(e) =\u003e return Err(e.into())\n }\n }\n }\n }\n Ok(())\n}","traces":[{"line":32,"address":[417264,418187],"length":1,"stats":{"Line":0},"fn_name":"qtap_socket_round"},{"line":33,"address":[417294],"length":1,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[417316],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[417397],"length":1,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[417353],"length":1,"stats":{"Line":0},"fn_name":null},{"line":42,"address":[417485],"length":1,"stats":{"Line":0},"fn_name":null},{"line":43,"address":[417499],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[417513],"length":1,"stats":{"Line":0},"fn_name":null},{"line":45,"address":[417527],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[417468,417556],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[417608],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[417719,417631,417863],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[417767],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[417964],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[417911,418068],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[418213,418075],"length":1,"stats":{"Line":0},"fn_name":null},{"line":58,"address":[418220],"length":1,"stats":{"Line":0},"fn_name":null},{"line":59,"address":[418234],"length":1,"stats":{"Line":0},"fn_name":null},{"line":68,"address":[418336,418748,418717],"length":1,"stats":{"Line":0},"fn_name":"qtap_socket_rounds_until_empty"},{"line":69,"address":[418353,418389],"length":1,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[418363],"length":1,"stats":{"Line":0},"fn_name":null},{"line":72,"address":[418391],"length":1,"stats":{"Line":0},"fn_name":null},{"line":73,"address":[418406],"length":1,"stats":{"Line":0},"fn_name":null},{"line":74,"address":[418553,418622,418428],"length":1,"stats":{"Line":0},"fn_name":null},{"line":75,"address":[418452],"length":1,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[418695,418587],"length":1,"stats":{"Line":0},"fn_name":null},{"line":81,"address":[418658],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":27},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","lib.rs"],"content":"//! A simple, almost pure-rust, cross-platform `WireGuard` implementation.\n//! Designed to function similarly to boringtun, this crate has modules for cross-platform device drivers, the `Noise_IKpsk2` handshake, and cryptography constructs required for the above.\n\n#![deny(missing_docs)]\n\n#![warn(clippy::pedantic)]\n#![warn(clippy::nursery)]\n#![deny(clippy::unwrap_used)]\n#![deny(clippy::expect_used)]\n\n// This is an annoyance\n#![allow(clippy::must_use_candidate)]\n#![allow(clippy::module_name_repetitions)]\n\npub use cidr;\n\npub mod drivers;\npub mod qcrypto;\npub mod noise;\npub mod stack;\npub mod device;\n\n#[cfg(test)]\npub mod tests;\n\n/// Gets the compile-time versioning information for the engine build.\npub const fn version() -\u003e \u0026'static str {\n build_info::format!(\"quicktap engine v{} ({}) built at {} with {}\", $.crate_info.version, $.version_control.unwrap().git().unwrap().commit_short_id, $.timestamp, $.compiler)\n}\n","traces":[{"line":27,"address":[506624],"length":1,"stats":{"Line":1},"fn_name":"version"}],"covered":1,"coverable":1},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","data.rs"],"content":"//! `WireGuard` transport data messages. see 5.4.6\n\nuse crate::noise::error::{NoiseError, NoisePacketParseError};\nuse crate::noise::handshake::HandshakeState;\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt};\n\nfn pad_packet(p: \u0026Vec\u003cu8\u003e) -\u003e Vec\u003cu8\u003e {\n let mut padded = p.clone();\n padded.append(\u0026mut vec![0u8; 16 - (p.len() % 16)]);\n padded\n}\nfn unpad_packet(p: \u0026[u8]) -\u003e Vec\u003cu8\u003e {\n p.iter().rev().skip_while(|x| **x == 0).copied().collect::\u003cVec\u003cu8\u003e\u003e()\n}\n\n/// Given any arbitrary IP packet, pad and encrypt it with the current handshake state.\n/// # Errors\n/// This function will error if the encryption step is unsuccessful.\npub fn encapsulate(state: \u0026mut HandshakeState, packet: \u0026Vec\u003cu8\u003e) -\u003e Result\u003cVec\u003cu8\u003e, NoiseError\u003e {\n let packet = pad_packet(packet);\n let counter = state.n_send + 1;\n let packet_data = match qcrypto_aead(\u0026state.t_send, state.n_send + 1, \u0026packet, \u0026[]) {\n Ok(d) =\u003e d,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n let i_other = if state.we_are_initiator { state.i_r } else { state.i_i };\n\n let mut res = vec![4u8; 16 + packet_data.len()];\n res[1..4].copy_from_slice(\u0026[0u8; 3]);\n res[4..8].copy_from_slice(\u0026i_other.to_le_bytes());\n res[8..16].copy_from_slice(\u0026counter.to_le_bytes());\n res[16..16+packet_data.len()].copy_from_slice(\u0026packet_data);\n\n state.n_send += 1;\n\n Ok(res)\n}\n\n/// Given an encrypted, encapsulated IP packet, decrypt and unpad it with the current handshake state.\n/// # Errors\n/// This function will error if the decryption step is unsuccessful.\n/// # Panics\n/// This function, while containing unwraps for type conversions, is safe and will never panic.\n#[allow(clippy::unwrap_used)]\npub fn deencapsulate(state: \u0026mut HandshakeState, packet: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, NoiseError\u003e {\n if packet[0] != 4u8 {\n return Err(NoiseError::PacketParseError(NoisePacketParseError::WrongPacketType(4, packet[0] as usize)))\n }\n if packet[1..4] != [0u8; 3] {\n return Err(NoiseError::PacketParseError(NoisePacketParseError::MissingReserved))\n }\n let index_me = if state.we_are_initiator { state.i_i } else { state.i_r };\n if packet[4..8] != index_me.to_le_bytes() {\n return Err(NoiseError::PacketParseError(NoisePacketParseError::WrongIndex(index_me as usize, usize::from_le_bytes(packet[4..8].try_into().unwrap()))))\n }\n let counter = u64::from_le_bytes(packet[8..16].try_into().unwrap());\n\n if !state.bitfield.check_replay_window(counter) {\n // this packet is not okay! replayed or too old\n return Err(NoiseError::PacketReplayed)\n }\n\n let packet = match qcrypto_aead_decrypt(\u0026state.t_recv, counter, \u0026packet[16..], \u0026[]) {\n Ok(p) =\u003e p,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n state.bitfield.update_replay_window(counter);\n state.n_recv = counter;\n\n Ok(unpad_packet(\u0026packet))\n}","traces":[{"line":7,"address":[483943,483964,483712],"length":1,"stats":{"Line":1},"fn_name":"pad_packet"},{"line":8,"address":[483739],"length":1,"stats":{"Line":1},"fn_name":null},{"line":9,"address":[483802,483750],"length":1,"stats":{"Line":2},"fn_name":null},{"line":12,"address":[483984],"length":1,"stats":{"Line":1},"fn_name":"unpad_packet"},{"line":13,"address":[1606797,1606784],"length":1,"stats":{"Line":3},"fn_name":"{closure#0}"},{"line":19,"address":[485940,484144,485910],"length":1,"stats":{"Line":1},"fn_name":"encapsulate"},{"line":20,"address":[484210],"length":1,"stats":{"Line":1},"fn_name":null},{"line":21,"address":[484231,484321],"length":1,"stats":{"Line":1},"fn_name":null},{"line":22,"address":[484397,484278],"length":1,"stats":{"Line":2},"fn_name":null},{"line":23,"address":[484559],"length":1,"stats":{"Line":1},"fn_name":null},{"line":24,"address":[484674],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[484655,484767],"length":1,"stats":{"Line":1},"fn_name":null},{"line":29,"address":[484811,484878],"length":1,"stats":{"Line":2},"fn_name":null},{"line":30,"address":[485096,484958],"length":1,"stats":{"Line":2},"fn_name":null},{"line":31,"address":[485126],"length":1,"stats":{"Line":1},"fn_name":null},{"line":32,"address":[485326],"length":1,"stats":{"Line":1},"fn_name":null},{"line":33,"address":[485516],"length":1,"stats":{"Line":1},"fn_name":null},{"line":35,"address":[485877,485750],"length":1,"stats":{"Line":1},"fn_name":null},{"line":37,"address":[485795],"length":1,"stats":{"Line":1},"fn_name":null},{"line":46,"address":[487889,485968],"length":1,"stats":{"Line":1},"fn_name":"deencapsulate"},{"line":47,"address":[486039],"length":1,"stats":{"Line":1},"fn_name":null},{"line":48,"address":[486365,486196],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[486114,486419],"length":1,"stats":{"Line":2},"fn_name":null},{"line":51,"address":[486482],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[486459,486598],"length":1,"stats":{"Line":2},"fn_name":null},{"line":54,"address":[486650],"length":1,"stats":{"Line":1},"fn_name":null},{"line":55,"address":[486890],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[486806,487204],"length":1,"stats":{"Line":2},"fn_name":null},{"line":59,"address":[487302],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[487413],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[487493,487349],"length":1,"stats":{"Line":2},"fn_name":null},{"line":65,"address":[487561],"length":1,"stats":{"Line":1},"fn_name":null},{"line":66,"address":[487644],"length":1,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[487625],"length":1,"stats":{"Line":1},"fn_name":null},{"line":70,"address":[487761],"length":1,"stats":{"Line":1},"fn_name":null},{"line":72,"address":[487765],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":30,"coverable":36},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","error.rs"],"content":"//! `Noise_IKpsk2` handshake errors\n#![allow(clippy::module_name_repetitions)]\n\nuse std::error::Error;\nuse std::fmt::{Display, Formatter};\n\n/// Represents a error while doing Noise handshake operations\n#[derive(Debug, Clone)]\npub enum NoiseError {\n /// Represents an error while parsing a Noise packet\n PacketParseError(NoisePacketParseError),\n /// Represents an opaque error from ChaCha\n ChaCha20Error(chacha20poly1305::Error),\n /// Represents that the packet had a missing or incorrect cookie MAC.\n PacketUnauthenticated,\n /// Represents that the packet had the wrong i_i value\n UnrelatedHandshakePacket,\n /// Represents that the packet has been replayed and should be dropped\n PacketReplayed\n}\nimpl Error for NoiseError {}\nimpl Display for NoiseError {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n match \u0026self {\n Self::PacketParseError(err) =\u003e write!(f, \"{}\", err),\n Self::ChaCha20Error(error) =\u003e write!(f, \"Encryption error: {}\", error),\n Self::PacketUnauthenticated =\u003e write!(f, \"Unauthenticated packet\"),\n Self::UnrelatedHandshakePacket =\u003e write!(f, \"Unrelated handshake packet\"),\n Self::PacketReplayed =\u003e write!(f, \"Packet was replayed\")\n }\n }\n}\n\n/// Represents and error while parsing a Noise packet\n#[derive(Debug, Clone)]\npub enum NoisePacketParseError {\n /// Represents an invalid packet length while parsing a packet. The first was the expected length, the second was the actual length\n InvalidLength(usize, usize),\n /// Represents that the packet being parsed is of the incorrect type. The first value is the expected packet type, the second was the actual packet type\n WrongPacketType(usize, usize),\n /// Represents that the expected 3 bytes of reserved space are missing\n MissingReserved,\n /// Represents that the index expected to be present on the message is incorrect\n WrongIndex(usize, usize),\n /// Indicates that this packet has been replayed and should be ignored.\n ReplayAttack,\n}\nimpl Display for NoisePacketParseError {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n match \u0026self {\n Self::InvalidLength(expected, got) =\u003e write!(f, \"Invalid packet length: expected {} got {}\", expected, got),\n Self::WrongPacketType(expected, got) =\u003e write!(f, \"Incorrect packet type: expected {} got {}\", expected, got),\n Self::MissingReserved =\u003e write!(f, \"Missing reserved bytes\"),\n Self::WrongIndex(expected, got) =\u003e write!(f, \"Incorrect session index: expected {} got {}\", expected, got),\n Self::ReplayAttack =\u003e write!(f, \"!!! !!! THIS PACKET HAS BEEN REPLAYED !!! !!! Something fishy is going on.\")\n }\n }\n}","traces":[{"line":23,"address":[429408],"length":1,"stats":{"Line":0},"fn_name":"fmt"},{"line":24,"address":[429433],"length":1,"stats":{"Line":0},"fn_name":null},{"line":25,"address":[429881,429490],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[429525,429788],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[429565,429757],"length":1,"stats":{"Line":0},"fn_name":null},{"line":28,"address":[429730,429607],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[429646],"length":1,"stats":{"Line":0},"fn_name":null},{"line":49,"address":[429952],"length":1,"stats":{"Line":0},"fn_name":"fmt"},{"line":50,"address":[429977],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[430636,430013],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[430493,430076],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[430139,430468],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[430320,430181],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[430241],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":14},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","initiator.rs"],"content":"//! `Noise_IKpsk2` handshake initiator packets\n\nuse rand::{Rng, thread_rng};\nuse x25519_dalek::PublicKey;\n\nuse crate::noise::error::NoiseError;\nuse crate::noise::handshake::{HANDSHAKE_INITIATOR_CHAIN_KEY, HANDSHAKE_INITIATOR_CHAIN_KEY_HASH, HandshakeState, needs_cookie};\nuse crate::qcrypto::{LABEL_MAC1, timestamp};\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt};\nuse crate::qcrypto::hashes::{qcrypto_hash_twice, qcrypto_mac};\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm};\n\nstruct HandshakeInitiatorRaw {\n sender: [u8; 4],\n ephemeral: [u8; 32],\n static_pub: [u8; 32 + 16],\n timestamp: [u8; 12 + 16],\n mac1: [u8; 16],\n mac2: [u8; 16]\n}\nimpl HandshakeInitiatorRaw {\n fn to_bytes(\u0026self, session: \u0026HandshakeState) -\u003e [u8; 148] {\n let mut output = [0u8; 148];\n\n output[0] = 1u8;\n output[4..8].copy_from_slice(\u0026self.sender);\n output[8..40].copy_from_slice(\u0026self.ephemeral);\n output[40..88].copy_from_slice(\u0026self.static_pub);\n output[88..116].copy_from_slice(\u0026self.timestamp);\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026output[..116]);\n\n output[116..132].copy_from_slice(\u0026mac1);\n\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026output[..132]) } else { [0u8; 16] };\n\n output[132..148].copy_from_slice(\u0026mac2);\n\n output\n }\n\n #[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways\n fn from_bytes(bytes: [u8; 148]) -\u003e Self {\n Self {\n sender: bytes[4..8].try_into().unwrap(),\n ephemeral: bytes[8..40].try_into().unwrap(),\n static_pub: bytes[40..88].try_into().unwrap(),\n timestamp: bytes[88..116].try_into().unwrap(),\n mac1: bytes[116..132].try_into().unwrap(),\n mac2: bytes[132..148].try_into().unwrap()\n }\n }\n}\n\n/// Generate a handshake initiator packet and encrypt it using the given session state, starting a new handshake state\n/// # Errors\n/// This function will error if encryption was unsuccessful\n/// # Panics\n/// While containing unwraps, this function will never panic.\n#[allow(clippy::module_name_repetitions)]\n#[allow(clippy::unwrap_used)] // Safe because it is only used for type conversions in known safe ways\npub fn generate_handshake_init(session: \u0026mut HandshakeState) -\u003e Result\u003c[u8; 148], NoiseError\u003e {\n session.we_are_initiator = true;\n session.s_pub_i = PublicKey::from(session.s_priv_me);\n session.s_pub_r = session.s_pub_them;\n\n session.i_i = thread_rng().gen();\n\n let mut msg = HandshakeInitiatorRaw {\n sender: session.i_i.to_le_bytes(),\n ephemeral: [0u8; 32],\n static_pub: [0u8; 32 + 16],\n timestamp: [0u8; 12 + 16],\n mac1: [0u8; 16],\n mac2: [0u8; 16]\n };\n\n session.ck = HANDSHAKE_INITIATOR_CHAIN_KEY;\n session.h = HANDSHAKE_INITIATOR_CHAIN_KEY_HASH;\n session.h = qcrypto_hash_twice(\u0026session.h, session.s_pub_r.as_bytes());\n\n let eph_keypair = qcrypto_dh_generate_longterm();\n\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, eph_keypair.1.as_bytes())[0];\n session.e_pub_i = eph_keypair.1;\n session.e_priv_me = eph_keypair.0;\n\n msg.ephemeral = eph_keypair.1.to_bytes();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.ephemeral);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026session.ck, qcrypto_dh_longterm(\u0026session.e_priv_me, \u0026session.s_pub_r).as_bytes());\n session.ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n msg.static_pub = match qcrypto_aead(\u0026k, 0, session.s_pub_i.as_bytes(), \u0026session.h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }.try_into().unwrap();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.static_pub);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026session.ck, qcrypto_dh_longterm(session.s_priv_me, \u0026session.s_pub_r).as_bytes());\n session.ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n msg.timestamp = match qcrypto_aead(\u0026k, 0, \u0026timestamp().to_bytes(), \u0026session.h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }.try_into().unwrap();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.timestamp);\n\n Ok(msg.to_bytes(session))\n}\n\n/// Parse a handshake initiator packet and encrypt it using the given session state, updating the session state with decrypted and authenticated values\n/// # Errors\n/// This function will error if decryption was unsuccessful\n/// # Panics\n/// While containing unwraps, this function will never panic.\n#[allow(clippy::module_name_repetitions)]\n#[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways\npub fn parse_handshake_init(session: \u0026mut HandshakeState, packet: [u8; 148]) -\u003e Result\u003c(), NoiseError\u003e {\n let s_pub_i = session.s_pub_them;\n let s_pub_r = PublicKey::from(session.s_priv_me);\n\n let msg = HandshakeInitiatorRaw::from_bytes(packet);\n\n let i_i = u32::from_le_bytes(msg.sender);\n\n let ck = HANDSHAKE_INITIATOR_CHAIN_KEY;\n let h = HANDSHAKE_INITIATOR_CHAIN_KEY_HASH;\n let h = qcrypto_hash_twice(\u0026h, s_pub_r.as_bytes());\n\n let ephemeral_public = msg.ephemeral;\n let eph_pub = PublicKey::from(ephemeral_public);\n let e_pub_i = eph_pub;\n\n let ck = qcrypto_hkdf::\u003c1\u003e(\u0026ck, eph_pub.as_bytes())[0];\n\n let h = qcrypto_hash_twice(\u0026h, \u0026msg.ephemeral);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026ck, qcrypto_dh_longterm(session.s_priv_me, \u0026eph_pub).as_bytes());\n let ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n\n\n session.s_pub_i = PublicKey::from(\u003cVec\u003cu8\u003e as TryInto\u003c[u8; 32]\u003e\u003e::try_into(match qcrypto_aead_decrypt(\u0026k, 0, \u0026msg.static_pub, \u0026h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }).unwrap());\n\n let h = qcrypto_hash_twice(\u0026h, \u0026msg.static_pub);\n\n let ci_k_pair = qcrypto_hkdf::\u003c2\u003e(\u0026ck, qcrypto_dh_longterm(session.s_priv_me, \u0026session.s_pub_i).as_bytes());\n let ck = ci_k_pair[0];\n let k = ci_k_pair[1];\n\n // This unwrap is safe because the output length is a known constant with these inputs\n let _sent_timestamp: [u8; 12] = match qcrypto_aead_decrypt(\u0026k, 0, \u0026msg.timestamp, \u0026h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n }.try_into().unwrap();\n\n let h = qcrypto_hash_twice(\u0026h, \u0026msg.timestamp);\n\n // we need to check mac1 and mac2\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026packet[..116]);\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026packet[..132]) } else { [0u8; 16] };\n\n if mac1 != msg.mac1 || mac2 != msg.mac2 {\n return Err(NoiseError::PacketUnauthenticated)\n }\n\n session.h = h;\n session.ck = ck;\n session.e_pub_i = e_pub_i;\n session.s_pub_i = s_pub_i;\n session.s_pub_r = s_pub_r;\n session.i_i = i_i;\n session.we_are_initiator = false;\n\n Ok(())\n}","traces":[{"line":23,"address":[474064],"length":1,"stats":{"Line":1},"fn_name":"to_bytes"},{"line":24,"address":[474122],"length":1,"stats":{"Line":1},"fn_name":null},{"line":26,"address":[474142],"length":1,"stats":{"Line":2},"fn_name":null},{"line":27,"address":[474145],"length":1,"stats":{"Line":1},"fn_name":null},{"line":28,"address":[474263],"length":1,"stats":{"Line":1},"fn_name":null},{"line":29,"address":[474385],"length":1,"stats":{"Line":1},"fn_name":null},{"line":30,"address":[474507],"length":1,"stats":{"Line":2},"fn_name":null},{"line":32,"address":[474705],"length":1,"stats":{"Line":1},"fn_name":null},{"line":34,"address":[474853],"length":1,"stats":{"Line":1},"fn_name":null},{"line":36,"address":[474959],"length":1,"stats":{"Line":1},"fn_name":null},{"line":38,"address":[475222],"length":1,"stats":{"Line":1},"fn_name":null},{"line":44,"address":[475344],"length":1,"stats":{"Line":2},"fn_name":"from_bytes"},{"line":46,"address":[475374],"length":1,"stats":{"Line":1},"fn_name":null},{"line":47,"address":[475566],"length":1,"stats":{"Line":1},"fn_name":null},{"line":48,"address":[475684],"length":1,"stats":{"Line":1},"fn_name":null},{"line":49,"address":[475802],"length":1,"stats":{"Line":2},"fn_name":null},{"line":50,"address":[475920],"length":1,"stats":{"Line":1},"fn_name":null},{"line":51,"address":[476040],"length":1,"stats":{"Line":1},"fn_name":null},{"line":63,"address":[476707,476352],"length":1,"stats":{"Line":2},"fn_name":"generate_handshake_init"},{"line":64,"address":[476385],"length":1,"stats":{"Line":1},"fn_name":null},{"line":65,"address":[476400],"length":1,"stats":{"Line":2},"fn_name":null},{"line":66,"address":[476482],"length":1,"stats":{"Line":1},"fn_name":null},{"line":68,"address":[476602],"length":1,"stats":{"Line":2},"fn_name":null},{"line":71,"address":[476738],"length":1,"stats":{"Line":1},"fn_name":null},{"line":72,"address":[476770],"length":1,"stats":{"Line":2},"fn_name":null},{"line":73,"address":[476790],"length":1,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[476810],"length":1,"stats":{"Line":2},"fn_name":null},{"line":75,"address":[476830],"length":1,"stats":{"Line":1},"fn_name":null},{"line":76,"address":[476850],"length":1,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[477109],"length":1,"stats":{"Line":1},"fn_name":null},{"line":80,"address":[477165],"length":1,"stats":{"Line":2},"fn_name":null},{"line":81,"address":[477221],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[477349],"length":1,"stats":{"Line":2},"fn_name":null},{"line":85,"address":[477375,477471],"length":1,"stats":{"Line":3},"fn_name":null},{"line":86,"address":[477548],"length":1,"stats":{"Line":1},"fn_name":null},{"line":87,"address":[477610],"length":1,"stats":{"Line":2},"fn_name":null},{"line":89,"address":[477795],"length":1,"stats":{"Line":1},"fn_name":null},{"line":91,"address":[477863],"length":1,"stats":{"Line":2},"fn_name":null},{"line":93,"address":[477929],"length":1,"stats":{"Line":1},"fn_name":null},{"line":94,"address":[478097],"length":1,"stats":{"Line":2},"fn_name":null},{"line":95,"address":[478159],"length":1,"stats":{"Line":1},"fn_name":null},{"line":98,"address":[478478,478191,478375],"length":1,"stats":{"Line":5},"fn_name":null},{"line":99,"address":[478295],"length":1,"stats":{"Line":1},"fn_name":null},{"line":100,"address":[478387],"length":1,"stats":{"Line":0},"fn_name":null},{"line":101,"address":[478451],"length":1,"stats":{"Line":0},"fn_name":null},{"line":103,"address":[478569],"length":1,"stats":{"Line":2},"fn_name":null},{"line":105,"address":[478637],"length":1,"stats":{"Line":1},"fn_name":null},{"line":106,"address":[478798],"length":1,"stats":{"Line":2},"fn_name":null},{"line":107,"address":[478860],"length":1,"stats":{"Line":1},"fn_name":null},{"line":110,"address":[478892,479104,479215],"length":1,"stats":{"Line":3},"fn_name":null},{"line":111,"address":[479024],"length":1,"stats":{"Line":1},"fn_name":null},{"line":112,"address":[479116],"length":1,"stats":{"Line":0},"fn_name":null},{"line":113,"address":[479188],"length":1,"stats":{"Line":0},"fn_name":null},{"line":115,"address":[479290],"length":1,"stats":{"Line":2},"fn_name":null},{"line":117,"address":[479374],"length":1,"stats":{"Line":1},"fn_name":null},{"line":127,"address":[480377,479456],"length":1,"stats":{"Line":2},"fn_name":"parse_handshake_init"},{"line":128,"address":[479503],"length":1,"stats":{"Line":1},"fn_name":null},{"line":129,"address":[479563],"length":1,"stats":{"Line":1},"fn_name":null},{"line":131,"address":[479588],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[479627],"length":1,"stats":{"Line":2},"fn_name":null},{"line":135,"address":[479667],"length":1,"stats":{"Line":1},"fn_name":null},{"line":136,"address":[479727],"length":1,"stats":{"Line":2},"fn_name":null},{"line":137,"address":[479787],"length":1,"stats":{"Line":1},"fn_name":null},{"line":139,"address":[479846],"length":1,"stats":{"Line":2},"fn_name":null},{"line":140,"address":[479910],"length":1,"stats":{"Line":1},"fn_name":null},{"line":141,"address":[479996],"length":1,"stats":{"Line":2},"fn_name":null},{"line":143,"address":[480060],"length":1,"stats":{"Line":1},"fn_name":null},{"line":145,"address":[480183],"length":1,"stats":{"Line":2},"fn_name":null},{"line":147,"address":[480233],"length":1,"stats":{"Line":1},"fn_name":null},{"line":148,"address":[480403],"length":1,"stats":{"Line":2},"fn_name":null},{"line":149,"address":[480467],"length":1,"stats":{"Line":1},"fn_name":null},{"line":154,"address":[480531,480805,480711],"length":1,"stats":{"Line":4},"fn_name":null},{"line":155,"address":[480615],"length":1,"stats":{"Line":1},"fn_name":null},{"line":156,"address":[480742],"length":1,"stats":{"Line":0},"fn_name":null},{"line":159,"address":[480923],"length":1,"stats":{"Line":1},"fn_name":null},{"line":161,"address":[480975],"length":1,"stats":{"Line":1},"fn_name":null},{"line":162,"address":[481119],"length":1,"stats":{"Line":2},"fn_name":null},{"line":163,"address":[481183],"length":1,"stats":{"Line":1},"fn_name":null},{"line":166,"address":[481510,481427,481247],"length":1,"stats":{"Line":4},"fn_name":null},{"line":167,"address":[481331],"length":1,"stats":{"Line":1},"fn_name":null},{"line":168,"address":[481458],"length":1,"stats":{"Line":0},"fn_name":null},{"line":171,"address":[481538],"length":1,"stats":{"Line":1},"fn_name":null},{"line":175,"address":[481663],"length":1,"stats":{"Line":1},"fn_name":null},{"line":176,"address":[481808],"length":1,"stats":{"Line":2},"fn_name":null},{"line":178,"address":[482063],"length":1,"stats":{"Line":1},"fn_name":null},{"line":179,"address":[482851],"length":1,"stats":{"Line":0},"fn_name":null},{"line":182,"address":[482198],"length":1,"stats":{"Line":1},"fn_name":null},{"line":183,"address":[482322],"length":1,"stats":{"Line":1},"fn_name":null},{"line":184,"address":[482446],"length":1,"stats":{"Line":2},"fn_name":null},{"line":185,"address":[482570],"length":1,"stats":{"Line":1},"fn_name":null},{"line":186,"address":[482694],"length":1,"stats":{"Line":1},"fn_name":null},{"line":187,"address":[482818],"length":1,"stats":{"Line":1},"fn_name":null},{"line":188,"address":[482824],"length":1,"stats":{"Line":2},"fn_name":null},{"line":190,"address":[482831],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":87,"coverable":94},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","mod.rs"],"content":"//! `Noise_IKpsk2` handshake, specifically the way `WireGuard` defines it\nuse std::fmt::{Debug, Formatter};\n\nuse rand::rngs::OsRng;\nuse tai64::Tai64N;\nuse x25519_dalek::{PublicKey, StaticSecret};\nuse crate::noise::rfc6479::ShiftWindow;\n\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::timestamp;\n\npub mod initiator;\npub mod response;\n\n#[cfg(test)]\npub mod tests;\n\n/// The Blake2s hash of the construction\npub const HANDSHAKE_INITIATOR_CHAIN_KEY: [u8; 32] = [\n 96, 226, 109, 174, 243, 39, 239, 192, 46, 195, 53, 226, 160, 37, 210, 208, 22, 235, 66, 6, 248,\n 114, 119, 245, 45, 56, 209, 152, 139, 120, 205, 54,\n];\n\n/// The hashed chaining key\npub const HANDSHAKE_INITIATOR_CHAIN_KEY_HASH: [u8; 32] = [\n 34, 17, 179, 97, 8, 26, 197, 102, 105, 18, 67, 219, 69, 138, 213, 50, 45, 156, 108, 102, 34,\n 147, 232, 183, 14, 225, 156, 101, 186, 7, 158, 243,\n];\n\n/// Represents a cookie we got from the other peer\n#[derive(Debug)]\npub struct Cookie {\n time: Tai64N,\n cookie: [u8; 16]\n}\n\n/// Represents the internal handshake state. This does not really need to be messed with by outside users\n#[allow(missing_docs)]\n#[allow(clippy::module_name_repetitions)]\npub struct HandshakeState\u003c'a\u003e {\n pub h: [u8; 32],\n pub ck: [u8; 32],\n\n pub e_pub_i: PublicKey,\n pub e_pub_r: PublicKey,\n\n pub s_pub_i: PublicKey,\n pub s_pub_r: PublicKey,\n\n pub e_priv_me: StaticSecret,\n pub s_priv_me: \u0026'a StaticSecret,\n pub s_pub_them: PublicKey,\n\n pub i_i: u32,\n pub i_r: u32,\n\n pub q: [u8; 32],\n\n pub cookies: Vec\u003cCookie\u003e,\n\n pub t_send: [u8; 32],\n pub t_recv: [u8; 32],\n\n pub n_send: u64,\n pub n_recv: u64,\n\n pub we_are_initiator: bool,\n\n pub bitfield: ShiftWindow\n}\nimpl\u003c'a\u003e HandshakeState\u003c'a\u003e {\n /// Determines if the state variables of this `HandshakeState` are the same as another\n #[allow(clippy::suspicious_operation_groupings)]\n pub fn is_eq(\u0026self, other: \u0026HandshakeState) -\u003e bool {\n self.h == other.h \u0026\u0026 self.ck == other.ck \u0026\u0026 self.e_pub_i == other.e_pub_i \u0026\u0026 self.s_pub_i == other.s_pub_i \u0026\u0026 self.s_pub_r == other.s_pub_r \u0026\u0026 self.i_i == other.i_i \u0026\u0026 self.i_r == other.i_r\n }\n\n /// Zeroes out handshake state and derives data transport keys. The handshake must be completed and the other party must do this at the same time otherwise the handshake will be trashed and you have to start over.\n pub fn derive_transport(\u0026mut self) {\n let t_send_recv = qcrypto_hkdf::\u003c2\u003e(\u0026self.ck, \u0026[]);\n if self.we_are_initiator {\n self.t_send = t_send_recv[0];\n self.t_recv = t_send_recv[1];\n } else {\n self.t_send = t_send_recv[1];\n self.t_recv = t_send_recv[0];\n }\n\n self.n_send = 0;\n self.n_recv = 0;\n\n self.e_pub_r = PublicKey::from([0u8; 32]);\n self.e_priv_me = StaticSecret::from([0u8; 32]);\n self.e_pub_i = PublicKey::from([0u8; 32]);\n self.ck = [0u8; 32];\n }\n\n /// Create a new handshake state representing a brand-new handshake.\n /// This function initializes the important values with their appropriate initialization vectors, and zeroes out all other values.\n pub fn new(private_key: \u0026'a StaticSecret, other_pubkey: PublicKey, pre_shared_key: Option\u003c[u8; 32]\u003e) -\u003e Self {\n Self {\n h: [0u8; 32],\n ck: [0u8; 32],\n e_pub_i: PublicKey::from([0u8; 32]),\n e_pub_r: PublicKey::from([0u8; 32]),\n s_pub_i: PublicKey::from([0u8; 32]),\n s_pub_r: PublicKey::from([0u8; 32]),\n e_priv_me: StaticSecret::new(OsRng),\n s_priv_me: private_key,\n s_pub_them: other_pubkey,\n i_i: 0,\n i_r: 0,\n q: pre_shared_key.unwrap_or([0u8; 32]),\n cookies: vec![],\n t_send: [0u8; 32],\n t_recv: [0u8; 32],\n n_send: 1,\n n_recv: 1,\n we_are_initiator: false,\n bitfield: ShiftWindow::new()\n }\n }\n}\nimpl\u003c'a\u003e Debug for HandshakeState\u003c'a\u003e {\n fn fmt(\u0026self, f: \u0026mut Formatter\u003c'_\u003e) -\u003e std::fmt::Result {\n f.debug_struct(\"HandshakeState\")\n .field(\"h\", \u0026self.h)\n .field(\"ck\", \u0026self.ck)\n .field(\"e_pub_i\", \u0026self.e_pub_i)\n .field(\"s_pub_i\", \u0026self.s_pub_i)\n .field(\"s_pub_r\", \u0026self.s_pub_r)\n .field(\"s_pub_them\", \u0026self.s_pub_them)\n .field(\"i_i\", \u0026self.i_i)\n .field(\"i_r\", \u0026self.i_r)\n .field(\"cookies\", \u0026self.cookies).finish()\n }\n}\n\n/// Determines if a cookie MAC needs to be added to the packet being sent\npub fn needs_cookie(session: \u0026HandshakeState) -\u003e bool {\n if !session.cookies.is_empty() {\n let past_cookie_timeout = session.cookies[session.cookies.len()-1].time.duration_since(\u0026timestamp()).map_or(true, |t| t.as_secs() \u003e= 120);\n if !past_cookie_timeout {\n return true;\n }\n }\n false\n}","traces":[{"line":74,"address":[497696],"length":1,"stats":{"Line":1},"fn_name":"is_eq"},{"line":75,"address":[497720],"length":1,"stats":{"Line":1},"fn_name":null},{"line":79,"address":[498810,498080],"length":1,"stats":{"Line":1},"fn_name":"derive_transport"},{"line":80,"address":[498103],"length":1,"stats":{"Line":1},"fn_name":null},{"line":81,"address":[498384,498142],"length":1,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[498394],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[498482],"length":1,"stats":{"Line":1},"fn_name":null},{"line":85,"address":[498160],"length":1,"stats":{"Line":1},"fn_name":null},{"line":86,"address":[498272],"length":1,"stats":{"Line":1},"fn_name":null},{"line":89,"address":[498587],"length":1,"stats":{"Line":1},"fn_name":null},{"line":90,"address":[498595],"length":1,"stats":{"Line":1},"fn_name":null},{"line":92,"address":[498603],"length":1,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[498710,498852],"length":1,"stats":{"Line":2},"fn_name":null},{"line":94,"address":[498912],"length":1,"stats":{"Line":1},"fn_name":null},{"line":95,"address":[499019],"length":1,"stats":{"Line":1},"fn_name":null},{"line":100,"address":[499056,500327],"length":1,"stats":{"Line":1},"fn_name":"new"},{"line":102,"address":[499096],"length":1,"stats":{"Line":2},"fn_name":null},{"line":103,"address":[499113],"length":1,"stats":{"Line":1},"fn_name":null},{"line":104,"address":[499130],"length":1,"stats":{"Line":1},"fn_name":null},{"line":105,"address":[499169],"length":1,"stats":{"Line":1},"fn_name":null},{"line":106,"address":[499211],"length":1,"stats":{"Line":2},"fn_name":null},{"line":107,"address":[499253],"length":1,"stats":{"Line":1},"fn_name":null},{"line":108,"address":[499295],"length":1,"stats":{"Line":1},"fn_name":null},{"line":113,"address":[499341],"length":1,"stats":{"Line":1},"fn_name":null},{"line":114,"address":[499476],"length":1,"stats":{"Line":2},"fn_name":null},{"line":115,"address":[499483],"length":1,"stats":{"Line":1},"fn_name":null},{"line":116,"address":[499502],"length":1,"stats":{"Line":1},"fn_name":null},{"line":120,"address":[499526],"length":1,"stats":{"Line":1},"fn_name":null},{"line":125,"address":[500368],"length":1,"stats":{"Line":1},"fn_name":"fmt"},{"line":126,"address":[500422,500800,500662,500615,500709,500387,500474,500756,500521,500568],"length":1,"stats":{"Line":10},"fn_name":null},{"line":127,"address":[500415],"length":1,"stats":{"Line":1},"fn_name":null},{"line":128,"address":[500467],"length":1,"stats":{"Line":1},"fn_name":null},{"line":129,"address":[500514],"length":1,"stats":{"Line":1},"fn_name":null},{"line":130,"address":[500561],"length":1,"stats":{"Line":1},"fn_name":null},{"line":131,"address":[500608],"length":1,"stats":{"Line":1},"fn_name":null},{"line":132,"address":[500655],"length":1,"stats":{"Line":1},"fn_name":null},{"line":133,"address":[500702],"length":1,"stats":{"Line":1},"fn_name":null},{"line":134,"address":[500749],"length":1,"stats":{"Line":1},"fn_name":null},{"line":135,"address":[500796],"length":1,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[500864],"length":1,"stats":{"Line":2},"fn_name":"needs_cookie"},{"line":141,"address":[500878],"length":1,"stats":{"Line":1},"fn_name":null},{"line":142,"address":[500916],"length":1,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[501086],"length":1,"stats":{"Line":0},"fn_name":null},{"line":144,"address":[501097],"length":1,"stats":{"Line":0},"fn_name":null},{"line":147,"address":[500901],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":42,"coverable":45},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","response.rs"],"content":"//! `Noise_IKpsk2` handshake response packet\n\nuse x25519_dalek::PublicKey;\n\nuse crate::noise::error::NoiseError;\nuse crate::noise::handshake::{HandshakeState, needs_cookie};\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt};\nuse crate::qcrypto::hashes::{qcrypto_hash_twice, qcrypto_mac};\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::LABEL_MAC1;\nuse crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm};\n\nstruct HandshakeResponseRaw {\n sender: [u8; 4],\n receiver: [u8; 4],\n ephemeral: [u8; 32],\n empty: [u8; 16],\n mac1: [u8; 16],\n mac2: [u8; 16]\n}\nimpl HandshakeResponseRaw {\n fn to_bytes(\u0026self, session: \u0026mut HandshakeState) -\u003e [u8; 92] {\n let mut output_array = [0u8; 92];\n\n output_array[0] = 2u8;\n output_array[4..8].copy_from_slice(\u0026self.sender);\n output_array[8..12].copy_from_slice(\u0026self.receiver);\n output_array[12..44].copy_from_slice(\u0026self.ephemeral);\n output_array[44..60].copy_from_slice(\u0026self.empty);\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026output_array[..60]);\n\n output_array[60..76].copy_from_slice(\u0026mac1);\n\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026output_array[..76]) } else { [0u8; 16] };\n\n output_array[76..92].copy_from_slice(\u0026mac2);\n\n output_array\n }\n\n #[allow(clippy::unwrap_used)] // Only used for type conversions in known safe ways\n fn from_bytes(packet: [u8; 92]) -\u003e Self {\n Self {\n sender: packet[4..8].try_into().unwrap(),\n receiver: packet[8..12].try_into().unwrap(),\n ephemeral: packet[12..44].try_into().unwrap(),\n empty: packet[44..60].try_into().unwrap(),\n mac1: packet[60..76].try_into().unwrap(),\n mac2: packet[76..92].try_into().unwrap()\n }\n }\n}\n\n/// Creates a handshake response packet using the current active handshake session.\n/// # Errors\n/// This function will error if an encryption step is unsuccessful\n/// # Panics\n/// This function, while containing unwraps, will never panic.\n#[allow(clippy::unwrap_used)] // Used for known safe type conversions only\npub fn generate_handshake_response(session: \u0026mut HandshakeState) -\u003e Result\u003c[u8; 92], NoiseError\u003e {\n let eph_keypair = qcrypto_dh_generate_longterm();\n\n let mut msg = HandshakeResponseRaw {\n sender: [0u8; 4],\n receiver: [0u8; 4],\n ephemeral: [0u8; 32],\n empty: [0u8; 16],\n mac1: [0u8; 16],\n mac2: [0u8; 16]\n };\n\n msg.receiver = session.i_i.to_le_bytes();\n msg.sender = session.i_r.to_le_bytes();\n\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, eph_keypair.1.as_bytes())[0];\n\n msg.ephemeral = eph_keypair.1.to_bytes();\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.ephemeral);\n\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, qcrypto_dh_longterm(\u0026eph_keypair.0, \u0026session.e_pub_i).as_bytes())[0];\n session.ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, qcrypto_dh_longterm(\u0026eph_keypair.0, \u0026session.s_pub_i).as_bytes())[0];\n\n let cr_t_k = qcrypto_hkdf::\u003c3\u003e(\u0026session.ck, \u0026session.q);\n session.ck = cr_t_k[0];\n let t = cr_t_k[1];\n let k = cr_t_k[2];\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026t);\n\n println!(\"{:?} {:?} {:?}\", k, 0, session.h);\n msg.empty = match qcrypto_aead(\u0026k, 0, \u0026[], \u0026session.h) {\n Ok(s) =\u003e s.try_into().unwrap(),\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n session.h = qcrypto_hash_twice(\u0026session.h, \u0026msg.empty);\n\n Ok(msg.to_bytes(session))\n}\n\n/// Decrypts a handshake response packet using the current active handshake session.\n/// # Errors\n/// This function will error if a decryption step is unsuccessful\n/// # Panics\n/// This function, while containing unwraps, will never panic.\npub fn parse_handshake_response(session: \u0026mut HandshakeState, packet: [u8; 92]) -\u003e Result\u003c(), NoiseError\u003e {\n let msg = HandshakeResponseRaw::from_bytes(packet);\n\n let e_pub_r = PublicKey::from(msg.ephemeral);\n\n let mut ck = qcrypto_hkdf::\u003c1\u003e(\u0026session.ck, e_pub_r.as_bytes())[0];\n let mut h = qcrypto_hash_twice(\u0026session.h, \u0026msg.ephemeral);\n\n ck = qcrypto_hkdf::\u003c1\u003e(\u0026ck, qcrypto_dh_longterm(\u0026session.e_priv_me, \u0026e_pub_r).as_bytes())[0];\n ck = qcrypto_hkdf::\u003c1\u003e(\u0026ck, qcrypto_dh_longterm(session.s_priv_me, \u0026e_pub_r).as_bytes())[0];\n\n let cr_t_k = qcrypto_hkdf::\u003c3\u003e(\u0026ck, \u0026session.q);\n ck = cr_t_k[0];\n let t = cr_t_k[1];\n let k = cr_t_k[2];\n\n h = qcrypto_hash_twice(\u0026h, \u0026t);\n\n let empty = match qcrypto_aead_decrypt(\u0026k, 0, \u0026msg.empty, \u0026h) {\n Ok(s) =\u003e s,\n Err(e) =\u003e return Err(NoiseError::ChaCha20Error(e))\n };\n\n if !empty.is_empty() {\n return Err(NoiseError::PacketUnauthenticated)\n }\n\n h = qcrypto_hash_twice(\u0026h, \u0026msg.empty);\n\n let mac1: [u8; 16] = qcrypto_mac(\u0026qcrypto_hash_twice(LABEL_MAC1.as_bytes(), session.s_pub_i.as_bytes()), \u0026packet[..60]);\n let mac2 = if needs_cookie(session) { qcrypto_mac(\u0026session.cookies[session.cookies.len() - 1].cookie, \u0026packet[..76]) } else { [0u8; 16] };\n\n if mac1 != msg.mac1 || mac2 != msg.mac2 {\n return Err(NoiseError::PacketUnauthenticated)\n }\n\n if msg.receiver != session.i_i.to_le_bytes() {\n return Err(NoiseError::UnrelatedHandshakePacket)\n }\n\n session.e_pub_r = e_pub_r;\n session.ck = ck;\n session.h = h;\n\n Ok(())\n}","traces":[{"line":22,"address":[489920],"length":1,"stats":{"Line":2},"fn_name":"to_bytes"},{"line":23,"address":[489978],"length":1,"stats":{"Line":2},"fn_name":null},{"line":25,"address":[489998],"length":1,"stats":{"Line":2},"fn_name":null},{"line":26,"address":[490001],"length":1,"stats":{"Line":2},"fn_name":null},{"line":27,"address":[490119],"length":1,"stats":{"Line":2},"fn_name":null},{"line":28,"address":[490241],"length":1,"stats":{"Line":2},"fn_name":null},{"line":29,"address":[490363],"length":1,"stats":{"Line":2},"fn_name":null},{"line":31,"address":[490561],"length":1,"stats":{"Line":2},"fn_name":null},{"line":33,"address":[490709],"length":1,"stats":{"Line":2},"fn_name":null},{"line":35,"address":[490815],"length":1,"stats":{"Line":2},"fn_name":null},{"line":37,"address":[491078],"length":1,"stats":{"Line":2},"fn_name":null},{"line":43,"address":[491200],"length":1,"stats":{"Line":2},"fn_name":"from_bytes"},{"line":45,"address":[491230],"length":1,"stats":{"Line":2},"fn_name":null},{"line":46,"address":[491422],"length":1,"stats":{"Line":2},"fn_name":null},{"line":47,"address":[491617],"length":1,"stats":{"Line":2},"fn_name":null},{"line":48,"address":[491735],"length":1,"stats":{"Line":2},"fn_name":null},{"line":49,"address":[491855],"length":1,"stats":{"Line":2},"fn_name":null},{"line":50,"address":[491975],"length":1,"stats":{"Line":2},"fn_name":null},{"line":61,"address":[494461,492256,493187],"length":1,"stats":{"Line":1},"fn_name":"generate_handshake_response"},{"line":62,"address":[492295],"length":1,"stats":{"Line":1},"fn_name":null},{"line":65,"address":[492316],"length":1,"stats":{"Line":1},"fn_name":null},{"line":66,"address":[492327],"length":1,"stats":{"Line":1},"fn_name":null},{"line":67,"address":[492338],"length":1,"stats":{"Line":1},"fn_name":null},{"line":68,"address":[492357],"length":1,"stats":{"Line":1},"fn_name":null},{"line":69,"address":[492365],"length":1,"stats":{"Line":1},"fn_name":null},{"line":70,"address":[492373],"length":1,"stats":{"Line":1},"fn_name":null},{"line":73,"address":[492564,492489],"length":1,"stats":{"Line":2},"fn_name":null},{"line":74,"address":[492599],"length":1,"stats":{"Line":1},"fn_name":null},{"line":76,"address":[492669],"length":1,"stats":{"Line":1},"fn_name":null},{"line":78,"address":[492816],"length":1,"stats":{"Line":1},"fn_name":null},{"line":80,"address":[492887],"length":1,"stats":{"Line":1},"fn_name":null},{"line":82,"address":[492956],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[493206],"length":1,"stats":{"Line":1},"fn_name":null},{"line":85,"address":[493445],"length":1,"stats":{"Line":1},"fn_name":null},{"line":86,"address":[493494],"length":1,"stats":{"Line":2},"fn_name":null},{"line":87,"address":[493556],"length":1,"stats":{"Line":2},"fn_name":null},{"line":88,"address":[493588],"length":1,"stats":{"Line":2},"fn_name":null},{"line":90,"address":[493620],"length":1,"stats":{"Line":2},"fn_name":null},{"line":92,"address":[493705],"length":1,"stats":{"Line":2},"fn_name":null},{"line":93,"address":[493964,494284],"length":1,"stats":{"Line":4},"fn_name":null},{"line":94,"address":[494044,494246],"length":1,"stats":{"Line":4},"fn_name":null},{"line":95,"address":[494139],"length":1,"stats":{"Line":0},"fn_name":null},{"line":98,"address":[494308],"length":1,"stats":{"Line":2},"fn_name":null},{"line":100,"address":[494395],"length":1,"stats":{"Line":2},"fn_name":null},{"line":108,"address":[495144,494480],"length":1,"stats":{"Line":2},"fn_name":"parse_handshake_response"},{"line":109,"address":[494538],"length":1,"stats":{"Line":2},"fn_name":null},{"line":111,"address":[494577],"length":1,"stats":{"Line":2},"fn_name":null},{"line":113,"address":[494671],"length":1,"stats":{"Line":2},"fn_name":null},{"line":114,"address":[494816],"length":1,"stats":{"Line":2},"fn_name":null},{"line":116,"address":[494865],"length":1,"stats":{"Line":2},"fn_name":null},{"line":117,"address":[495178],"length":1,"stats":{"Line":2},"fn_name":null},{"line":119,"address":[495456],"length":1,"stats":{"Line":2},"fn_name":null},{"line":120,"address":[495493],"length":1,"stats":{"Line":2},"fn_name":null},{"line":121,"address":[495621],"length":1,"stats":{"Line":2},"fn_name":null},{"line":122,"address":[495685],"length":1,"stats":{"Line":2},"fn_name":null},{"line":124,"address":[495749],"length":1,"stats":{"Line":2},"fn_name":null},{"line":126,"address":[495851],"length":1,"stats":{"Line":2},"fn_name":null},{"line":127,"address":[495935],"length":1,"stats":{"Line":2},"fn_name":null},{"line":128,"address":[496029],"length":1,"stats":{"Line":0},"fn_name":null},{"line":131,"address":[496143,496007],"length":1,"stats":{"Line":4},"fn_name":null},{"line":132,"address":[496199],"length":1,"stats":{"Line":0},"fn_name":null},{"line":135,"address":[496149,496265],"length":1,"stats":{"Line":4},"fn_name":null},{"line":137,"address":[496413],"length":1,"stats":{"Line":2},"fn_name":null},{"line":138,"address":[496575],"length":1,"stats":{"Line":2},"fn_name":null},{"line":140,"address":[496835],"length":1,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[496980],"length":1,"stats":{"Line":0},"fn_name":null},{"line":144,"address":[496942,497041],"length":1,"stats":{"Line":4},"fn_name":null},{"line":145,"address":[497517],"length":1,"stats":{"Line":0},"fn_name":null},{"line":148,"address":[497111],"length":1,"stats":{"Line":2},"fn_name":null},{"line":149,"address":[497235],"length":1,"stats":{"Line":2},"fn_name":null},{"line":150,"address":[497359],"length":1,"stats":{"Line":2},"fn_name":null},{"line":152,"address":[497483],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":67,"coverable":72},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","handshake","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // this is a test harness, we want to panic\n\nuse crate::noise::handshake::HandshakeState;\nuse crate::noise::handshake::initiator::{parse_handshake_init, generate_handshake_init};\nuse crate::noise::handshake::response::{parse_handshake_response, generate_handshake_response};\nuse crate::qcrypto::pki::qcrypto_dh_generate_longterm;\n\n#[test]\nfn noise_halfhandshake_test() {\n let alice_keypair = qcrypto_dh_generate_longterm();\n let bob_keypair = qcrypto_dh_generate_longterm();\n\n let mut alice_session = HandshakeState::new(\u0026alice_keypair.0, bob_keypair.1, None);\n let mut bob_session = HandshakeState::new(\u0026bob_keypair.0, alice_keypair.1, None);\n\n let handshake_init = generate_handshake_init(\u0026mut alice_session).unwrap();\n parse_handshake_init(\u0026mut bob_session, handshake_init).unwrap();\n\n println!(\"{:?}\", alice_session);\n println!(\"{:?}\", bob_session);\n\n assert!(alice_session.is_eq(\u0026bob_session));\n}\n\n#[test]\nfn noise_nocookie_handshake_test() {\n let alice_keypair = qcrypto_dh_generate_longterm();\n let bob_keypair = qcrypto_dh_generate_longterm();\n\n let mut alice_session = HandshakeState::new(\u0026alice_keypair.0, bob_keypair.1, None);\n let mut bob_session = HandshakeState::new(\u0026bob_keypair.0, alice_keypair.1, None);\n\n let handshake_init = generate_handshake_init(\u0026mut alice_session).unwrap();\n parse_handshake_init(\u0026mut bob_session, handshake_init).unwrap();\n\n let handshake_response = generate_handshake_response(\u0026mut bob_session).unwrap();\n parse_handshake_response(\u0026mut alice_session, handshake_response).unwrap();\n\n println!(\"{:?}\", alice_session);\n println!(\"{:?}\", bob_session);\n\n assert!(alice_session.is_eq(\u0026bob_session));\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","mod.rs"],"content":"//! Contains structs and functions for serializing and deserializing different packets in the `Noise_IKpsk2` handshake and data frames\npub mod handshake;\npub mod error;\npub mod data;\n\n#[cfg(test)]\npub mod tests;\npub mod rfc6479;","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","rfc6479","mod.rs"],"content":"//! A Rust implementation of the anti-replay algorithm described in [RFC 6479](https://rfc-editor.org/rfc6479).\n\nconst SIZE_OF_INTEGER: usize = std::mem::size_of::\u003cusize\u003e() * 8;\nconst BITMAP_LEN: usize = 1024 / SIZE_OF_INTEGER;\nconst BITMAP_INDEX_MASK: u64 = BITMAP_LEN as u64 - 1;\nconst REDUNDANT_BIT_SHIFTS: u64 = 5;\nconst REDUNDANT_BITS: u64 = 1 \u003c\u003c REDUNDANT_BIT_SHIFTS;\nconst BITMAP_LOC_MASK: u64 = REDUNDANT_BITS - 1;\nconst WINDOW_SIZE: u64 = 512;\n\n#[derive(Default)]\n/// An implementation of the RFC6479 anti-replay algorithm\npub struct ShiftWindow {\n replaywin_lastseq: u64,\n replaywin_bitmap: [usize; BITMAP_LEN],\n}\n\nimpl ShiftWindow {\n /// Create a new ShiftWindow with default values\n pub fn new() -\u003e Self {\n Self::default()\n }\n\n /// Check if a given sequence value is okay given the current state of the shift window\n pub fn check_replay_window(\u0026self, seq: u64) -\u003e bool {\n println!(\"sequence {} {}\", seq, self.replaywin_lastseq);\n\n // first == 0 or wrapped\n if seq == 0 {\n return false;\n }\n\n // larger is always good\n if seq \u003e self.replaywin_lastseq {\n return true;\n }\n\n // too old\n if (seq + WINDOW_SIZE) \u003c self.replaywin_lastseq {\n return false;\n }\n\n let bit_location = seq \u0026 BITMAP_LOC_MASK;\n let index = (seq \u003e\u003e REDUNDANT_BIT_SHIFTS) \u0026 BITMAP_INDEX_MASK;\n\n self.replaywin_bitmap[index as usize] \u0026 (1 \u003c\u003c bit_location) == 0\n }\n\n /// Update the internal state of the replay window to mark the given sequence number as used and disallow future use of it.\n pub fn update_replay_window(\u0026mut self, seq: u64) {\n if !self.check_replay_window(seq) {\n return;\n }\n\n let index = seq \u003e\u003e REDUNDANT_BIT_SHIFTS;\n\n if seq \u003e self.replaywin_lastseq {\n let index_cur = self.replaywin_lastseq \u003e\u003e REDUNDANT_BIT_SHIFTS;\n let mut diff = index - index_cur;\n\n if diff \u003e BITMAP_LEN as u64 {\n diff = BITMAP_LEN as u64;\n }\n\n for id in 0..diff {\n let iindex = (id + index_cur + 1) \u0026 BITMAP_INDEX_MASK;\n self.replaywin_bitmap[iindex as usize] = 0;\n }\n\n self.replaywin_lastseq = seq;\n }\n\n let index = index \u0026 BITMAP_INDEX_MASK;\n let bit_location = seq \u0026 BITMAP_LOC_MASK;\n\n self.replaywin_bitmap[index as usize] |= 1 \u003c\u003c bit_location;\n }\n}\n\n#[cfg(test)]\nmod tests {\n use crate::noise::rfc6479::ShiftWindow;\n\n #[test]\n pub fn rfc6479_tests() {\n let mut shiftwin = ShiftWindow::new();\n\n assert!(!shiftwin.check_replay_window(0));\n assert!(shiftwin.check_replay_window(1));\n shiftwin.update_replay_window(1);\n assert!(!shiftwin.check_replay_window(1));\n shiftwin.update_replay_window(329_846_324_987);\n assert!(!shiftwin.check_replay_window(2));\n }\n}","traces":[{"line":20,"address":[1613392],"length":1,"stats":{"Line":2},"fn_name":"new"},{"line":21,"address":[1613400],"length":1,"stats":{"Line":1},"fn_name":null},{"line":25,"address":[1613424],"length":1,"stats":{"Line":1},"fn_name":"check_replay_window"},{"line":26,"address":[1613449],"length":1,"stats":{"Line":1},"fn_name":null},{"line":29,"address":[1613590],"length":1,"stats":{"Line":1},"fn_name":null},{"line":30,"address":[1613598],"length":1,"stats":{"Line":0},"fn_name":null},{"line":34,"address":[1613610],"length":1,"stats":{"Line":1},"fn_name":null},{"line":35,"address":[1613645],"length":1,"stats":{"Line":1},"fn_name":null},{"line":39,"address":[1613677,1613620],"length":1,"stats":{"Line":0},"fn_name":null},{"line":40,"address":[488696],"length":1,"stats":{"Line":0},"fn_name":null},{"line":43,"address":[488658],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[488680,488708],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[488725,488859],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[1613952],"length":1,"stats":{"Line":1},"fn_name":"update_replay_window"},{"line":51,"address":[1613985],"length":1,"stats":{"Line":1},"fn_name":null},{"line":55,"address":[1614044,1614010],"length":1,"stats":{"Line":2},"fn_name":null},{"line":57,"address":[488995,489333],"length":1,"stats":{"Line":2},"fn_name":null},{"line":58,"address":[489088],"length":1,"stats":{"Line":1},"fn_name":null},{"line":59,"address":[1614175,1614210],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[489244,489143],"length":1,"stats":{"Line":1},"fn_name":null},{"line":62,"address":[489235],"length":1,"stats":{"Line":0},"fn_name":null},{"line":65,"address":[489511,489183,489256,489343],"length":1,"stats":{"Line":2},"fn_name":null},{"line":66,"address":[489462,489359],"length":1,"stats":{"Line":0},"fn_name":null},{"line":67,"address":[489502,489449,489521],"length":1,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[489330],"length":1,"stats":{"Line":1},"fn_name":null},{"line":73,"address":[489010],"length":1,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[489027],"length":1,"stats":{"Line":1},"fn_name":null},{"line":76,"address":[489549,489627,489039],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":19,"coverable":28},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","noise","tests.rs"],"content":"#![allow(clippy::unwrap_used)]\n#![allow(clippy::pedantic)]\n\nuse crate::noise::data::{deencapsulate, encapsulate};\nuse crate::noise::handshake::HandshakeState;\nuse crate::noise::handshake::initiator::{parse_handshake_init, generate_handshake_init};\nuse crate::noise::handshake::response::{parse_handshake_response, generate_handshake_response};\nuse crate::qcrypto::pki::qcrypto_dh_generate_longterm;\n\n#[test]\npub fn noise_transport_test() {\n let alice_keypair = qcrypto_dh_generate_longterm();\n let bob_keypair = qcrypto_dh_generate_longterm();\n\n let mut alice_session = HandshakeState::new(\u0026alice_keypair.0, bob_keypair.1, None);\n let mut bob_session = HandshakeState::new(\u0026bob_keypair.0, alice_keypair.1, None);\n\n let handshake_init = generate_handshake_init(\u0026mut alice_session).unwrap();\n parse_handshake_init(\u0026mut bob_session, handshake_init).unwrap();\n\n let handshake_response = generate_handshake_response(\u0026mut bob_session).unwrap();\n parse_handshake_response(\u0026mut alice_session, handshake_response).unwrap();\n\n alice_session.derive_transport();\n bob_session.derive_transport();\n\n assert!(alice_session.is_eq(\u0026bob_session));\n\n let packet_abc = vec![42u8; 17];\n let packet_encapsulated = encapsulate(\u0026mut alice_session, \u0026packet_abc).unwrap();\n\n let packet_abc_deencapsulated = deencapsulate(\u0026mut bob_session, \u0026packet_encapsulated).unwrap();\n\n assert_eq!(packet_abc, packet_abc_deencapsulated)\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","aead.rs"],"content":"//! Various functions for `ChaCha20Poly1305` stream ciphers\n\nuse chacha20poly1305::{ChaCha20Poly1305, Error, KeyInit, XChaCha20Poly1305};\nuse chacha20poly1305::aead::{Aead, Nonce, Payload};\n\n/// Encrypt the plaintext with the given parameters using `ChaCha20Poly1305`\n/// # Errors\n/// This function will error if the encryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::module_name_repetitions)]\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_aead(key: \u0026[u8; 32], counter: u64, plaintext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut nonce_bytes = [0u8; 12];\n nonce_bytes[4..].copy_from_slice(\u0026counter.to_le_bytes());\n let mut payload = Payload::from(plaintext);\n payload.aad = authtext;\n\n cipher.encrypt(\u0026Nonce::\u003cChaCha20Poly1305\u003e::from(nonce_bytes), payload)\n}\n\n/// Decrypt the ciphertext with the given parameters using `ChaCha20Poly1305`\n/// # Errors\n/// This function will error if the decryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_aead_decrypt(key: \u0026[u8; 32], counter: u64, ciphertext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = ChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut nonce_bytes = [0u8; 12];\n nonce_bytes[4..].copy_from_slice(\u0026counter.to_le_bytes());\n let mut payload = Payload::from(ciphertext);\n payload.aad = authtext;\n\n cipher.decrypt(\u0026Nonce::\u003cChaCha20Poly1305\u003e::from(nonce_bytes), payload)\n}\n\n/// Encrypt the ciphertext with the given parameters using `XChaCha20Poly1305`\n/// # Errors\n/// This function will error if the decryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_xaead(key: \u0026[u8; 32], nonce: \u0026[u8; 24], plaintext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut payload = Payload::from(plaintext);\n payload.aad = authtext;\n\n cipher.encrypt(Nonce::\u003cXChaCha20Poly1305\u003e::from_slice(nonce), payload)\n}\n\n/// Decrypt the ciphertext with the given parameters using `XChaCha20Poly1305`\n/// # Errors\n/// This function will error if the decryption was unsuccessful\n/// # Panics\n/// This function, while having an .unwrap() call, will never panic because the key is a fixed, correctly sized array.\n#[allow(clippy::unwrap_used)] // Safe becuase the key is a fixed size array\npub fn qcrypto_xaead_decrypt(key: \u0026[u8; 32], nonce: \u0026[u8; 24], ciphertext: \u0026[u8], authtext: \u0026[u8]) -\u003e Result\u003cVec\u003cu8\u003e, Error\u003e {\n let cipher = XChaCha20Poly1305::new_from_slice(key).unwrap();\n let mut payload = Payload::from(ciphertext);\n payload.aad = authtext;\n\n cipher.decrypt(Nonce::\u003cXChaCha20Poly1305\u003e::from_slice(nonce), payload)\n}","traces":[{"line":13,"address":[427424,428005],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_aead"},{"line":14,"address":[427522],"length":1,"stats":{"Line":1},"fn_name":null},{"line":15,"address":[427565],"length":1,"stats":{"Line":1},"fn_name":null},{"line":16,"address":[427588,427706],"length":1,"stats":{"Line":2},"fn_name":null},{"line":17,"address":[427798],"length":1,"stats":{"Line":1},"fn_name":null},{"line":18,"address":[427827],"length":1,"stats":{"Line":1},"fn_name":null},{"line":20,"address":[427933,427843],"length":1,"stats":{"Line":2},"fn_name":null},{"line":29,"address":[428629,428048],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_aead_decrypt"},{"line":30,"address":[428146],"length":1,"stats":{"Line":1},"fn_name":null},{"line":31,"address":[428189],"length":1,"stats":{"Line":1},"fn_name":null},{"line":32,"address":[428212,428330],"length":1,"stats":{"Line":2},"fn_name":null},{"line":33,"address":[428422],"length":1,"stats":{"Line":1},"fn_name":null},{"line":34,"address":[428451],"length":1,"stats":{"Line":1},"fn_name":null},{"line":36,"address":[428557,428467],"length":1,"stats":{"Line":2},"fn_name":null},{"line":45,"address":[428995,428672],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_xaead"},{"line":46,"address":[428770],"length":1,"stats":{"Line":1},"fn_name":null},{"line":47,"address":[428817],"length":1,"stats":{"Line":1},"fn_name":null},{"line":48,"address":[428888],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[428909],"length":1,"stats":{"Line":1},"fn_name":null},{"line":59,"address":[429363,429040],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_xaead_decrypt"},{"line":60,"address":[429138],"length":1,"stats":{"Line":1},"fn_name":null},{"line":61,"address":[429185],"length":1,"stats":{"Line":1},"fn_name":null},{"line":62,"address":[429256],"length":1,"stats":{"Line":1},"fn_name":null},{"line":64,"address":[429277],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":24,"coverable":24},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","hashes.rs"],"content":"//! Various hash functions\n\nuse blake2::{Blake2s256, Blake2sMac, Digest};\nuse blake2::digest::{FixedOutput, KeyInit, Update};\nuse hmac::SimpleHmac;\n\ntype HmacBlake2s = SimpleHmac\u003cBlake2s256\u003e;\n\n/// Given a varied length input, produce a 32-byte Blake2s hash digest\npub fn qcrypto_hash(input: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = Blake2s256::new();\n Update::update(\u0026mut hasher, input);\n hasher.finalize().into()\n}\n\n/// Given two varied length inputs, produce a 32-byte Blake2s hash digest\npub fn qcrypto_hash_twice(input: \u0026[u8], input2: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = Blake2s256::new();\n Update::update(\u0026mut hasher, input);\n Update::update(\u0026mut hasher, input2);\n hasher.finalize().into()\n}\n\n/// Given a varied length MAC key and a varied length input, produce a 16-byte MAC digest using Blake2s\n/// # Panics\n/// This function will panic if the key is an incorrect size.\n#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap\npub fn qcrypto_mac(key: \u0026[u8], input: \u0026[u8]) -\u003e [u8; 16] {\n let mut hasher = Blake2sMac::new_from_slice(key).unwrap();\n hasher.update(input);\n hasher.finalize_fixed().into()\n}\n\n/// Given a varied length HMAC key and a varied length input, produce a 32-byte HMAC digest using Blake2s\n/// # Panics\n/// This function will panic if the key is an incorrect size.\n#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap\npub fn qcrypto_hmac(key: \u0026[u8], input: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();\n Update::update(\u0026mut hasher, input);\n hasher.finalize_fixed().into()\n}\n\n/// Given a varied length HMAC key and two varied length inputs, produce a 32-byte HMAC digest using Blake2s.\n/// This does essentially the same thing as concatenating input2 to input and calling `qcrypto_hmac` on that.\n/// # Panics\n/// This function will panic if the key is an incorrect size.\n#[allow(clippy::unwrap_used)] // Safe because a panic indicates a bug in quicktap\npub fn qcrypto_hmac_twice(key: \u0026[u8], input: \u0026[u8], input2: \u0026[u8]) -\u003e [u8; 32] {\n let mut hasher = HmacBlake2s::new_from_slice(key).unwrap();\n Update::update(\u0026mut hasher, input);\n Update::update(\u0026mut hasher, input2);\n hasher.finalize_fixed().into()\n}","traces":[{"line":10,"address":[1621392],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_hash"},{"line":11,"address":[1621435],"length":1,"stats":{"Line":1},"fn_name":null},{"line":12,"address":[1621456],"length":1,"stats":{"Line":1},"fn_name":null},{"line":13,"address":[1621467],"length":1,"stats":{"Line":1},"fn_name":null},{"line":17,"address":[1621552],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_hash_twice"},{"line":18,"address":[1621621],"length":1,"stats":{"Line":1},"fn_name":null},{"line":19,"address":[433193],"length":1,"stats":{"Line":1},"fn_name":null},{"line":20,"address":[433213],"length":1,"stats":{"Line":1},"fn_name":null},{"line":21,"address":[433223],"length":1,"stats":{"Line":1},"fn_name":null},{"line":28,"address":[433312],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_mac"},{"line":29,"address":[433370],"length":1,"stats":{"Line":1},"fn_name":null},{"line":30,"address":[433417],"length":1,"stats":{"Line":1},"fn_name":null},{"line":31,"address":[433427],"length":1,"stats":{"Line":1},"fn_name":null},{"line":38,"address":[433504],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_hmac"},{"line":39,"address":[433563],"length":1,"stats":{"Line":1},"fn_name":null},{"line":41,"address":[433650],"length":1,"stats":{"Line":1},"fn_name":null},{"line":49,"address":[433728],"length":1,"stats":{"Line":2},"fn_name":"qcrypto_hmac_twice"},{"line":50,"address":[433820],"length":1,"stats":{"Line":1},"fn_name":null},{"line":53,"address":[433955],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":19,"coverable":19},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","hkdf.rs"],"content":"//! An implementation of the HKDF algorithm\n\nuse crate::qcrypto::hashes::{qcrypto_hmac, qcrypto_hmac_twice};\n\n#[allow(clippy::module_name_repetitions)]\n/// Given a constant order N, a varied length key and varied length input, perform the HKDF algorithm and produce an N-array of 32-byte arrays.\npub fn qcrypto_hkdf\u003cconst N: usize\u003e(key: \u0026[u8], input: \u0026[u8]) -\u003e [[u8; 32]; N] {\n let mut result_array = [[0u8; 32]; N];\n\n let t0 = qcrypto_hmac(key, input);\n let t1 = qcrypto_hmac(\u0026t0, \u0026[1u8]);\n\n result_array[0] = t1;\n\n for n in 1..N {\n result_array[n] = qcrypto_hmac_twice(\u0026t0, \u0026result_array[n-1], \u0026n.to_be_bytes());\n }\n\n result_array\n}","traces":[{"line":7,"address":[410848,412608,411728],"length":1,"stats":{"Line":5},"fn_name":"qcrypto_hkdf\u003c1\u003e"},{"line":8,"address":[412677,410917,411797],"length":1,"stats":{"Line":4},"fn_name":null},{"line":10,"address":[411942,411062,412822],"length":1,"stats":{"Line":5},"fn_name":null},{"line":11,"address":[411955,411075,412835],"length":1,"stats":{"Line":4},"fn_name":null},{"line":13,"address":[411994,411114,412874],"length":1,"stats":{"Line":5},"fn_name":null},{"line":15,"address":[412990,411230,412257,413137,411377,412110,411681,413441,412561],"length":1,"stats":{"Line":11},"fn_name":null},{"line":16,"address":[413451,412571,411398,412278,413158,411691],"length":1,"stats":{"Line":3},"fn_name":null},{"line":19,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":7,"coverable":8},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","mod.rs"],"content":"//! A module to implement all of the various cryptography constructs required to implement `WireGuard`\n\nuse tai64::Tai64N;\n\npub mod hashes;\npub mod pki;\npub mod aead;\n\n#[cfg(test)]\npub mod tests;\npub mod hkdf;\n\n/// Get the current TAI64N timestamp\npub fn timestamp() -\u003e Tai64N {\n Tai64N::now()\n}\n\n/// The cryptography handshake construction identifier\npub const CONSTURCTION: \u0026str = \"Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s\";\n/// The `WireGuard` protocol identifier\npub const IDENTIFIER: \u0026str = \"WireGuard v1 zx2c4 Jason@zx2c4.com\";\n/// The MAC1 cookie label\npub const LABEL_MAC1: \u0026str = \"mac1----\";\n/// The COOKIE1 cookie label\npub const LABEL_COOKIE: \u0026str = \"cookie--\";","traces":[{"line":14,"address":[467296],"length":1,"stats":{"Line":1},"fn_name":"timestamp"},{"line":15,"address":[467300],"length":1,"stats":{"Line":2},"fn_name":null}],"covered":2,"coverable":2},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","pki.rs"],"content":"//! Various public-key cryptography functions\n\nuse rand::rngs::OsRng;\nuse x25519_dalek::{EphemeralSecret, PublicKey, SharedSecret, StaticSecret};\n\ntype LongtermKeypair = (StaticSecret, PublicKey);\n\n/// Generate a X25519 keypair\npub fn qcrypto_dh_generate_longterm() -\u003e LongtermKeypair {\n let secret = StaticSecret::new(OsRng);\n let public = PublicKey::from(\u0026secret);\n (secret, public)\n}\n\n/// Perform Elliptic-Curve Diffie-Hellman between a secret and public key to get a shared secret value\npub fn qcrypto_dh_longterm(secret: \u0026StaticSecret, public: \u0026PublicKey) -\u003e SharedSecret {\n secret.diffie_hellman(public)\n}\n\n\ntype EphemeralKeypair = (EphemeralSecret, PublicKey);\n\n/// Generate a X25519 keypair\npub fn qcrypto_dh_generate_ephemeral() -\u003e EphemeralKeypair {\n let secret = EphemeralSecret::new(OsRng);\n let public = PublicKey::from(\u0026secret);\n (secret, public)\n}\n\n/// Perform Elliptic-Curve Diffie-Hellman between a secret and public key to get a shared secret value\npub fn qcrypto_dh_ephemeral(secret: EphemeralSecret, public: \u0026PublicKey) -\u003e SharedSecret {\n secret.diffie_hellman(public)\n}","traces":[{"line":9,"address":[439732,439456],"length":1,"stats":{"Line":3},"fn_name":"qcrypto_dh_generate_longterm"},{"line":10,"address":[439473],"length":1,"stats":{"Line":4},"fn_name":null},{"line":11,"address":[439483],"length":1,"stats":{"Line":1},"fn_name":null},{"line":12,"address":[439555],"length":1,"stats":{"Line":2},"fn_name":null},{"line":16,"address":[439760],"length":1,"stats":{"Line":1},"fn_name":"qcrypto_dh_longterm"},{"line":17,"address":[439781],"length":1,"stats":{"Line":1},"fn_name":null},{"line":24,"address":[440084,439808],"length":1,"stats":{"Line":0},"fn_name":"qcrypto_dh_generate_ephemeral"},{"line":25,"address":[439825],"length":1,"stats":{"Line":0},"fn_name":null},{"line":26,"address":[439835],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[439907],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[440112],"length":1,"stats":{"Line":0},"fn_name":"qcrypto_dh_ephemeral"},{"line":32,"address":[440129],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":6,"coverable":12},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","qcrypto","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // we want to panic, this is a test file\n\nuse hex_lit::hex;\nuse x25519_dalek::PublicKey;\n\nuse crate::qcrypto::{CONSTURCTION, IDENTIFIER};\nuse crate::qcrypto::aead::{qcrypto_aead, qcrypto_aead_decrypt, qcrypto_xaead, qcrypto_xaead_decrypt};\nuse crate::qcrypto::hashes::{qcrypto_hash, qcrypto_hash_twice, qcrypto_hmac, qcrypto_mac};\nuse crate::qcrypto::hkdf::qcrypto_hkdf;\nuse crate::qcrypto::pki::{qcrypto_dh_generate_longterm, qcrypto_dh_longterm};\n\n#[test]\nfn qcrypto_hash_test() {\n assert_eq!(qcrypto_hash(\u0026[0u8; 32]), hex!(\"320b5ea99e653bc2b593db4130d10a4efd3a0b4cc2e1a6672b678d71dfbd33ad\"));\n assert_eq!(qcrypto_hash(CONSTURCTION.as_bytes()), [\n 96, 226, 109, 174, 243, 39, 239, 192, 46, 195, 53, 226, 160, 37, 210, 208, 22, 235, 66, 6, 248,\n 114, 119, 245, 45, 56, 209, 152, 139, 120, 205, 54,\n ]);\n assert_eq!(qcrypto_hash_twice(\u0026qcrypto_hash(CONSTURCTION.as_bytes()), IDENTIFIER.as_bytes()), [\n 34, 17, 179, 97, 8, 26, 197, 102, 105, 18, 67, 219, 69, 138, 213, 50, 45, 156, 108, 102, 34,\n 147, 232, 183, 14, 225, 156, 101, 186, 7, 158, 243,\n ]);\n}\n#[test]\nfn qcrypto_mac_test() {\n assert_eq!(qcrypto_mac(\u0026[0u8; 32], \u0026[0u8; 32]), hex!(\"086de86cfb256a2bc40740062bcf4dcc\"));\n}\n#[test]\nfn qcrypto_hmac_test() {\n assert_eq!(qcrypto_hmac(\u0026[0u8; 32], \u0026[0u8; 32]), hex!(\"025108dc4694cac66d549e152b967e41e516cc7568111822bf1ca44cb89bcbca\"));\n}\n\n#[test]\nfn qcrypto_pki_generate_test() {\n let keypair = qcrypto_dh_generate_longterm();\n assert_eq!(keypair.1, PublicKey::from(\u0026keypair.0))\n}\n#[test]\nfn qcrypto_dh_test() {\n let alice = qcrypto_dh_generate_longterm();\n let bob = qcrypto_dh_generate_longterm();\n\n let secret = qcrypto_dh_longterm(\u0026alice.0, \u0026bob.1);\n let secret2 = qcrypto_dh_longterm(\u0026bob.0, \u0026alice.1);\n\n assert_eq!(secret.as_bytes(), secret2.as_bytes())\n}\n#[test]\nfn qcrypto_aead_test() {\n let ciphertext = qcrypto_aead(\u0026[0u8; 32], 0, \u0026[0u8; 32], \u0026[0u8; 32]).unwrap();\n assert_eq!(qcrypto_aead_decrypt(\u0026[0u8; 32], 0, \u0026ciphertext, \u0026[0u8; 32]).unwrap(), [0u8; 32].to_vec())\n}\n#[test]\nfn qcrypto_xaead_test() {\n let ciphertext = qcrypto_xaead(\u0026[0u8; 32], \u0026[0u8; 24], \u0026[0u8; 32], \u0026[0u8; 32]).unwrap();\n assert_eq!(qcrypto_xaead_decrypt(\u0026[0u8; 32], \u0026[0u8; 24], \u0026ciphertext, \u0026[0u8; 32]).unwrap(), [0u8; 32].to_vec());\n}\n#[test]\nfn qcrypto_hkdf_test() {\n let derived = qcrypto_hkdf::\u003c1\u003e(\u0026[0u8; 32], \u0026[0u8; 32]);\n assert_eq!(derived, [hex!(\"1090894613df8aef670b0b867e222daebc0d3e436cdddbc16c65855ab93cc91a\")]);\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","stack","entry.rs"],"content":"//! The ENTRY stage of the packet processing stack. Provides a `PacketEntryStage` which implements `PacketProcessingStage`.\n\nuse std::error::Error;\nuse std::net::SocketAddr;\nuse crate::stack::{PacketProcessingStage};\n\n/// The ENTRY stage of the packet processing stack\npub struct PacketEntryStage {}\n\nimpl PacketProcessingStage for PacketEntryStage {\n fn process_packet(pkt: Vec\u003cu8\u003e, from: \u0026SocketAddr) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n Ok(())\n }\n}","traces":[{"line":11,"address":[514608],"length":1,"stats":{"Line":0},"fn_name":"process_packet"},{"line":12,"address":[514617],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":2},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","stack","mod.rs"],"content":"//! quicktap's packet processing stack\n//! Packet processing is done in several *stages*:\n//! - ENTRY\n//! - CRYPT\n//! - ROUTING\n//! - PROCESSING\n//! - EXIT\n//! # UDP Packet Flow\n//! For a packet received on the UDP socket, the following route is taken through the processing stack:\n//! ```text\n//! UDP Socket -\u003e ENTRY -\u003e CRYPT -\u003e (drop) \u003c-----+\n//! | | ^ |\n//! | | | |\n//! | +-----\u003e ROUTING -\u003e CRYPT -\u003e EXIT\n//! | v\n//! +---\u003e PROCESSING -\u003e (end flow)\n//! ```\n//! # TUN Packet Flow\n//! For a packet received on the TUN interface, the following route is taken through the processing stack:\n//! ```text\n//! TUN Interface -\u003e ENTRY -\u003e ROUTING -\u003e CRYPT -\u003e EXIT\n//! | |\n//! v |\n//! (drop) \u003c----+\n//! ```\n\nuse std::error::Error;\nuse std::net::SocketAddr;\n\npub mod entry;\n\n/// The methods and functions that need to be implemented by a stage in the packet processor\npub trait PacketProcessingStage {\n /// Process a raw datagram. This should go down the WHOLE routing chain - assume previous steps have already done.\n /// For example, if you are the CRYPT layer, and are processing a tun packet, assume that the ENTRY and ROUTING stack stages have already been completed and you are being given the result of that processing.\n /// # Errors\n /// This function will error if an error occurs\n fn process_packet(pkt: Vec\u003cu8\u003e, from: \u0026SocketAddr) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e where Self: Sized;\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap","src","tests.rs"],"content":"#![allow(clippy::unwrap_used)] // we want to panic, this is a test file\n\nuse crate::version;\n\n#[test] // This is one of those good ol' \"just for codecov\" tests. This doesn't actually need to be tested, it's for frontends, but I want that juicy 100% codecov\npub const fn version_test() {\n version();\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","cli.rs"],"content":"use clap::{ArgAction, Parser};\n\n#[derive(Parser)]\n#[command(author = \"The Quicktap Maintainers\", version, about = \"A userspace WireGuard implementation written in Rust\", long_about = None)]\npub struct Cli {\n #[arg(short, long, action = ArgAction::SetTrue)]\n pub foreground: bool,\n pub interface_name: String\n}","traces":[],"covered":0,"coverable":0},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","command.rs"],"content":"use std::error::Error;\nuse std::io;\nuse std::os::unix::net::SocketAddr;\nuse std::os::unix::net::{UnixListener, UnixStream};\n\npub enum PacketThreadCommand {\n UpdateConfig(UpdateConfigCommand),\n Stop\n}\n\npub struct UpdateConfigCommand {}\n\npub struct CommandClient {\n stream: UnixStream,\n addr: SocketAddr,\n current_command: CommandType\n}\npub enum CommandType {\n WaitingForCommand,\n Read,\n Write\n}\n\npub fn command_handler(listener: UnixListener) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n listener.set_nonblocking(true)?;\n\n let mut clients: Vec\u003cCommandClient\u003e = vec![];\n\n match listener.accept() {\n Ok((stream, addr)) =\u003e {\n clients.push(CommandClient { stream, addr, current_command: CommandType::WaitingForCommand })\n },\n Err(e) if matches!(e.kind(), io::ErrorKind::WouldBlock) =\u003e {\n // ignore.\n },\n Err(e) =\u003e {\n // okay, real error, knock it up\n return Err(e.into())\n }\n }\n\n // uh lets play ignorey ignorey for now\n\n Ok(())\n}","traces":[{"line":24,"address":[762400,763513,763567],"length":1,"stats":{"Line":0},"fn_name":"command_handler"},{"line":25,"address":[762547,762411,762487],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[762540],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[762646,762704],"length":1,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[762735],"length":1,"stats":{"Line":0},"fn_name":null},{"line":31,"address":[763475,762869],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[763248,763159,763342],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[763297],"length":1,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[763321,763424],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[763534],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":10},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","main.rs"],"content":"\nuse std::fs::File;\n\nuse std::os::unix::net::{UnixListener};\n\nuse std::sync::mpsc::channel;\nuse std::thread::{spawn};\n\nuse clap::Parser;\nuse daemonize::Daemonize;\nuse log::{error, info};\n\nuse quicktap::drivers::tun::TunDevice;\nuse quicktap::drivers::tungeneric::{GenericDriver, GenericInterface};\n\nuse crate::cli::Cli;\nuse crate::command::{command_handler, PacketThreadCommand};\nuse crate::pproc::packet_thread;\n\npub mod cli;\npub mod pproc;\npub mod command;\n\nfn main() {\n simple_logger::init().unwrap();\n\n let args = Cli::parse();\n\n info!(\"Hello, world! {}\", quicktap::version());\n info!(\"Starting up\");\n\n if !args.foreground {\n info!(\"Forking to background\");\n\n let stdout = match File::create(\"/var/log/e4.log\") {\n Ok(f) =\u003e f,\n Err(e) =\u003e {\n error!(\"Failed to open stdout file: {}\", e);\n std::process::exit(8);\n }\n };\n let stderr = match File::create(\"/var/log/e4.err\") {\n Ok(f) =\u003e f,\n Err(e) =\u003e {\n error!(\"Failed to open stderr file: {}\", e);\n std::process::exit(9);\n }\n };\n\n let daemon_opts = Daemonize::new()\n .stdout(stdout)\n .stderr(stderr);\n match daemon_opts.start() {\n Ok(_) =\u003e info!(\"Forked to background successfully\"),\n Err(e) =\u003e {\n error!(\"Failed to daemonize quicktap-cli worker process: {}\", e);\n std::process::exit(1);\n }\n }\n }\n\n info!(\"Creating unconfigured device\");\n\n let device = match TunDevice::new(\u0026GenericInterface {\n addresses: vec![],\n mtu: None,\n name: args.interface_name.clone(),\n }) {\n Ok(d) =\u003e d,\n Err(e) =\u003e {\n error!(\"Failed to create interface: {}\", e);\n std::process::exit(2);\n }\n };\n\n info!(\"Spawning packet processor thread\");\n\n let (tx, rx) = channel::\u003cPacketThreadCommand\u003e();\n\n let pproc_thread = spawn(|| {\n match packet_thread(device, rx) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Error in pproc_thread: {}\", e);\n }\n }\n });\n\n info!(\"Creating command listener\");\n match UnixListener::bind(format!(\"/var/run/{}.sock\", args.interface_name)) {\n Ok(l) =\u003e {\n // handle l\n match command_handler(l) {\n Ok(_) =\u003e (),\n Err(e) =\u003e error!(\"Error in command handler: {}\", e)\n }\n },\n Err(e) =\u003e {\n error!(\"Error creating command listener {}: {}\", format!(\"/var/run/{}.sock\", args.interface_name), e);\n }\n };\n\n\n match tx.send(PacketThreadCommand::Stop) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Error sending stop command to packet thread: {}\", e);\n std::process::exit(6);\n }\n }\n\n info!(\"Waiting for packet thread to stop\");\n match pproc_thread.join() {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Error joining thread: {:?}\", e);\n std::process::exit(5);\n }\n }\n\n info!(\"Cleaning up\");\n\n match std::fs::remove_file(format!(\"/var/run/{}.sock\", args.interface_name)) {\n Ok(_) =\u003e (),\n Err(e) =\u003e {\n error!(\"Failed to remove existing socket: {}\", e);\n std::process::exit(7);\n }\n }\n\n info!(\"Cya!\");\n}\n","traces":[{"line":24,"address":[742009,740160,750132],"length":1,"stats":{"Line":0},"fn_name":"main"},{"line":25,"address":[740173],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[740255],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[740268,740453,740561,740356],"length":1,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[740800,740517,740897,740980],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[740961,743490],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[741363,741272,741127],"length":1,"stats":{"Line":0},"fn_name":null},{"line":35,"address":[741336,741469],"length":1,"stats":{"Line":0},"fn_name":null},{"line":36,"address":[741487],"length":1,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[741546],"length":1,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[741562,741751,741654,741834],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[741815],"length":1,"stats":{"Line":0},"fn_name":null},{"line":42,"address":[741516,742066],"length":1,"stats":{"Line":0},"fn_name":null},{"line":43,"address":[742084],"length":1,"stats":{"Line":0},"fn_name":null},{"line":44,"address":[742135],"length":1,"stats":{"Line":0},"fn_name":null},{"line":45,"address":[742243,742340,742151,742423],"length":1,"stats":{"Line":0},"fn_name":null},{"line":46,"address":[742404],"length":1,"stats":{"Line":0},"fn_name":null},{"line":50,"address":[742113,742673,742711],"length":1,"stats":{"Line":0},"fn_name":null},{"line":51,"address":[742642],"length":1,"stats":{"Line":0},"fn_name":null},{"line":52,"address":[742680],"length":1,"stats":{"Line":0},"fn_name":null},{"line":53,"address":[742754],"length":1,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[743313,743410,743495,742837],"length":1,"stats":{"Line":0},"fn_name":null},{"line":55,"address":[742881],"length":1,"stats":{"Line":0},"fn_name":null},{"line":56,"address":[743145,743054,742909],"length":1,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[743118],"length":1,"stats":{"Line":0},"fn_name":null},{"line":62,"address":[741083,743649,743746,743825],"length":1,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[744010,744173],"length":1,"stats":{"Line":0},"fn_name":null},{"line":65,"address":[743818],"length":1,"stats":{"Line":0},"fn_name":null},{"line":66,"address":[743928],"length":1,"stats":{"Line":0},"fn_name":null},{"line":67,"address":[743939],"length":1,"stats":{"Line":0},"fn_name":null},{"line":69,"address":[744250],"length":1,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[744316],"length":1,"stats":{"Line":0},"fn_name":null},{"line":71,"address":[744348,744628,744440,744537],"length":1,"stats":{"Line":0},"fn_name":null},{"line":72,"address":[744601],"length":1,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[745059,744980,744835],"length":1,"stats":{"Line":0},"fn_name":null},{"line":78,"address":[745162,745052],"length":1,"stats":{"Line":0},"fn_name":null},{"line":80,"address":[639836,639296],"length":1,"stats":{"Line":0},"fn_name":"{closure#0}"},{"line":81,"address":[639339],"length":1,"stats":{"Line":0},"fn_name":null},{"line":83,"address":[639410],"length":1,"stats":{"Line":0},"fn_name":null},{"line":84,"address":[639689,639522,639436,639604],"length":1,"stats":{"Line":0},"fn_name":null},{"line":89,"address":[745575,745478,745392,745674],"length":1,"stats":{"Line":0},"fn_name":null},{"line":90,"address":[745796,745639],"length":1,"stats":{"Line":0},"fn_name":null},{"line":91,"address":[745949],"length":1,"stats":{"Line":0},"fn_name":null},{"line":93,"address":[745963,746860],"length":1,"stats":{"Line":0},"fn_name":null},{"line":95,"address":[747124,746903],"length":1,"stats":{"Line":0},"fn_name":null},{"line":98,"address":[745989],"length":1,"stats":{"Line":0},"fn_name":null},{"line":99,"address":[746005,746097,746280,746194],"length":1,"stats":{"Line":0},"fn_name":null},{"line":104,"address":[747413,746803],"length":1,"stats":{"Line":0},"fn_name":null},{"line":106,"address":[747487],"length":1,"stats":{"Line":0},"fn_name":null},{"line":107,"address":[747646,747501,747737],"length":1,"stats":{"Line":0},"fn_name":null},{"line":108,"address":[747710],"length":1,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[748002,747443,748137,747905],"length":1,"stats":{"Line":0},"fn_name":null},{"line":113,"address":[748259,748066],"length":1,"stats":{"Line":0},"fn_name":null},{"line":115,"address":[748344],"length":1,"stats":{"Line":0},"fn_name":null},{"line":116,"address":[748468,748376,748656,748565],"length":1,"stats":{"Line":0},"fn_name":null},{"line":117,"address":[748629],"length":1,"stats":{"Line":0},"fn_name":null},{"line":121,"address":[748998,748911,748829,748300],"length":1,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[749114,748969],"length":1,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[749325],"length":1,"stats":{"Line":0},"fn_name":null},{"line":126,"address":[749427,749341,749586,749509],"length":1,"stats":{"Line":0},"fn_name":null},{"line":127,"address":[749567],"length":1,"stats":{"Line":0},"fn_name":null},{"line":131,"address":[749930,749838,749756,749284],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":62},{"path":["/","home","core","prj","e3t","elaeis4","quicktap-cli","src","pproc.rs"],"content":"use std::error::Error;\nuse std::io;\nuse std::sync::mpsc::Receiver;\n\nuse log::{error, info};\n\nuse quicktap::drivers::tun::TunDevice;\nuse quicktap::drivers::tungeneric::GenericDriver;\n\nuse crate::command::PacketThreadCommand;\n\npub fn packet_thread(mut device: TunDevice, rx: Receiver\u003cPacketThreadCommand\u003e) -\u003e Result\u003c(), Box\u003cdyn Error\u003e\u003e {\n loop {\n // Check command channel\n let command = match rx.try_recv() {\n Ok(d) =\u003e Some(d),\n Err(e) if matches!(e, std::sync::mpsc::TryRecvError::Empty) =\u003e None,\n Err(e) =\u003e return Err(e.into())\n };\n if let Some(cmd) = command {\n if let PacketThreadCommand::Stop = cmd {\n info!(\"packet thread: recieved command to stop by control process\");\n return Ok(())\n }\n }\n\n let packet = match device.read() {\n Ok(p) =\u003e Some(p),\n Err(e) =\u003e match e.kind() {\n io::ErrorKind::WouldBlock =\u003e None,\n _ =\u003e {\n error!(\"Error while reading packets from interface: {}\", e);\n return Err(e.into());\n }\n }\n };\n\n if let Some(p) = packet {\n info!(\"recv_packet_on_tun {:?}\", p.header);\n\n // parse and route\n\n }\n }\n}","traces":[{"line":12,"address":[668768,670766,669994],"length":1,"stats":{"Line":0},"fn_name":"packet_thread"},{"line":13,"address":[668805],"length":1,"stats":{"Line":0},"fn_name":null},{"line":15,"address":[668821,668896],"length":1,"stats":{"Line":0},"fn_name":null},{"line":16,"address":[668928],"length":1,"stats":{"Line":0},"fn_name":null},{"line":17,"address":[669070,668961],"length":1,"stats":{"Line":0},"fn_name":null},{"line":18,"address":[669142,669027],"length":1,"stats":{"Line":0},"fn_name":null},{"line":20,"address":[669176,669094],"length":1,"stats":{"Line":0},"fn_name":null},{"line":21,"address":[669192],"length":1,"stats":{"Line":0},"fn_name":null},{"line":22,"address":[670606,669237,670449,670531],"length":1,"stats":{"Line":0},"fn_name":null},{"line":23,"address":[670589],"length":1,"stats":{"Line":0},"fn_name":null},{"line":27,"address":[669218,669281],"length":1,"stats":{"Line":0},"fn_name":null},{"line":28,"address":[669305],"length":1,"stats":{"Line":0},"fn_name":null},{"line":29,"address":[669482,669388],"length":1,"stats":{"Line":0},"fn_name":null},{"line":30,"address":[669503],"length":1,"stats":{"Line":0},"fn_name":null},{"line":32,"address":[669536,669672,669770],"length":1,"stats":{"Line":0},"fn_name":null},{"line":33,"address":[669730,669941],"length":1,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[670035],"length":1,"stats":{"Line":0},"fn_name":null},{"line":39,"address":[670223,670099],"length":1,"stats":{"Line":0},"fn_name":null}],"covered":0,"coverable":18}]};
</script>
<script crossorigin>/** @license React v16.13.1
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';(function(d,r){"object"===typeof exports&&"undefined"!==typeof module?r(exports):"function"===typeof define&&define.amd?define(["exports"],r):(d=d||self,r(d.React={}))})(this,function(d){function r(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c<arguments.length;c++)b+="&args[]="+encodeURIComponent(arguments[c]);return"Minified React error #"+a+"; visit "+b+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}
function w(a,b,c){this.props=a;this.context=b;this.refs=ba;this.updater=c||ca}function da(){}function L(a,b,c){this.props=a;this.context=b;this.refs=ba;this.updater=c||ca}function ea(a,b,c){var g,e={},fa=null,d=null;if(null!=b)for(g in void 0!==b.ref&&(d=b.ref),void 0!==b.key&&(fa=""+b.key),b)ha.call(b,g)&&!ia.hasOwnProperty(g)&&(e[g]=b[g]);var h=arguments.length-2;if(1===h)e.children=c;else if(1<h){for(var k=Array(h),f=0;f<h;f++)k[f]=arguments[f+2];e.children=k}if(a&&a.defaultProps)for(g in h=a.defaultProps,
h)void 0===e[g]&&(e[g]=h[g]);return{$$typeof:x,type:a,key:fa,ref:d,props:e,_owner:M.current}}function va(a,b){return{$$typeof:x,type:a.type,key:b,ref:a.ref,props:a.props,_owner:a._owner}}function N(a){return"object"===typeof a&&null!==a&&a.$$typeof===x}function wa(a){var b={"=":"=0",":":"=2"};return"$"+(""+a).replace(/[=:]/g,function(a){return b[a]})}function ja(a,b,c,g){if(C.length){var e=C.pop();e.result=a;e.keyPrefix=b;e.func=c;e.context=g;e.count=0;return e}return{result:a,keyPrefix:b,func:c,
context:g,count:0}}function ka(a){a.result=null;a.keyPrefix=null;a.func=null;a.context=null;a.count=0;10>C.length&&C.push(a)}function O(a,b,c,g){var e=typeof a;if("undefined"===e||"boolean"===e)a=null;var d=!1;if(null===a)d=!0;else switch(e){case "string":case "number":d=!0;break;case "object":switch(a.$$typeof){case x:case xa:d=!0}}if(d)return c(g,a,""===b?"."+P(a,0):b),1;d=0;b=""===b?".":b+":";if(Array.isArray(a))for(var f=0;f<a.length;f++){e=a[f];var h=b+P(e,f);d+=O(e,h,c,g)}else if(null===a||
"object"!==typeof a?h=null:(h=la&&a[la]||a["@@iterator"],h="function"===typeof h?h:null),"function"===typeof h)for(a=h.call(a),f=0;!(e=a.next()).done;)e=e.value,h=b+P(e,f++),d+=O(e,h,c,g);else if("object"===e)throw c=""+a,Error(r(31,"[object Object]"===c?"object with keys {"+Object.keys(a).join(", ")+"}":c,""));return d}function Q(a,b,c){return null==a?0:O(a,"",b,c)}function P(a,b){return"object"===typeof a&&null!==a&&null!=a.key?wa(a.key):b.toString(36)}function ya(a,b,c){a.func.call(a.context,b,
a.count++)}function za(a,b,c){var g=a.result,e=a.keyPrefix;a=a.func.call(a.context,b,a.count++);Array.isArray(a)?R(a,g,c,function(a){return a}):null!=a&&(N(a)&&(a=va(a,e+(!a.key||b&&b.key===a.key?"":(""+a.key).replace(ma,"$&/")+"/")+c)),g.push(a))}function R(a,b,c,g,e){var d="";null!=c&&(d=(""+c).replace(ma,"$&/")+"/");b=ja(b,d,g,e);Q(a,za,b);ka(b)}function t(){var a=na.current;if(null===a)throw Error(r(321));return a}function S(a,b){var c=a.length;a.push(b);a:for(;;){var g=c-1>>>1,e=a[g];if(void 0!==
e&&0<D(e,b))a[g]=b,a[c]=e,c=g;else break a}}function n(a){a=a[0];return void 0===a?null:a}function E(a){var b=a[0];if(void 0!==b){var c=a.pop();if(c!==b){a[0]=c;a:for(var g=0,e=a.length;g<e;){var d=2*(g+1)-1,f=a[d],h=d+1,k=a[h];if(void 0!==f&&0>D(f,c))void 0!==k&&0>D(k,f)?(a[g]=k,a[h]=c,g=h):(a[g]=f,a[d]=c,g=d);else if(void 0!==k&&0>D(k,c))a[g]=k,a[h]=c,g=h;else break a}}return b}return null}function D(a,b){var c=a.sortIndex-b.sortIndex;return 0!==c?c:a.id-b.id}function F(a){for(var b=n(u);null!==
b;){if(null===b.callback)E(u);else if(b.startTime<=a)E(u),b.sortIndex=b.expirationTime,S(p,b);else break;b=n(u)}}function T(a){y=!1;F(a);if(!v)if(null!==n(p))v=!0,z(U);else{var b=n(u);null!==b&&G(T,b.startTime-a)}}function U(a,b){v=!1;y&&(y=!1,V());H=!0;var c=m;try{F(b);for(l=n(p);null!==l&&(!(l.expirationTime>b)||a&&!W());){var g=l.callback;if(null!==g){l.callback=null;m=l.priorityLevel;var e=g(l.expirationTime<=b);b=q();"function"===typeof e?l.callback=e:l===n(p)&&E(p);F(b)}else E(p);l=n(p)}if(null!==
l)var d=!0;else{var f=n(u);null!==f&&G(T,f.startTime-b);d=!1}return d}finally{l=null,m=c,H=!1}}function oa(a){switch(a){case 1:return-1;case 2:return 250;case 5:return 1073741823;case 4:return 1E4;default:return 5E3}}var f="function"===typeof Symbol&&Symbol.for,x=f?Symbol.for("react.element"):60103,xa=f?Symbol.for("react.portal"):60106,Aa=f?Symbol.for("react.fragment"):60107,Ba=f?Symbol.for("react.strict_mode"):60108,Ca=f?Symbol.for("react.profiler"):60114,Da=f?Symbol.for("react.provider"):60109,
Ea=f?Symbol.for("react.context"):60110,Fa=f?Symbol.for("react.forward_ref"):60112,Ga=f?Symbol.for("react.suspense"):60113,Ha=f?Symbol.for("react.memo"):60115,Ia=f?Symbol.for("react.lazy"):60116,la="function"===typeof Symbol&&Symbol.iterator,pa=Object.getOwnPropertySymbols,Ja=Object.prototype.hasOwnProperty,Ka=Object.prototype.propertyIsEnumerable,I=function(){try{if(!Object.assign)return!1;var a=new String("abc");a[5]="de";if("5"===Object.getOwnPropertyNames(a)[0])return!1;var b={};for(a=0;10>a;a++)b["_"+
String.fromCharCode(a)]=a;if("0123456789"!==Object.getOwnPropertyNames(b).map(function(a){return b[a]}).join(""))return!1;var c={};"abcdefghijklmnopqrst".split("").forEach(function(a){c[a]=a});return"abcdefghijklmnopqrst"!==Object.keys(Object.assign({},c)).join("")?!1:!0}catch(g){return!1}}()?Object.assign:function(a,b){if(null===a||void 0===a)throw new TypeError("Object.assign cannot be called with null or undefined");var c=Object(a);for(var g,e=1;e<arguments.length;e++){var d=Object(arguments[e]);
for(var f in d)Ja.call(d,f)&&(c[f]=d[f]);if(pa){g=pa(d);for(var h=0;h<g.length;h++)Ka.call(d,g[h])&&(c[g[h]]=d[g[h]])}}return c},ca={isMounted:function(a){return!1},enqueueForceUpdate:function(a,b,c){},enqueueReplaceState:function(a,b,c,d){},enqueueSetState:function(a,b,c,d){}},ba={};w.prototype.isReactComponent={};w.prototype.setState=function(a,b){if("object"!==typeof a&&"function"!==typeof a&&null!=a)throw Error(r(85));this.updater.enqueueSetState(this,a,b,"setState")};w.prototype.forceUpdate=
function(a){this.updater.enqueueForceUpdate(this,a,"forceUpdate")};da.prototype=w.prototype;f=L.prototype=new da;f.constructor=L;I(f,w.prototype);f.isPureReactComponent=!0;var M={current:null},ha=Object.prototype.hasOwnProperty,ia={key:!0,ref:!0,__self:!0,__source:!0},ma=/\/+/g,C=[],na={current:null},X;if("undefined"===typeof window||"function"!==typeof MessageChannel){var A=null,qa=null,ra=function(){if(null!==A)try{var a=q();A(!0,a);A=null}catch(b){throw setTimeout(ra,0),b;}},La=Date.now();var q=
function(){return Date.now()-La};var z=function(a){null!==A?setTimeout(z,0,a):(A=a,setTimeout(ra,0))};var G=function(a,b){qa=setTimeout(a,b)};var V=function(){clearTimeout(qa)};var W=function(){return!1};f=X=function(){}}else{var Y=window.performance,sa=window.Date,Ma=window.setTimeout,Na=window.clearTimeout;"undefined"!==typeof console&&(f=window.cancelAnimationFrame,"function"!==typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),
"function"!==typeof f&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"));if("object"===typeof Y&&"function"===typeof Y.now)q=function(){return Y.now()};else{var Oa=sa.now();q=function(){return sa.now()-Oa}}var J=!1,K=null,Z=-1,ta=5,ua=0;W=function(){return q()>=ua};f=function(){};X=function(a){0>a||125<a?console.error("forceFrameRate takes a positive int between 0 and 125, forcing framerates higher than 125 fps is not unsupported"):
ta=0<a?Math.floor(1E3/a):5};var B=new MessageChannel,aa=B.port2;B.port1.onmessage=function(){if(null!==K){var a=q();ua=a+ta;try{K(!0,a)?aa.postMessage(null):(J=!1,K=null)}catch(b){throw aa.postMessage(null),b;}}else J=!1};z=function(a){K=a;J||(J=!0,aa.postMessage(null))};G=function(a,b){Z=Ma(function(){a(q())},b)};V=function(){Na(Z);Z=-1}}var p=[],u=[],Pa=1,l=null,m=3,H=!1,v=!1,y=!1,Qa=0;B={ReactCurrentDispatcher:na,ReactCurrentOwner:M,IsSomeRendererActing:{current:!1},assign:I};I(B,{Scheduler:{__proto__:null,
unstable_ImmediatePriority:1,unstable_UserBlockingPriority:2,unstable_NormalPriority:3,unstable_IdlePriority:5,unstable_LowPriority:4,unstable_runWithPriority:function(a,b){switch(a){case 1:case 2:case 3:case 4:case 5:break;default:a=3}var c=m;m=a;try{return b()}finally{m=c}},unstable_next:function(a){switch(m){case 1:case 2:case 3:var b=3;break;default:b=m}var c=m;m=b;try{return a()}finally{m=c}},unstable_scheduleCallback:function(a,b,c){var d=q();if("object"===typeof c&&null!==c){var e=c.delay;
e="number"===typeof e&&0<e?d+e:d;c="number"===typeof c.timeout?c.timeout:oa(a)}else c=oa(a),e=d;c=e+c;a={id:Pa++,callback:b,priorityLevel:a,startTime:e,expirationTime:c,sortIndex:-1};e>d?(a.sortIndex=e,S(u,a),null===n(p)&&a===n(u)&&(y?V():y=!0,G(T,e-d))):(a.sortIndex=c,S(p,a),v||H||(v=!0,z(U)));return a},unstable_cancelCallback:function(a){a.callback=null},unstable_wrapCallback:function(a){var b=m;return function(){var c=m;m=b;try{return a.apply(this,arguments)}finally{m=c}}},unstable_getCurrentPriorityLevel:function(){return m},
unstable_shouldYield:function(){var a=q();F(a);var b=n(p);return b!==l&&null!==l&&null!==b&&null!==b.callback&&b.startTime<=a&&b.expirationTime<l.expirationTime||W()},unstable_requestPaint:f,unstable_continueExecution:function(){v||H||(v=!0,z(U))},unstable_pauseExecution:function(){},unstable_getFirstCallbackNode:function(){return n(p)},get unstable_now(){return q},get unstable_forceFrameRate(){return X},unstable_Profiling:null},SchedulerTracing:{__proto__:null,__interactionsRef:null,__subscriberRef:null,
unstable_clear:function(a){return a()},unstable_getCurrent:function(){return null},unstable_getThreadID:function(){return++Qa},unstable_trace:function(a,b,c){return c()},unstable_wrap:function(a){return a},unstable_subscribe:function(a){},unstable_unsubscribe:function(a){}}});d.Children={map:function(a,b,c){if(null==a)return a;var d=[];R(a,d,null,b,c);return d},forEach:function(a,b,c){if(null==a)return a;b=ja(null,null,b,c);Q(a,ya,b);ka(b)},count:function(a){return Q(a,function(){return null},null)},
toArray:function(a){var b=[];R(a,b,null,function(a){return a});return b},only:function(a){if(!N(a))throw Error(r(143));return a}};d.Component=w;d.Fragment=Aa;d.Profiler=Ca;d.PureComponent=L;d.StrictMode=Ba;d.Suspense=Ga;d.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=B;d.cloneElement=function(a,b,c){if(null===a||void 0===a)throw Error(r(267,a));var d=I({},a.props),e=a.key,f=a.ref,m=a._owner;if(null!=b){void 0!==b.ref&&(f=b.ref,m=M.current);void 0!==b.key&&(e=""+b.key);if(a.type&&a.type.defaultProps)var h=
a.type.defaultProps;for(k in b)ha.call(b,k)&&!ia.hasOwnProperty(k)&&(d[k]=void 0===b[k]&&void 0!==h?h[k]:b[k])}var k=arguments.length-2;if(1===k)d.children=c;else if(1<k){h=Array(k);for(var l=0;l<k;l++)h[l]=arguments[l+2];d.children=h}return{$$typeof:x,type:a.type,key:e,ref:f,props:d,_owner:m}};d.createContext=function(a,b){void 0===b&&(b=null);a={$$typeof:Ea,_calculateChangedBits:b,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null};a.Provider={$$typeof:Da,_context:a};return a.Consumer=
a};d.createElement=ea;d.createFactory=function(a){var b=ea.bind(null,a);b.type=a;return b};d.createRef=function(){return{current:null}};d.forwardRef=function(a){return{$$typeof:Fa,render:a}};d.isValidElement=N;d.lazy=function(a){return{$$typeof:Ia,_ctor:a,_status:-1,_result:null}};d.memo=function(a,b){return{$$typeof:Ha,type:a,compare:void 0===b?null:b}};d.useCallback=function(a,b){return t().useCallback(a,b)};d.useContext=function(a,b){return t().useContext(a,b)};d.useDebugValue=function(a,b){};
d.useEffect=function(a,b){return t().useEffect(a,b)};d.useImperativeHandle=function(a,b,c){return t().useImperativeHandle(a,b,c)};d.useLayoutEffect=function(a,b){return t().useLayoutEffect(a,b)};d.useMemo=function(a,b){return t().useMemo(a,b)};d.useReducer=function(a,b,c){return t().useReducer(a,b,c)};d.useRef=function(a){return t().useRef(a)};d.useState=function(a){return t().useState(a)};d.version="16.13.1"});
</script>
<script crossorigin>/** @license React v16.13.1
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/*
Modernizr 3.0.0pre (Custom Build) | MIT
*/
'use strict';(function(I,ea){"object"===typeof exports&&"undefined"!==typeof module?ea(exports,require("react")):"function"===typeof define&&define.amd?define(["exports","react"],ea):(I=I||self,ea(I.ReactDOM={},I.React))})(this,function(I,ea){function k(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c<arguments.length;c++)b+="&args[]="+encodeURIComponent(arguments[c]);return"Minified React error #"+a+"; visit "+b+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}
function ji(a,b,c,d,e,f,g,h,m){yb=!1;gc=null;ki.apply(li,arguments)}function mi(a,b,c,d,e,f,g,h,m){ji.apply(this,arguments);if(yb){if(yb){var n=gc;yb=!1;gc=null}else throw Error(k(198));hc||(hc=!0,pd=n)}}function lf(a,b,c){var d=a.type||"unknown-event";a.currentTarget=mf(c);mi(d,b,void 0,a);a.currentTarget=null}function nf(){if(ic)for(var a in cb){var b=cb[a],c=ic.indexOf(a);if(!(-1<c))throw Error(k(96,a));if(!jc[c]){if(!b.extractEvents)throw Error(k(97,a));jc[c]=b;c=b.eventTypes;for(var d in c){var e=
void 0;var f=c[d],g=b,h=d;if(qd.hasOwnProperty(h))throw Error(k(99,h));qd[h]=f;var m=f.phasedRegistrationNames;if(m){for(e in m)m.hasOwnProperty(e)&&of(m[e],g,h);e=!0}else f.registrationName?(of(f.registrationName,g,h),e=!0):e=!1;if(!e)throw Error(k(98,d,a));}}}}function of(a,b,c){if(db[a])throw Error(k(100,a));db[a]=b;rd[a]=b.eventTypes[c].dependencies}function pf(a){var b=!1,c;for(c in a)if(a.hasOwnProperty(c)){var d=a[c];if(!cb.hasOwnProperty(c)||cb[c]!==d){if(cb[c])throw Error(k(102,c));cb[c]=
d;b=!0}}b&&nf()}function qf(a){if(a=rf(a)){if("function"!==typeof sd)throw Error(k(280));var b=a.stateNode;b&&(b=td(b),sd(a.stateNode,a.type,b))}}function sf(a){eb?fb?fb.push(a):fb=[a]:eb=a}function tf(){if(eb){var a=eb,b=fb;fb=eb=null;qf(a);if(b)for(a=0;a<b.length;a++)qf(b[a])}}function ud(){if(null!==eb||null!==fb)vd(),tf()}function uf(a,b,c){if(wd)return a(b,c);wd=!0;try{return vf(a,b,c)}finally{wd=!1,ud()}}function ni(a){if(wf.call(xf,a))return!0;if(wf.call(yf,a))return!1;if(oi.test(a))return xf[a]=
!0;yf[a]=!0;return!1}function pi(a,b,c,d){if(null!==c&&0===c.type)return!1;switch(typeof b){case "function":case "symbol":return!0;case "boolean":if(d)return!1;if(null!==c)return!c.acceptsBooleans;a=a.toLowerCase().slice(0,5);return"data-"!==a&&"aria-"!==a;default:return!1}}function qi(a,b,c,d){if(null===b||"undefined"===typeof b||pi(a,b,c,d))return!0;if(d)return!1;if(null!==c)switch(c.type){case 3:return!b;case 4:return!1===b;case 5:return isNaN(b);case 6:return isNaN(b)||1>b}return!1}function L(a,
b,c,d,e,f){this.acceptsBooleans=2===b||3===b||4===b;this.attributeName=d;this.attributeNamespace=e;this.mustUseProperty=c;this.propertyName=a;this.type=b;this.sanitizeURL=f}function xd(a,b,c,d){var e=E.hasOwnProperty(b)?E[b]:null;var f=null!==e?0===e.type:d?!1:!(2<b.length)||"o"!==b[0]&&"O"!==b[0]||"n"!==b[1]&&"N"!==b[1]?!1:!0;f||(qi(b,c,e,d)&&(c=null),d||null===e?ni(b)&&(null===c?a.removeAttribute(b):a.setAttribute(b,""+c)):e.mustUseProperty?a[e.propertyName]=null===c?3===e.type?!1:"":c:(b=e.attributeName,
d=e.attributeNamespace,null===c?a.removeAttribute(b):(e=e.type,c=3===e||4===e&&!0===c?"":""+c,d?a.setAttributeNS(d,b,c):a.setAttribute(b,c))))}function zb(a){if(null===a||"object"!==typeof a)return null;a=zf&&a[zf]||a["@@iterator"];return"function"===typeof a?a:null}function ri(a){if(-1===a._status){a._status=0;var b=a._ctor;b=b();a._result=b;b.then(function(b){0===a._status&&(b=b.default,a._status=1,a._result=b)},function(b){0===a._status&&(a._status=2,a._result=b)})}}function na(a){if(null==a)return null;
if("function"===typeof a)return a.displayName||a.name||null;if("string"===typeof a)return a;switch(a){case Ma:return"Fragment";case gb:return"Portal";case kc:return"Profiler";case Af:return"StrictMode";case lc:return"Suspense";case yd:return"SuspenseList"}if("object"===typeof a)switch(a.$$typeof){case Bf:return"Context.Consumer";case Cf:return"Context.Provider";case zd:var b=a.render;b=b.displayName||b.name||"";return a.displayName||(""!==b?"ForwardRef("+b+")":"ForwardRef");case Ad:return na(a.type);
case Df:return na(a.render);case Ef:if(a=1===a._status?a._result:null)return na(a)}return null}function Bd(a){var b="";do{a:switch(a.tag){case 3:case 4:case 6:case 7:case 10:case 9:var c="";break a;default:var d=a._debugOwner,e=a._debugSource,f=na(a.type);c=null;d&&(c=na(d.type));d=f;f="";e?f=" (at "+e.fileName.replace(si,"")+":"+e.lineNumber+")":c&&(f=" (created by "+c+")");c="\n in "+(d||"Unknown")+f}b+=c;a=a.return}while(a);return b}function va(a){switch(typeof a){case "boolean":case "number":case "object":case "string":case "undefined":return a;
default:return""}}function Ff(a){var b=a.type;return(a=a.nodeName)&&"input"===a.toLowerCase()&&("checkbox"===b||"radio"===b)}function ti(a){var b=Ff(a)?"checked":"value",c=Object.getOwnPropertyDescriptor(a.constructor.prototype,b),d=""+a[b];if(!a.hasOwnProperty(b)&&"undefined"!==typeof c&&"function"===typeof c.get&&"function"===typeof c.set){var e=c.get,f=c.set;Object.defineProperty(a,b,{configurable:!0,get:function(){return e.call(this)},set:function(a){d=""+a;f.call(this,a)}});Object.defineProperty(a,
b,{enumerable:c.enumerable});return{getValue:function(){return d},setValue:function(a){d=""+a},stopTracking:function(){a._valueTracker=null;delete a[b]}}}}function mc(a){a._valueTracker||(a._valueTracker=ti(a))}function Gf(a){if(!a)return!1;var b=a._valueTracker;if(!b)return!0;var c=b.getValue();var d="";a&&(d=Ff(a)?a.checked?"true":"false":a.value);a=d;return a!==c?(b.setValue(a),!0):!1}function Cd(a,b){var c=b.checked;return M({},b,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=
c?c:a._wrapperState.initialChecked})}function Hf(a,b){var c=null==b.defaultValue?"":b.defaultValue,d=null!=b.checked?b.checked:b.defaultChecked;c=va(null!=b.value?b.value:c);a._wrapperState={initialChecked:d,initialValue:c,controlled:"checkbox"===b.type||"radio"===b.type?null!=b.checked:null!=b.value}}function If(a,b){b=b.checked;null!=b&&xd(a,"checked",b,!1)}function Dd(a,b){If(a,b);var c=va(b.value),d=b.type;if(null!=c)if("number"===d){if(0===c&&""===a.value||a.value!=c)a.value=""+c}else a.value!==
""+c&&(a.value=""+c);else if("submit"===d||"reset"===d){a.removeAttribute("value");return}b.hasOwnProperty("value")?Ed(a,b.type,c):b.hasOwnProperty("defaultValue")&&Ed(a,b.type,va(b.defaultValue));null==b.checked&&null!=b.defaultChecked&&(a.defaultChecked=!!b.defaultChecked)}function Jf(a,b,c){if(b.hasOwnProperty("value")||b.hasOwnProperty("defaultValue")){var d=b.type;if(!("submit"!==d&&"reset"!==d||void 0!==b.value&&null!==b.value))return;b=""+a._wrapperState.initialValue;c||b===a.value||(a.value=
b);a.defaultValue=b}c=a.name;""!==c&&(a.name="");a.defaultChecked=!!a._wrapperState.initialChecked;""!==c&&(a.name=c)}function Ed(a,b,c){if("number"!==b||a.ownerDocument.activeElement!==a)null==c?a.defaultValue=""+a._wrapperState.initialValue:a.defaultValue!==""+c&&(a.defaultValue=""+c)}function ui(a){var b="";ea.Children.forEach(a,function(a){null!=a&&(b+=a)});return b}function Fd(a,b){a=M({children:void 0},b);if(b=ui(b.children))a.children=b;return a}function hb(a,b,c,d){a=a.options;if(b){b={};
for(var e=0;e<c.length;e++)b["$"+c[e]]=!0;for(c=0;c<a.length;c++)e=b.hasOwnProperty("$"+a[c].value),a[c].selected!==e&&(a[c].selected=e),e&&d&&(a[c].defaultSelected=!0)}else{c=""+va(c);b=null;for(e=0;e<a.length;e++){if(a[e].value===c){a[e].selected=!0;d&&(a[e].defaultSelected=!0);return}null!==b||a[e].disabled||(b=a[e])}null!==b&&(b.selected=!0)}}function Gd(a,b){if(null!=b.dangerouslySetInnerHTML)throw Error(k(91));return M({},b,{value:void 0,defaultValue:void 0,children:""+a._wrapperState.initialValue})}
function Kf(a,b){var c=b.value;if(null==c){c=b.children;b=b.defaultValue;if(null!=c){if(null!=b)throw Error(k(92));if(Array.isArray(c)){if(!(1>=c.length))throw Error(k(93));c=c[0]}b=c}null==b&&(b="");c=b}a._wrapperState={initialValue:va(c)}}function Lf(a,b){var c=va(b.value),d=va(b.defaultValue);null!=c&&(c=""+c,c!==a.value&&(a.value=c),null==b.defaultValue&&a.defaultValue!==c&&(a.defaultValue=c));null!=d&&(a.defaultValue=""+d)}function Mf(a,b){b=a.textContent;b===a._wrapperState.initialValue&&""!==
b&&null!==b&&(a.value=b)}function Nf(a){switch(a){case "svg":return"http://www.w3.org/2000/svg";case "math":return"http://www.w3.org/1998/Math/MathML";default:return"http://www.w3.org/1999/xhtml"}}function Hd(a,b){return null==a||"http://www.w3.org/1999/xhtml"===a?Nf(b):"http://www.w3.org/2000/svg"===a&&"foreignObject"===b?"http://www.w3.org/1999/xhtml":a}function nc(a,b){var c={};c[a.toLowerCase()]=b.toLowerCase();c["Webkit"+a]="webkit"+b;c["Moz"+a]="moz"+b;return c}function oc(a){if(Id[a])return Id[a];
if(!ib[a])return a;var b=ib[a],c;for(c in b)if(b.hasOwnProperty(c)&&c in Of)return Id[a]=b[c];return a}function Jd(a){var b=Pf.get(a);void 0===b&&(b=new Map,Pf.set(a,b));return b}function Na(a){var b=a,c=a;if(a.alternate)for(;b.return;)b=b.return;else{a=b;do b=a,0!==(b.effectTag&1026)&&(c=b.return),a=b.return;while(a)}return 3===b.tag?c:null}function Qf(a){if(13===a.tag){var b=a.memoizedState;null===b&&(a=a.alternate,null!==a&&(b=a.memoizedState));if(null!==b)return b.dehydrated}return null}function Rf(a){if(Na(a)!==
a)throw Error(k(188));}function vi(a){var b=a.alternate;if(!b){b=Na(a);if(null===b)throw Error(k(188));return b!==a?null:a}for(var c=a,d=b;;){var e=c.return;if(null===e)break;var f=e.alternate;if(null===f){d=e.return;if(null!==d){c=d;continue}break}if(e.child===f.child){for(f=e.child;f;){if(f===c)return Rf(e),a;if(f===d)return Rf(e),b;f=f.sibling}throw Error(k(188));}if(c.return!==d.return)c=e,d=f;else{for(var g=!1,h=e.child;h;){if(h===c){g=!0;c=e;d=f;break}if(h===d){g=!0;d=e;c=f;break}h=h.sibling}if(!g){for(h=
f.child;h;){if(h===c){g=!0;c=f;d=e;break}if(h===d){g=!0;d=f;c=e;break}h=h.sibling}if(!g)throw Error(k(189));}}if(c.alternate!==d)throw Error(k(190));}if(3!==c.tag)throw Error(k(188));return c.stateNode.current===c?a:b}function Sf(a){a=vi(a);if(!a)return null;for(var b=a;;){if(5===b.tag||6===b.tag)return b;if(b.child)b.child.return=b,b=b.child;else{if(b===a)break;for(;!b.sibling;){if(!b.return||b.return===a)return null;b=b.return}b.sibling.return=b.return;b=b.sibling}}return null}function jb(a,b){if(null==
b)throw Error(k(30));if(null==a)return b;if(Array.isArray(a)){if(Array.isArray(b))return a.push.apply(a,b),a;a.push(b);return a}return Array.isArray(b)?[a].concat(b):[a,b]}function Kd(a,b,c){Array.isArray(a)?a.forEach(b,c):a&&b.call(c,a)}function pc(a){null!==a&&(Ab=jb(Ab,a));a=Ab;Ab=null;if(a){Kd(a,wi);if(Ab)throw Error(k(95));if(hc)throw a=pd,hc=!1,pd=null,a;}}function Ld(a){a=a.target||a.srcElement||window;a.correspondingUseElement&&(a=a.correspondingUseElement);return 3===a.nodeType?a.parentNode:
a}function Tf(a){if(!wa)return!1;a="on"+a;var b=a in document;b||(b=document.createElement("div"),b.setAttribute(a,"return;"),b="function"===typeof b[a]);return b}function Uf(a){a.topLevelType=null;a.nativeEvent=null;a.targetInst=null;a.ancestors.length=0;10>qc.length&&qc.push(a)}function Vf(a,b,c,d){if(qc.length){var e=qc.pop();e.topLevelType=a;e.eventSystemFlags=d;e.nativeEvent=b;e.targetInst=c;return e}return{topLevelType:a,eventSystemFlags:d,nativeEvent:b,targetInst:c,ancestors:[]}}function Wf(a){var b=
a.targetInst,c=b;do{if(!c){a.ancestors.push(c);break}var d=c;if(3===d.tag)d=d.stateNode.containerInfo;else{for(;d.return;)d=d.return;d=3!==d.tag?null:d.stateNode.containerInfo}if(!d)break;b=c.tag;5!==b&&6!==b||a.ancestors.push(c);c=Bb(d)}while(c);for(c=0;c<a.ancestors.length;c++){b=a.ancestors[c];var e=Ld(a.nativeEvent);d=a.topLevelType;var f=a.nativeEvent,g=a.eventSystemFlags;0===c&&(g|=64);for(var h=null,m=0;m<jc.length;m++){var n=jc[m];n&&(n=n.extractEvents(d,b,f,e,g))&&(h=jb(h,n))}pc(h)}}function Md(a,
b,c){if(!c.has(a)){switch(a){case "scroll":Cb(b,"scroll",!0);break;case "focus":case "blur":Cb(b,"focus",!0);Cb(b,"blur",!0);c.set("blur",null);c.set("focus",null);break;case "cancel":case "close":Tf(a)&&Cb(b,a,!0);break;case "invalid":case "submit":case "reset":break;default:-1===Db.indexOf(a)&&w(a,b)}c.set(a,null)}}function xi(a,b){var c=Jd(b);Nd.forEach(function(a){Md(a,b,c)});yi.forEach(function(a){Md(a,b,c)})}function Od(a,b,c,d,e){return{blockedOn:a,topLevelType:b,eventSystemFlags:c|32,nativeEvent:e,
container:d}}function Xf(a,b){switch(a){case "focus":case "blur":xa=null;break;case "dragenter":case "dragleave":ya=null;break;case "mouseover":case "mouseout":za=null;break;case "pointerover":case "pointerout":Eb.delete(b.pointerId);break;case "gotpointercapture":case "lostpointercapture":Fb.delete(b.pointerId)}}function Gb(a,b,c,d,e,f){if(null===a||a.nativeEvent!==f)return a=Od(b,c,d,e,f),null!==b&&(b=Hb(b),null!==b&&Yf(b)),a;a.eventSystemFlags|=d;return a}function zi(a,b,c,d,e){switch(b){case "focus":return xa=
Gb(xa,a,b,c,d,e),!0;case "dragenter":return ya=Gb(ya,a,b,c,d,e),!0;case "mouseover":return za=Gb(za,a,b,c,d,e),!0;case "pointerover":var f=e.pointerId;Eb.set(f,Gb(Eb.get(f)||null,a,b,c,d,e));return!0;case "gotpointercapture":return f=e.pointerId,Fb.set(f,Gb(Fb.get(f)||null,a,b,c,d,e)),!0}return!1}function Ai(a){var b=Bb(a.target);if(null!==b){var c=Na(b);if(null!==c)if(b=c.tag,13===b){if(b=Qf(c),null!==b){a.blockedOn=b;Pd(a.priority,function(){Bi(c)});return}}else if(3===b&&c.stateNode.hydrate){a.blockedOn=
3===c.tag?c.stateNode.containerInfo:null;return}}a.blockedOn=null}function rc(a){if(null!==a.blockedOn)return!1;var b=Qd(a.topLevelType,a.eventSystemFlags,a.container,a.nativeEvent);if(null!==b){var c=Hb(b);null!==c&&Yf(c);a.blockedOn=b;return!1}return!0}function Zf(a,b,c){rc(a)&&c.delete(b)}function Ci(){for(Rd=!1;0<fa.length;){var a=fa[0];if(null!==a.blockedOn){a=Hb(a.blockedOn);null!==a&&Di(a);break}var b=Qd(a.topLevelType,a.eventSystemFlags,a.container,a.nativeEvent);null!==b?a.blockedOn=b:fa.shift()}null!==
xa&&rc(xa)&&(xa=null);null!==ya&&rc(ya)&&(ya=null);null!==za&&rc(za)&&(za=null);Eb.forEach(Zf);Fb.forEach(Zf)}function Ib(a,b){a.blockedOn===b&&(a.blockedOn=null,Rd||(Rd=!0,$f(ag,Ci)))}function bg(a){if(0<fa.length){Ib(fa[0],a);for(var b=1;b<fa.length;b++){var c=fa[b];c.blockedOn===a&&(c.blockedOn=null)}}null!==xa&&Ib(xa,a);null!==ya&&Ib(ya,a);null!==za&&Ib(za,a);b=function(b){return Ib(b,a)};Eb.forEach(b);Fb.forEach(b);for(b=0;b<Jb.length;b++)c=Jb[b],c.blockedOn===a&&(c.blockedOn=null);for(;0<Jb.length&&
(b=Jb[0],null===b.blockedOn);)Ai(b),null===b.blockedOn&&Jb.shift()}function Sd(a,b){for(var c=0;c<a.length;c+=2){var d=a[c],e=a[c+1],f="on"+(e[0].toUpperCase()+e.slice(1));f={phasedRegistrationNames:{bubbled:f,captured:f+"Capture"},dependencies:[d],eventPriority:b};Td.set(d,b);cg.set(d,f);dg[e]=f}}function w(a,b){Cb(b,a,!1)}function Cb(a,b,c){var d=Td.get(b);switch(void 0===d?2:d){case 0:d=Ei.bind(null,b,1,a);break;case 1:d=Fi.bind(null,b,1,a);break;default:d=sc.bind(null,b,1,a)}c?a.addEventListener(b,
d,!0):a.addEventListener(b,d,!1)}function Ei(a,b,c,d){Oa||vd();var e=sc,f=Oa;Oa=!0;try{eg(e,a,b,c,d)}finally{(Oa=f)||ud()}}function Fi(a,b,c,d){Gi(Hi,sc.bind(null,a,b,c,d))}function sc(a,b,c,d){if(tc)if(0<fa.length&&-1<Nd.indexOf(a))a=Od(null,a,b,c,d),fa.push(a);else{var e=Qd(a,b,c,d);if(null===e)Xf(a,d);else if(-1<Nd.indexOf(a))a=Od(e,a,b,c,d),fa.push(a);else if(!zi(e,a,b,c,d)){Xf(a,d);a=Vf(a,d,null,b);try{uf(Wf,a)}finally{Uf(a)}}}}function Qd(a,b,c,d){c=Ld(d);c=Bb(c);if(null!==c){var e=Na(c);if(null===
e)c=null;else{var f=e.tag;if(13===f){c=Qf(e);if(null!==c)return c;c=null}else if(3===f){if(e.stateNode.hydrate)return 3===e.tag?e.stateNode.containerInfo:null;c=null}else e!==c&&(c=null)}}a=Vf(a,d,c,b);try{uf(Wf,a)}finally{Uf(a)}return null}function fg(a,b,c){return null==b||"boolean"===typeof b||""===b?"":c||"number"!==typeof b||0===b||Kb.hasOwnProperty(a)&&Kb[a]?(""+b).trim():b+"px"}function gg(a,b){a=a.style;for(var c in b)if(b.hasOwnProperty(c)){var d=0===c.indexOf("--"),e=fg(c,b[c],d);"float"===
c&&(c="cssFloat");d?a.setProperty(c,e):a[c]=e}}function Ud(a,b){if(b){if(Ii[a]&&(null!=b.children||null!=b.dangerouslySetInnerHTML))throw Error(k(137,a,""));if(null!=b.dangerouslySetInnerHTML){if(null!=b.children)throw Error(k(60));if(!("object"===typeof b.dangerouslySetInnerHTML&&"__html"in b.dangerouslySetInnerHTML))throw Error(k(61));}if(null!=b.style&&"object"!==typeof b.style)throw Error(k(62,""));}}function Vd(a,b){if(-1===a.indexOf("-"))return"string"===typeof b.is;switch(a){case "annotation-xml":case "color-profile":case "font-face":case "font-face-src":case "font-face-uri":case "font-face-format":case "font-face-name":case "missing-glyph":return!1;
default:return!0}}function oa(a,b){a=9===a.nodeType||11===a.nodeType?a:a.ownerDocument;var c=Jd(a);b=rd[b];for(var d=0;d<b.length;d++)Md(b[d],a,c)}function uc(){}function Wd(a){a=a||("undefined"!==typeof document?document:void 0);if("undefined"===typeof a)return null;try{return a.activeElement||a.body}catch(b){return a.body}}function hg(a){for(;a&&a.firstChild;)a=a.firstChild;return a}function ig(a,b){var c=hg(a);a=0;for(var d;c;){if(3===c.nodeType){d=a+c.textContent.length;if(a<=b&&d>=b)return{node:c,
offset:b-a};a=d}a:{for(;c;){if(c.nextSibling){c=c.nextSibling;break a}c=c.parentNode}c=void 0}c=hg(c)}}function jg(a,b){return a&&b?a===b?!0:a&&3===a.nodeType?!1:b&&3===b.nodeType?jg(a,b.parentNode):"contains"in a?a.contains(b):a.compareDocumentPosition?!!(a.compareDocumentPosition(b)&16):!1:!1}function kg(){for(var a=window,b=Wd();b instanceof a.HTMLIFrameElement;){try{var c="string"===typeof b.contentWindow.location.href}catch(d){c=!1}if(c)a=b.contentWindow;else break;b=Wd(a.document)}return b}
function Xd(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return b&&("input"===b&&("text"===a.type||"search"===a.type||"tel"===a.type||"url"===a.type||"password"===a.type)||"textarea"===b||"true"===a.contentEditable)}function lg(a,b){switch(a){case "button":case "input":case "select":case "textarea":return!!b.autoFocus}return!1}function Yd(a,b){return"textarea"===a||"option"===a||"noscript"===a||"string"===typeof b.children||"number"===typeof b.children||"object"===typeof b.dangerouslySetInnerHTML&&
null!==b.dangerouslySetInnerHTML&&null!=b.dangerouslySetInnerHTML.__html}function kb(a){for(;null!=a;a=a.nextSibling){var b=a.nodeType;if(1===b||3===b)break}return a}function mg(a){a=a.previousSibling;for(var b=0;a;){if(8===a.nodeType){var c=a.data;if(c===ng||c===Zd||c===$d){if(0===b)return a;b--}else c===og&&b++}a=a.previousSibling}return null}function Bb(a){var b=a[Aa];if(b)return b;for(var c=a.parentNode;c;){if(b=c[Lb]||c[Aa]){c=b.alternate;if(null!==b.child||null!==c&&null!==c.child)for(a=mg(a);null!==
a;){if(c=a[Aa])return c;a=mg(a)}return b}a=c;c=a.parentNode}return null}function Hb(a){a=a[Aa]||a[Lb];return!a||5!==a.tag&&6!==a.tag&&13!==a.tag&&3!==a.tag?null:a}function Pa(a){if(5===a.tag||6===a.tag)return a.stateNode;throw Error(k(33));}function ae(a){return a[vc]||null}function pa(a){do a=a.return;while(a&&5!==a.tag);return a?a:null}function pg(a,b){var c=a.stateNode;if(!c)return null;var d=td(c);if(!d)return null;c=d[b];a:switch(b){case "onClick":case "onClickCapture":case "onDoubleClick":case "onDoubleClickCapture":case "onMouseDown":case "onMouseDownCapture":case "onMouseMove":case "onMouseMoveCapture":case "onMouseUp":case "onMouseUpCapture":case "onMouseEnter":(d=
!d.disabled)||(a=a.type,d=!("button"===a||"input"===a||"select"===a||"textarea"===a));a=!d;break a;default:a=!1}if(a)return null;if(c&&"function"!==typeof c)throw Error(k(231,b,typeof c));return c}function qg(a,b,c){if(b=pg(a,c.dispatchConfig.phasedRegistrationNames[b]))c._dispatchListeners=jb(c._dispatchListeners,b),c._dispatchInstances=jb(c._dispatchInstances,a)}function Ji(a){if(a&&a.dispatchConfig.phasedRegistrationNames){for(var b=a._targetInst,c=[];b;)c.push(b),b=pa(b);for(b=c.length;0<b--;)qg(c[b],
"captured",a);for(b=0;b<c.length;b++)qg(c[b],"bubbled",a)}}function be(a,b,c){a&&c&&c.dispatchConfig.registrationName&&(b=pg(a,c.dispatchConfig.registrationName))&&(c._dispatchListeners=jb(c._dispatchListeners,b),c._dispatchInstances=jb(c._dispatchInstances,a))}function Ki(a){a&&a.dispatchConfig.registrationName&&be(a._targetInst,null,a)}function lb(a){Kd(a,Ji)}function rg(){if(wc)return wc;var a,b=ce,c=b.length,d,e="value"in Ba?Ba.value:Ba.textContent,f=e.length;for(a=0;a<c&&b[a]===e[a];a++);var g=
c-a;for(d=1;d<=g&&b[c-d]===e[f-d];d++);return wc=e.slice(a,1<d?1-d:void 0)}function xc(){return!0}function yc(){return!1}function R(a,b,c,d){this.dispatchConfig=a;this._targetInst=b;this.nativeEvent=c;a=this.constructor.Interface;for(var e in a)a.hasOwnProperty(e)&&((b=a[e])?this[e]=b(c):"target"===e?this.target=d:this[e]=c[e]);this.isDefaultPrevented=(null!=c.defaultPrevented?c.defaultPrevented:!1===c.returnValue)?xc:yc;this.isPropagationStopped=yc;return this}function Li(a,b,c,d){if(this.eventPool.length){var e=
this.eventPool.pop();this.call(e,a,b,c,d);return e}return new this(a,b,c,d)}function Mi(a){if(!(a instanceof this))throw Error(k(279));a.destructor();10>this.eventPool.length&&this.eventPool.push(a)}function sg(a){a.eventPool=[];a.getPooled=Li;a.release=Mi}function tg(a,b){switch(a){case "keyup":return-1!==Ni.indexOf(b.keyCode);case "keydown":return 229!==b.keyCode;case "keypress":case "mousedown":case "blur":return!0;default:return!1}}function ug(a){a=a.detail;return"object"===typeof a&&"data"in
a?a.data:null}function Oi(a,b){switch(a){case "compositionend":return ug(b);case "keypress":if(32!==b.which)return null;vg=!0;return wg;case "textInput":return a=b.data,a===wg&&vg?null:a;default:return null}}function Pi(a,b){if(mb)return"compositionend"===a||!de&&tg(a,b)?(a=rg(),wc=ce=Ba=null,mb=!1,a):null;switch(a){case "paste":return null;case "keypress":if(!(b.ctrlKey||b.altKey||b.metaKey)||b.ctrlKey&&b.altKey){if(b.char&&1<b.char.length)return b.char;if(b.which)return String.fromCharCode(b.which)}return null;
case "compositionend":return xg&&"ko"!==b.locale?null:b.data;default:return null}}function yg(a){var b=a&&a.nodeName&&a.nodeName.toLowerCase();return"input"===b?!!Qi[a.type]:"textarea"===b?!0:!1}function zg(a,b,c){a=R.getPooled(Ag.change,a,b,c);a.type="change";sf(c);lb(a);return a}function Ri(a){pc(a)}function zc(a){var b=Pa(a);if(Gf(b))return a}function Si(a,b){if("change"===a)return b}function Bg(){Mb&&(Mb.detachEvent("onpropertychange",Cg),Nb=Mb=null)}function Cg(a){if("value"===a.propertyName&&
zc(Nb))if(a=zg(Nb,a,Ld(a)),Oa)pc(a);else{Oa=!0;try{ee(Ri,a)}finally{Oa=!1,ud()}}}function Ti(a,b,c){"focus"===a?(Bg(),Mb=b,Nb=c,Mb.attachEvent("onpropertychange",Cg)):"blur"===a&&Bg()}function Ui(a,b){if("selectionchange"===a||"keyup"===a||"keydown"===a)return zc(Nb)}function Vi(a,b){if("click"===a)return zc(b)}function Wi(a,b){if("input"===a||"change"===a)return zc(b)}function Xi(a){var b=this.nativeEvent;return b.getModifierState?b.getModifierState(a):(a=Yi[a])?!!b[a]:!1}function fe(a){return Xi}
function Zi(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}function Ob(a,b){if(Qa(a,b))return!0;if("object"!==typeof a||null===a||"object"!==typeof b||null===b)return!1;var c=Object.keys(a),d=Object.keys(b);if(c.length!==d.length)return!1;for(d=0;d<c.length;d++)if(!$i.call(b,c[d])||!Qa(a[c[d]],b[c[d]]))return!1;return!0}function Dg(a,b){var c=b.window===b?b.document:9===b.nodeType?b:b.ownerDocument;if(ge||null==nb||nb!==Wd(c))return null;c=nb;"selectionStart"in c&&Xd(c)?c={start:c.selectionStart,
end:c.selectionEnd}:(c=(c.ownerDocument&&c.ownerDocument.defaultView||window).getSelection(),c={anchorNode:c.anchorNode,anchorOffset:c.anchorOffset,focusNode:c.focusNode,focusOffset:c.focusOffset});return Pb&&Ob(Pb,c)?null:(Pb=c,a=R.getPooled(Eg.select,he,a,b),a.type="select",a.target=nb,lb(a),a)}function Ac(a){var b=a.keyCode;"charCode"in a?(a=a.charCode,0===a&&13===b&&(a=13)):a=b;10===a&&(a=13);return 32<=a||13===a?a:0}function q(a,b){0>ob||(a.current=ie[ob],ie[ob]=null,ob--)}function y(a,b,c){ob++;
ie[ob]=a.current;a.current=b}function pb(a,b){var c=a.type.contextTypes;if(!c)return Ca;var d=a.stateNode;if(d&&d.__reactInternalMemoizedUnmaskedChildContext===b)return d.__reactInternalMemoizedMaskedChildContext;var e={},f;for(f in c)e[f]=b[f];d&&(a=a.stateNode,a.__reactInternalMemoizedUnmaskedChildContext=b,a.__reactInternalMemoizedMaskedChildContext=e);return e}function N(a){a=a.childContextTypes;return null!==a&&void 0!==a}function Fg(a,b,c){if(B.current!==Ca)throw Error(k(168));y(B,b);y(G,c)}
function Gg(a,b,c){var d=a.stateNode;a=b.childContextTypes;if("function"!==typeof d.getChildContext)return c;d=d.getChildContext();for(var e in d)if(!(e in a))throw Error(k(108,na(b)||"Unknown",e));return M({},c,{},d)}function Bc(a){a=(a=a.stateNode)&&a.__reactInternalMemoizedMergedChildContext||Ca;Ra=B.current;y(B,a);y(G,G.current);return!0}function Hg(a,b,c){var d=a.stateNode;if(!d)throw Error(k(169));c?(a=Gg(a,b,Ra),d.__reactInternalMemoizedMergedChildContext=a,q(G),q(B),y(B,a)):q(G);y(G,c)}function Cc(){switch(aj()){case Dc:return 99;
case Ig:return 98;case Jg:return 97;case Kg:return 96;case Lg:return 95;default:throw Error(k(332));}}function Mg(a){switch(a){case 99:return Dc;case 98:return Ig;case 97:return Jg;case 96:return Kg;case 95:return Lg;default:throw Error(k(332));}}function Da(a,b){a=Mg(a);return bj(a,b)}function Ng(a,b,c){a=Mg(a);return je(a,b,c)}function Og(a){null===qa?(qa=[a],Ec=je(Dc,Pg)):qa.push(a);return Qg}function ha(){if(null!==Ec){var a=Ec;Ec=null;Rg(a)}Pg()}function Pg(){if(!ke&&null!==qa){ke=!0;var a=0;
try{var b=qa;Da(99,function(){for(;a<b.length;a++){var c=b[a];do c=c(!0);while(null!==c)}});qa=null}catch(c){throw null!==qa&&(qa=qa.slice(a+1)),je(Dc,ha),c;}finally{ke=!1}}}function Fc(a,b,c){c/=10;return 1073741821-(((1073741821-a+b/10)/c|0)+1)*c}function aa(a,b){if(a&&a.defaultProps){b=M({},b);a=a.defaultProps;for(var c in a)void 0===b[c]&&(b[c]=a[c])}return b}function le(){Gc=qb=Hc=null}function me(a){var b=Ic.current;q(Ic);a.type._context._currentValue=b}function Sg(a,b){for(;null!==a;){var c=
a.alternate;if(a.childExpirationTime<b)a.childExpirationTime=b,null!==c&&c.childExpirationTime<b&&(c.childExpirationTime=b);else if(null!==c&&c.childExpirationTime<b)c.childExpirationTime=b;else break;a=a.return}}function rb(a,b){Hc=a;Gc=qb=null;a=a.dependencies;null!==a&&null!==a.firstContext&&(a.expirationTime>=b&&(ia=!0),a.firstContext=null)}function W(a,b){if(Gc!==a&&!1!==b&&0!==b){if("number"!==typeof b||1073741823===b)Gc=a,b=1073741823;b={context:a,observedBits:b,next:null};if(null===qb){if(null===
Hc)throw Error(k(308));qb=b;Hc.dependencies={expirationTime:0,firstContext:b,responders:null}}else qb=qb.next=b}return a._currentValue}function ne(a){a.updateQueue={baseState:a.memoizedState,baseQueue:null,shared:{pending:null},effects:null}}function oe(a,b){a=a.updateQueue;b.updateQueue===a&&(b.updateQueue={baseState:a.baseState,baseQueue:a.baseQueue,shared:a.shared,effects:a.effects})}function Ea(a,b){a={expirationTime:a,suspenseConfig:b,tag:Tg,payload:null,callback:null,next:null};return a.next=
a}function Fa(a,b){a=a.updateQueue;if(null!==a){a=a.shared;var c=a.pending;null===c?b.next=b:(b.next=c.next,c.next=b);a.pending=b}}function Ug(a,b){var c=a.alternate;null!==c&&oe(c,a);a=a.updateQueue;c=a.baseQueue;null===c?(a.baseQueue=b.next=b,b.next=b):(b.next=c.next,c.next=b)}function Qb(a,b,c,d){var e=a.updateQueue;Ga=!1;var f=e.baseQueue,g=e.shared.pending;if(null!==g){if(null!==f){var h=f.next;f.next=g.next;g.next=h}f=g;e.shared.pending=null;h=a.alternate;null!==h&&(h=h.updateQueue,null!==h&&
(h.baseQueue=g))}if(null!==f){h=f.next;var m=e.baseState,n=0,k=null,ba=null,l=null;if(null!==h){var p=h;do{g=p.expirationTime;if(g<d){var t={expirationTime:p.expirationTime,suspenseConfig:p.suspenseConfig,tag:p.tag,payload:p.payload,callback:p.callback,next:null};null===l?(ba=l=t,k=m):l=l.next=t;g>n&&(n=g)}else{null!==l&&(l=l.next={expirationTime:1073741823,suspenseConfig:p.suspenseConfig,tag:p.tag,payload:p.payload,callback:p.callback,next:null});Vg(g,p.suspenseConfig);a:{var q=a,r=p;g=b;t=c;switch(r.tag){case 1:q=
r.payload;if("function"===typeof q){m=q.call(t,m,g);break a}m=q;break a;case 3:q.effectTag=q.effectTag&-4097|64;case Tg:q=r.payload;g="function"===typeof q?q.call(t,m,g):q;if(null===g||void 0===g)break a;m=M({},m,g);break a;case Jc:Ga=!0}}null!==p.callback&&(a.effectTag|=32,g=e.effects,null===g?e.effects=[p]:g.push(p))}p=p.next;if(null===p||p===h)if(g=e.shared.pending,null===g)break;else p=f.next=g.next,g.next=h,e.baseQueue=f=g,e.shared.pending=null}while(1)}null===l?k=m:l.next=ba;e.baseState=k;e.baseQueue=
l;Kc(n);a.expirationTime=n;a.memoizedState=m}}function Wg(a,b,c){a=b.effects;b.effects=null;if(null!==a)for(b=0;b<a.length;b++){var d=a[b],e=d.callback;if(null!==e){d.callback=null;d=e;e=c;if("function"!==typeof d)throw Error(k(191,d));d.call(e)}}}function Lc(a,b,c,d){b=a.memoizedState;c=c(d,b);c=null===c||void 0===c?b:M({},b,c);a.memoizedState=c;0===a.expirationTime&&(a.updateQueue.baseState=c)}function Xg(a,b,c,d,e,f,g){a=a.stateNode;return"function"===typeof a.shouldComponentUpdate?a.shouldComponentUpdate(d,
f,g):b.prototype&&b.prototype.isPureReactComponent?!Ob(c,d)||!Ob(e,f):!0}function Yg(a,b,c){var d=!1,e=Ca;var f=b.contextType;"object"===typeof f&&null!==f?f=W(f):(e=N(b)?Ra:B.current,d=b.contextTypes,f=(d=null!==d&&void 0!==d)?pb(a,e):Ca);b=new b(c,f);a.memoizedState=null!==b.state&&void 0!==b.state?b.state:null;b.updater=Mc;a.stateNode=b;b._reactInternalFiber=a;d&&(a=a.stateNode,a.__reactInternalMemoizedUnmaskedChildContext=e,a.__reactInternalMemoizedMaskedChildContext=f);return b}function Zg(a,
b,c,d){a=b.state;"function"===typeof b.componentWillReceiveProps&&b.componentWillReceiveProps(c,d);"function"===typeof b.UNSAFE_componentWillReceiveProps&&b.UNSAFE_componentWillReceiveProps(c,d);b.state!==a&&Mc.enqueueReplaceState(b,b.state,null)}function pe(a,b,c,d){var e=a.stateNode;e.props=c;e.state=a.memoizedState;e.refs=$g;ne(a);var f=b.contextType;"object"===typeof f&&null!==f?e.context=W(f):(f=N(b)?Ra:B.current,e.context=pb(a,f));Qb(a,c,e,d);e.state=a.memoizedState;f=b.getDerivedStateFromProps;
"function"===typeof f&&(Lc(a,b,f,c),e.state=a.memoizedState);"function"===typeof b.getDerivedStateFromProps||"function"===typeof e.getSnapshotBeforeUpdate||"function"!==typeof e.UNSAFE_componentWillMount&&"function"!==typeof e.componentWillMount||(b=e.state,"function"===typeof e.componentWillMount&&e.componentWillMount(),"function"===typeof e.UNSAFE_componentWillMount&&e.UNSAFE_componentWillMount(),b!==e.state&&Mc.enqueueReplaceState(e,e.state,null),Qb(a,c,e,d),e.state=a.memoizedState);"function"===
typeof e.componentDidMount&&(a.effectTag|=4)}function Rb(a,b,c){a=c.ref;if(null!==a&&"function"!==typeof a&&"object"!==typeof a){if(c._owner){c=c._owner;if(c){if(1!==c.tag)throw Error(k(309));var d=c.stateNode}if(!d)throw Error(k(147,a));var e=""+a;if(null!==b&&null!==b.ref&&"function"===typeof b.ref&&b.ref._stringRef===e)return b.ref;b=function(a){var b=d.refs;b===$g&&(b=d.refs={});null===a?delete b[e]:b[e]=a};b._stringRef=e;return b}if("string"!==typeof a)throw Error(k(284));if(!c._owner)throw Error(k(290,
a));}return a}function Nc(a,b){if("textarea"!==a.type)throw Error(k(31,"[object Object]"===Object.prototype.toString.call(b)?"object with keys {"+Object.keys(b).join(", ")+"}":b,""));}function ah(a){function b(b,c){if(a){var d=b.lastEffect;null!==d?(d.nextEffect=c,b.lastEffect=c):b.firstEffect=b.lastEffect=c;c.nextEffect=null;c.effectTag=8}}function c(c,d){if(!a)return null;for(;null!==d;)b(c,d),d=d.sibling;return null}function d(a,b){for(a=new Map;null!==b;)null!==b.key?a.set(b.key,b):a.set(b.index,
b),b=b.sibling;return a}function e(a,b){a=Sa(a,b);a.index=0;a.sibling=null;return a}function f(b,c,d){b.index=d;if(!a)return c;d=b.alternate;if(null!==d)return d=d.index,d<c?(b.effectTag=2,c):d;b.effectTag=2;return c}function g(b){a&&null===b.alternate&&(b.effectTag=2);return b}function h(a,b,c,d){if(null===b||6!==b.tag)return b=qe(c,a.mode,d),b.return=a,b;b=e(b,c);b.return=a;return b}function m(a,b,c,d){if(null!==b&&b.elementType===c.type)return d=e(b,c.props),d.ref=Rb(a,b,c),d.return=a,d;d=Oc(c.type,
c.key,c.props,null,a.mode,d);d.ref=Rb(a,b,c);d.return=a;return d}function n(a,b,c,d){if(null===b||4!==b.tag||b.stateNode.containerInfo!==c.containerInfo||b.stateNode.implementation!==c.implementation)return b=re(c,a.mode,d),b.return=a,b;b=e(b,c.children||[]);b.return=a;return b}function l(a,b,c,d,f){if(null===b||7!==b.tag)return b=Ha(c,a.mode,d,f),b.return=a,b;b=e(b,c);b.return=a;return b}function ba(a,b,c){if("string"===typeof b||"number"===typeof b)return b=qe(""+b,a.mode,c),b.return=a,b;if("object"===
typeof b&&null!==b){switch(b.$$typeof){case Pc:return c=Oc(b.type,b.key,b.props,null,a.mode,c),c.ref=Rb(a,null,b),c.return=a,c;case gb:return b=re(b,a.mode,c),b.return=a,b}if(Qc(b)||zb(b))return b=Ha(b,a.mode,c,null),b.return=a,b;Nc(a,b)}return null}function p(a,b,c,d){var e=null!==b?b.key:null;if("string"===typeof c||"number"===typeof c)return null!==e?null:h(a,b,""+c,d);if("object"===typeof c&&null!==c){switch(c.$$typeof){case Pc:return c.key===e?c.type===Ma?l(a,b,c.props.children,d,e):m(a,b,c,
d):null;case gb:return c.key===e?n(a,b,c,d):null}if(Qc(c)||zb(c))return null!==e?null:l(a,b,c,d,null);Nc(a,c)}return null}function t(a,b,c,d,e){if("string"===typeof d||"number"===typeof d)return a=a.get(c)||null,h(b,a,""+d,e);if("object"===typeof d&&null!==d){switch(d.$$typeof){case Pc:return a=a.get(null===d.key?c:d.key)||null,d.type===Ma?l(b,a,d.props.children,e,d.key):m(b,a,d,e);case gb:return a=a.get(null===d.key?c:d.key)||null,n(b,a,d,e)}if(Qc(d)||zb(d))return a=a.get(c)||null,l(b,a,d,e,null);
Nc(b,d)}return null}function q(e,g,h,m){for(var n=null,k=null,l=g,r=g=0,C=null;null!==l&&r<h.length;r++){l.index>r?(C=l,l=null):C=l.sibling;var O=p(e,l,h[r],m);if(null===O){null===l&&(l=C);break}a&&l&&null===O.alternate&&b(e,l);g=f(O,g,r);null===k?n=O:k.sibling=O;k=O;l=C}if(r===h.length)return c(e,l),n;if(null===l){for(;r<h.length;r++)l=ba(e,h[r],m),null!==l&&(g=f(l,g,r),null===k?n=l:k.sibling=l,k=l);return n}for(l=d(e,l);r<h.length;r++)C=t(l,e,r,h[r],m),null!==C&&(a&&null!==C.alternate&&l.delete(null===
C.key?r:C.key),g=f(C,g,r),null===k?n=C:k.sibling=C,k=C);a&&l.forEach(function(a){return b(e,a)});return n}function w(e,g,h,n){var m=zb(h);if("function"!==typeof m)throw Error(k(150));h=m.call(h);if(null==h)throw Error(k(151));for(var l=m=null,r=g,C=g=0,O=null,v=h.next();null!==r&&!v.done;C++,v=h.next()){r.index>C?(O=r,r=null):O=r.sibling;var q=p(e,r,v.value,n);if(null===q){null===r&&(r=O);break}a&&r&&null===q.alternate&&b(e,r);g=f(q,g,C);null===l?m=q:l.sibling=q;l=q;r=O}if(v.done)return c(e,r),m;
if(null===r){for(;!v.done;C++,v=h.next())v=ba(e,v.value,n),null!==v&&(g=f(v,g,C),null===l?m=v:l.sibling=v,l=v);return m}for(r=d(e,r);!v.done;C++,v=h.next())v=t(r,e,C,v.value,n),null!==v&&(a&&null!==v.alternate&&r.delete(null===v.key?C:v.key),g=f(v,g,C),null===l?m=v:l.sibling=v,l=v);a&&r.forEach(function(a){return b(e,a)});return m}return function(a,d,f,h){var m="object"===typeof f&&null!==f&&f.type===Ma&&null===f.key;m&&(f=f.props.children);var n="object"===typeof f&&null!==f;if(n)switch(f.$$typeof){case Pc:a:{n=
f.key;for(m=d;null!==m;){if(m.key===n){switch(m.tag){case 7:if(f.type===Ma){c(a,m.sibling);d=e(m,f.props.children);d.return=a;a=d;break a}break;default:if(m.elementType===f.type){c(a,m.sibling);d=e(m,f.props);d.ref=Rb(a,m,f);d.return=a;a=d;break a}}c(a,m);break}else b(a,m);m=m.sibling}f.type===Ma?(d=Ha(f.props.children,a.mode,h,f.key),d.return=a,a=d):(h=Oc(f.type,f.key,f.props,null,a.mode,h),h.ref=Rb(a,d,f),h.return=a,a=h)}return g(a);case gb:a:{for(m=f.key;null!==d;){if(d.key===m)if(4===d.tag&&d.stateNode.containerInfo===
f.containerInfo&&d.stateNode.implementation===f.implementation){c(a,d.sibling);d=e(d,f.children||[]);d.return=a;a=d;break a}else{c(a,d);break}else b(a,d);d=d.sibling}d=re(f,a.mode,h);d.return=a;a=d}return g(a)}if("string"===typeof f||"number"===typeof f)return f=""+f,null!==d&&6===d.tag?(c(a,d.sibling),d=e(d,f),d.return=a,a=d):(c(a,d),d=qe(f,a.mode,h),d.return=a,a=d),g(a);if(Qc(f))return q(a,d,f,h);if(zb(f))return w(a,d,f,h);n&&Nc(a,f);if("undefined"===typeof f&&!m)switch(a.tag){case 1:case 0:throw a=
a.type,Error(k(152,a.displayName||a.name||"Component"));}return c(a,d)}}function Ta(a){if(a===Sb)throw Error(k(174));return a}function se(a,b){y(Tb,b);y(Ub,a);y(ja,Sb);a=b.nodeType;switch(a){case 9:case 11:b=(b=b.documentElement)?b.namespaceURI:Hd(null,"");break;default:a=8===a?b.parentNode:b,b=a.namespaceURI||null,a=a.tagName,b=Hd(b,a)}q(ja);y(ja,b)}function tb(a){q(ja);q(Ub);q(Tb)}function bh(a){Ta(Tb.current);var b=Ta(ja.current);var c=Hd(b,a.type);b!==c&&(y(Ub,a),y(ja,c))}function te(a){Ub.current===
a&&(q(ja),q(Ub))}function Rc(a){for(var b=a;null!==b;){if(13===b.tag){var c=b.memoizedState;if(null!==c&&(c=c.dehydrated,null===c||c.data===$d||c.data===Zd))return b}else if(19===b.tag&&void 0!==b.memoizedProps.revealOrder){if(0!==(b.effectTag&64))return b}else if(null!==b.child){b.child.return=b;b=b.child;continue}if(b===a)break;for(;null===b.sibling;){if(null===b.return||b.return===a)return null;b=b.return}b.sibling.return=b.return;b=b.sibling}return null}function ue(a,b){return{responder:a,props:b}}
function S(){throw Error(k(321));}function ve(a,b){if(null===b)return!1;for(var c=0;c<b.length&&c<a.length;c++)if(!Qa(a[c],b[c]))return!1;return!0}function we(a,b,c,d,e,f){Ia=f;z=b;b.memoizedState=null;b.updateQueue=null;b.expirationTime=0;Sc.current=null===a||null===a.memoizedState?dj:ej;a=c(d,e);if(b.expirationTime===Ia){f=0;do{b.expirationTime=0;if(!(25>f))throw Error(k(301));f+=1;J=K=null;b.updateQueue=null;Sc.current=fj;a=c(d,e)}while(b.expirationTime===Ia)}Sc.current=Tc;b=null!==K&&null!==K.next;
Ia=0;J=K=z=null;Uc=!1;if(b)throw Error(k(300));return a}function ub(){var a={memoizedState:null,baseState:null,baseQueue:null,queue:null,next:null};null===J?z.memoizedState=J=a:J=J.next=a;return J}function vb(){if(null===K){var a=z.alternate;a=null!==a?a.memoizedState:null}else a=K.next;var b=null===J?z.memoizedState:J.next;if(null!==b)J=b,K=a;else{if(null===a)throw Error(k(310));K=a;a={memoizedState:K.memoizedState,baseState:K.baseState,baseQueue:K.baseQueue,queue:K.queue,next:null};null===J?z.memoizedState=
J=a:J=J.next=a}return J}function Ua(a,b){return"function"===typeof b?b(a):b}function Vc(a,b,c){b=vb();c=b.queue;if(null===c)throw Error(k(311));c.lastRenderedReducer=a;var d=K,e=d.baseQueue,f=c.pending;if(null!==f){if(null!==e){var g=e.next;e.next=f.next;f.next=g}d.baseQueue=e=f;c.pending=null}if(null!==e){e=e.next;d=d.baseState;var h=g=f=null,m=e;do{var n=m.expirationTime;if(n<Ia){var l={expirationTime:m.expirationTime,suspenseConfig:m.suspenseConfig,action:m.action,eagerReducer:m.eagerReducer,eagerState:m.eagerState,
next:null};null===h?(g=h=l,f=d):h=h.next=l;n>z.expirationTime&&(z.expirationTime=n,Kc(n))}else null!==h&&(h=h.next={expirationTime:1073741823,suspenseConfig:m.suspenseConfig,action:m.action,eagerReducer:m.eagerReducer,eagerState:m.eagerState,next:null}),Vg(n,m.suspenseConfig),d=m.eagerReducer===a?m.eagerState:a(d,m.action);m=m.next}while(null!==m&&m!==e);null===h?f=d:h.next=g;Qa(d,b.memoizedState)||(ia=!0);b.memoizedState=d;b.baseState=f;b.baseQueue=h;c.lastRenderedState=d}return[b.memoizedState,
c.dispatch]}function Wc(a,b,c){b=vb();c=b.queue;if(null===c)throw Error(k(311));c.lastRenderedReducer=a;var d=c.dispatch,e=c.pending,f=b.memoizedState;if(null!==e){c.pending=null;var g=e=e.next;do f=a(f,g.action),g=g.next;while(g!==e);Qa(f,b.memoizedState)||(ia=!0);b.memoizedState=f;null===b.baseQueue&&(b.baseState=f);c.lastRenderedState=f}return[f,d]}function xe(a){var b=ub();"function"===typeof a&&(a=a());b.memoizedState=b.baseState=a;a=b.queue={pending:null,dispatch:null,lastRenderedReducer:Ua,
lastRenderedState:a};a=a.dispatch=ch.bind(null,z,a);return[b.memoizedState,a]}function ye(a,b,c,d){a={tag:a,create:b,destroy:c,deps:d,next:null};b=z.updateQueue;null===b?(b={lastEffect:null},z.updateQueue=b,b.lastEffect=a.next=a):(c=b.lastEffect,null===c?b.lastEffect=a.next=a:(d=c.next,c.next=a,a.next=d,b.lastEffect=a));return a}function dh(a){return vb().memoizedState}function ze(a,b,c,d){var e=ub();z.effectTag|=a;e.memoizedState=ye(1|b,c,void 0,void 0===d?null:d)}function Ae(a,b,c,d){var e=vb();
d=void 0===d?null:d;var f=void 0;if(null!==K){var g=K.memoizedState;f=g.destroy;if(null!==d&&ve(d,g.deps)){ye(b,c,f,d);return}}z.effectTag|=a;e.memoizedState=ye(1|b,c,f,d)}function eh(a,b){return ze(516,4,a,b)}function Xc(a,b){return Ae(516,4,a,b)}function fh(a,b){return Ae(4,2,a,b)}function gh(a,b){if("function"===typeof b)return a=a(),b(a),function(){b(null)};if(null!==b&&void 0!==b)return a=a(),b.current=a,function(){b.current=null}}function hh(a,b,c){c=null!==c&&void 0!==c?c.concat([a]):null;
return Ae(4,2,gh.bind(null,b,a),c)}function Be(a,b){}function ih(a,b){ub().memoizedState=[a,void 0===b?null:b];return a}function Yc(a,b){var c=vb();b=void 0===b?null:b;var d=c.memoizedState;if(null!==d&&null!==b&&ve(b,d[1]))return d[0];c.memoizedState=[a,b];return a}function jh(a,b){var c=vb();b=void 0===b?null:b;var d=c.memoizedState;if(null!==d&&null!==b&&ve(b,d[1]))return d[0];a=a();c.memoizedState=[a,b];return a}function Ce(a,b,c){var d=Cc();Da(98>d?98:d,function(){a(!0)});Da(97<d?97:d,function(){var d=
X.suspense;X.suspense=void 0===b?null:b;try{a(!1),c()}finally{X.suspense=d}})}function ch(a,b,c){var d=ka(),e=Vb.suspense;d=Va(d,a,e);e={expirationTime:d,suspenseConfig:e,action:c,eagerReducer:null,eagerState:null,next:null};var f=b.pending;null===f?e.next=e:(e.next=f.next,f.next=e);b.pending=e;f=a.alternate;if(a===z||null!==f&&f===z)Uc=!0,e.expirationTime=Ia,z.expirationTime=Ia;else{if(0===a.expirationTime&&(null===f||0===f.expirationTime)&&(f=b.lastRenderedReducer,null!==f))try{var g=b.lastRenderedState,
h=f(g,c);e.eagerReducer=f;e.eagerState=h;if(Qa(h,g))return}catch(m){}finally{}Ja(a,d)}}function kh(a,b){var c=la(5,null,null,0);c.elementType="DELETED";c.type="DELETED";c.stateNode=b;c.return=a;c.effectTag=8;null!==a.lastEffect?(a.lastEffect.nextEffect=c,a.lastEffect=c):a.firstEffect=a.lastEffect=c}function lh(a,b){switch(a.tag){case 5:var c=a.type;b=1!==b.nodeType||c.toLowerCase()!==b.nodeName.toLowerCase()?null:b;return null!==b?(a.stateNode=b,!0):!1;case 6:return b=""===a.pendingProps||3!==b.nodeType?
null:b,null!==b?(a.stateNode=b,!0):!1;case 13:return!1;default:return!1}}function De(a){if(Wa){var b=Ka;if(b){var c=b;if(!lh(a,b)){b=kb(c.nextSibling);if(!b||!lh(a,b)){a.effectTag=a.effectTag&-1025|2;Wa=!1;ra=a;return}kh(ra,c)}ra=a;Ka=kb(b.firstChild)}else a.effectTag=a.effectTag&-1025|2,Wa=!1,ra=a}}function mh(a){for(a=a.return;null!==a&&5!==a.tag&&3!==a.tag&&13!==a.tag;)a=a.return;ra=a}function Zc(a){if(a!==ra)return!1;if(!Wa)return mh(a),Wa=!0,!1;var b=a.type;if(5!==a.tag||"head"!==b&&"body"!==
b&&!Yd(b,a.memoizedProps))for(b=Ka;b;)kh(a,b),b=kb(b.nextSibling);mh(a);if(13===a.tag){a=a.memoizedState;a=null!==a?a.dehydrated:null;if(!a)throw Error(k(317));a:{a=a.nextSibling;for(b=0;a;){if(8===a.nodeType){var c=a.data;if(c===og){if(0===b){Ka=kb(a.nextSibling);break a}b--}else c!==ng&&c!==Zd&&c!==$d||b++}a=a.nextSibling}Ka=null}}else Ka=ra?kb(a.stateNode.nextSibling):null;return!0}function Ee(){Ka=ra=null;Wa=!1}function T(a,b,c,d){b.child=null===a?Fe(b,null,c,d):wb(b,a.child,c,d)}function nh(a,
b,c,d,e){c=c.render;var f=b.ref;rb(b,e);d=we(a,b,c,d,f,e);if(null!==a&&!ia)return b.updateQueue=a.updateQueue,b.effectTag&=-517,a.expirationTime<=e&&(a.expirationTime=0),sa(a,b,e);b.effectTag|=1;T(a,b,d,e);return b.child}function oh(a,b,c,d,e,f){if(null===a){var g=c.type;if("function"===typeof g&&!Ge(g)&&void 0===g.defaultProps&&null===c.compare&&void 0===c.defaultProps)return b.tag=15,b.type=g,ph(a,b,g,d,e,f);a=Oc(c.type,null,d,null,b.mode,f);a.ref=b.ref;a.return=b;return b.child=a}g=a.child;if(e<
f&&(e=g.memoizedProps,c=c.compare,c=null!==c?c:Ob,c(e,d)&&a.ref===b.ref))return sa(a,b,f);b.effectTag|=1;a=Sa(g,d);a.ref=b.ref;a.return=b;return b.child=a}function ph(a,b,c,d,e,f){return null!==a&&Ob(a.memoizedProps,d)&&a.ref===b.ref&&(ia=!1,e<f)?(b.expirationTime=a.expirationTime,sa(a,b,f)):He(a,b,c,d,f)}function qh(a,b){var c=b.ref;if(null===a&&null!==c||null!==a&&a.ref!==c)b.effectTag|=128}function He(a,b,c,d,e){var f=N(c)?Ra:B.current;f=pb(b,f);rb(b,e);c=we(a,b,c,d,f,e);if(null!==a&&!ia)return b.updateQueue=
a.updateQueue,b.effectTag&=-517,a.expirationTime<=e&&(a.expirationTime=0),sa(a,b,e);b.effectTag|=1;T(a,b,c,e);return b.child}function rh(a,b,c,d,e){if(N(c)){var f=!0;Bc(b)}else f=!1;rb(b,e);if(null===b.stateNode)null!==a&&(a.alternate=null,b.alternate=null,b.effectTag|=2),Yg(b,c,d),pe(b,c,d,e),d=!0;else if(null===a){var g=b.stateNode,h=b.memoizedProps;g.props=h;var m=g.context,n=c.contextType;"object"===typeof n&&null!==n?n=W(n):(n=N(c)?Ra:B.current,n=pb(b,n));var l=c.getDerivedStateFromProps,k="function"===
typeof l||"function"===typeof g.getSnapshotBeforeUpdate;k||"function"!==typeof g.UNSAFE_componentWillReceiveProps&&"function"!==typeof g.componentWillReceiveProps||(h!==d||m!==n)&&Zg(b,g,d,n);Ga=!1;var p=b.memoizedState;g.state=p;Qb(b,d,g,e);m=b.memoizedState;h!==d||p!==m||G.current||Ga?("function"===typeof l&&(Lc(b,c,l,d),m=b.memoizedState),(h=Ga||Xg(b,c,h,d,p,m,n))?(k||"function"!==typeof g.UNSAFE_componentWillMount&&"function"!==typeof g.componentWillMount||("function"===typeof g.componentWillMount&&
g.componentWillMount(),"function"===typeof g.UNSAFE_componentWillMount&&g.UNSAFE_componentWillMount()),"function"===typeof g.componentDidMount&&(b.effectTag|=4)):("function"===typeof g.componentDidMount&&(b.effectTag|=4),b.memoizedProps=d,b.memoizedState=m),g.props=d,g.state=m,g.context=n,d=h):("function"===typeof g.componentDidMount&&(b.effectTag|=4),d=!1)}else g=b.stateNode,oe(a,b),h=b.memoizedProps,g.props=b.type===b.elementType?h:aa(b.type,h),m=g.context,n=c.contextType,"object"===typeof n&&null!==
n?n=W(n):(n=N(c)?Ra:B.current,n=pb(b,n)),l=c.getDerivedStateFromProps,(k="function"===typeof l||"function"===typeof g.getSnapshotBeforeUpdate)||"function"!==typeof g.UNSAFE_componentWillReceiveProps&&"function"!==typeof g.componentWillReceiveProps||(h!==d||m!==n)&&Zg(b,g,d,n),Ga=!1,m=b.memoizedState,g.state=m,Qb(b,d,g,e),p=b.memoizedState,h!==d||m!==p||G.current||Ga?("function"===typeof l&&(Lc(b,c,l,d),p=b.memoizedState),(l=Ga||Xg(b,c,h,d,m,p,n))?(k||"function"!==typeof g.UNSAFE_componentWillUpdate&&
"function"!==typeof g.componentWillUpdate||("function"===typeof g.componentWillUpdate&&g.componentWillUpdate(d,p,n),"function"===typeof g.UNSAFE_componentWillUpdate&&g.UNSAFE_componentWillUpdate(d,p,n)),"function"===typeof g.componentDidUpdate&&(b.effectTag|=4),"function"===typeof g.getSnapshotBeforeUpdate&&(b.effectTag|=256)):("function"!==typeof g.componentDidUpdate||h===a.memoizedProps&&m===a.memoizedState||(b.effectTag|=4),"function"!==typeof g.getSnapshotBeforeUpdate||h===a.memoizedProps&&m===
a.memoizedState||(b.effectTag|=256),b.memoizedProps=d,b.memoizedState=p),g.props=d,g.state=p,g.context=n,d=l):("function"!==typeof g.componentDidUpdate||h===a.memoizedProps&&m===a.memoizedState||(b.effectTag|=4),"function"!==typeof g.getSnapshotBeforeUpdate||h===a.memoizedProps&&m===a.memoizedState||(b.effectTag|=256),d=!1);return Ie(a,b,c,d,f,e)}function Ie(a,b,c,d,e,f){qh(a,b);var g=0!==(b.effectTag&64);if(!d&&!g)return e&&Hg(b,c,!1),sa(a,b,f);d=b.stateNode;gj.current=b;var h=g&&"function"!==typeof c.getDerivedStateFromError?
null:d.render();b.effectTag|=1;null!==a&&g?(b.child=wb(b,a.child,null,f),b.child=wb(b,null,h,f)):T(a,b,h,f);b.memoizedState=d.state;e&&Hg(b,c,!0);return b.child}function sh(a){var b=a.stateNode;b.pendingContext?Fg(a,b.pendingContext,b.pendingContext!==b.context):b.context&&Fg(a,b.context,!1);se(a,b.containerInfo)}function th(a,b,c){var d=b.mode,e=b.pendingProps,f=D.current,g=!1,h;(h=0!==(b.effectTag&64))||(h=0!==(f&2)&&(null===a||null!==a.memoizedState));h?(g=!0,b.effectTag&=-65):null!==a&&null===
a.memoizedState||void 0===e.fallback||!0===e.unstable_avoidThisFallback||(f|=1);y(D,f&1);if(null===a){void 0!==e.fallback&&De(b);if(g){g=e.fallback;e=Ha(null,d,0,null);e.return=b;if(0===(b.mode&2))for(a=null!==b.memoizedState?b.child.child:b.child,e.child=a;null!==a;)a.return=e,a=a.sibling;c=Ha(g,d,c,null);c.return=b;e.sibling=c;b.memoizedState=Je;b.child=e;return c}d=e.children;b.memoizedState=null;return b.child=Fe(b,null,d,c)}if(null!==a.memoizedState){a=a.child;d=a.sibling;if(g){e=e.fallback;
c=Sa(a,a.pendingProps);c.return=b;if(0===(b.mode&2)&&(g=null!==b.memoizedState?b.child.child:b.child,g!==a.child))for(c.child=g;null!==g;)g.return=c,g=g.sibling;d=Sa(d,e);d.return=b;c.sibling=d;c.childExpirationTime=0;b.memoizedState=Je;b.child=c;return d}c=wb(b,a.child,e.children,c);b.memoizedState=null;return b.child=c}a=a.child;if(g){g=e.fallback;e=Ha(null,d,0,null);e.return=b;e.child=a;null!==a&&(a.return=e);if(0===(b.mode&2))for(a=null!==b.memoizedState?b.child.child:b.child,e.child=a;null!==
a;)a.return=e,a=a.sibling;c=Ha(g,d,c,null);c.return=b;e.sibling=c;c.effectTag|=2;e.childExpirationTime=0;b.memoizedState=Je;b.child=e;return c}b.memoizedState=null;return b.child=wb(b,a,e.children,c)}function uh(a,b){a.expirationTime<b&&(a.expirationTime=b);var c=a.alternate;null!==c&&c.expirationTime<b&&(c.expirationTime=b);Sg(a.return,b)}function Ke(a,b,c,d,e,f){var g=a.memoizedState;null===g?a.memoizedState={isBackwards:b,rendering:null,renderingStartTime:0,last:d,tail:c,tailExpiration:0,tailMode:e,
lastEffect:f}:(g.isBackwards=b,g.rendering=null,g.renderingStartTime=0,g.last=d,g.tail=c,g.tailExpiration=0,g.tailMode=e,g.lastEffect=f)}function vh(a,b,c){var d=b.pendingProps,e=d.revealOrder,f=d.tail;T(a,b,d.children,c);d=D.current;if(0!==(d&2))d=d&1|2,b.effectTag|=64;else{if(null!==a&&0!==(a.effectTag&64))a:for(a=b.child;null!==a;){if(13===a.tag)null!==a.memoizedState&&uh(a,c);else if(19===a.tag)uh(a,c);else if(null!==a.child){a.child.return=a;a=a.child;continue}if(a===b)break a;for(;null===a.sibling;){if(null===
a.return||a.return===b)break a;a=a.return}a.sibling.return=a.return;a=a.sibling}d&=1}y(D,d);if(0===(b.mode&2))b.memoizedState=null;else switch(e){case "forwards":c=b.child;for(e=null;null!==c;)a=c.alternate,null!==a&&null===Rc(a)&&(e=c),c=c.sibling;c=e;null===c?(e=b.child,b.child=null):(e=c.sibling,c.sibling=null);Ke(b,!1,e,c,f,b.lastEffect);break;case "backwards":c=null;e=b.child;for(b.child=null;null!==e;){a=e.alternate;if(null!==a&&null===Rc(a)){b.child=e;break}a=e.sibling;e.sibling=c;c=e;e=a}Ke(b,
!0,c,null,f,b.lastEffect);break;case "together":Ke(b,!1,null,null,void 0,b.lastEffect);break;default:b.memoizedState=null}return b.child}function sa(a,b,c){null!==a&&(b.dependencies=a.dependencies);var d=b.expirationTime;0!==d&&Kc(d);if(b.childExpirationTime<c)return null;if(null!==a&&b.child!==a.child)throw Error(k(153));if(null!==b.child){a=b.child;c=Sa(a,a.pendingProps);b.child=c;for(c.return=b;null!==a.sibling;)a=a.sibling,c=c.sibling=Sa(a,a.pendingProps),c.return=b;c.sibling=null}return b.child}
function $c(a,b){switch(a.tailMode){case "hidden":b=a.tail;for(var c=null;null!==b;)null!==b.alternate&&(c=b),b=b.sibling;null===c?a.tail=null:c.sibling=null;break;case "collapsed":c=a.tail;for(var d=null;null!==c;)null!==c.alternate&&(d=c),c=c.sibling;null===d?b||null===a.tail?a.tail=null:a.tail.sibling=null:d.sibling=null}}function hj(a,b,c){var d=b.pendingProps;switch(b.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return null;case 1:return N(b.type)&&(q(G),q(B)),
null;case 3:return tb(),q(G),q(B),c=b.stateNode,c.pendingContext&&(c.context=c.pendingContext,c.pendingContext=null),null!==a&&null!==a.child||!Zc(b)||(b.effectTag|=4),wh(b),null;case 5:te(b);c=Ta(Tb.current);var e=b.type;if(null!==a&&null!=b.stateNode)ij(a,b,e,d,c),a.ref!==b.ref&&(b.effectTag|=128);else{if(!d){if(null===b.stateNode)throw Error(k(166));return null}a=Ta(ja.current);if(Zc(b)){d=b.stateNode;e=b.type;var f=b.memoizedProps;d[Aa]=b;d[vc]=f;switch(e){case "iframe":case "object":case "embed":w("load",
d);break;case "video":case "audio":for(a=0;a<Db.length;a++)w(Db[a],d);break;case "source":w("error",d);break;case "img":case "image":case "link":w("error",d);w("load",d);break;case "form":w("reset",d);w("submit",d);break;case "details":w("toggle",d);break;case "input":Hf(d,f);w("invalid",d);oa(c,"onChange");break;case "select":d._wrapperState={wasMultiple:!!f.multiple};w("invalid",d);oa(c,"onChange");break;case "textarea":Kf(d,f),w("invalid",d),oa(c,"onChange")}Ud(e,f);a=null;for(var g in f)if(f.hasOwnProperty(g)){var h=
f[g];"children"===g?"string"===typeof h?d.textContent!==h&&(a=["children",h]):"number"===typeof h&&d.textContent!==""+h&&(a=["children",""+h]):db.hasOwnProperty(g)&&null!=h&&oa(c,g)}switch(e){case "input":mc(d);Jf(d,f,!0);break;case "textarea":mc(d);Mf(d);break;case "select":case "option":break;default:"function"===typeof f.onClick&&(d.onclick=uc)}c=a;b.updateQueue=c;null!==c&&(b.effectTag|=4)}else{g=9===c.nodeType?c:c.ownerDocument;"http://www.w3.org/1999/xhtml"===a&&(a=Nf(e));"http://www.w3.org/1999/xhtml"===
a?"script"===e?(a=g.createElement("div"),a.innerHTML="<script>\x3c/script>",a=a.removeChild(a.firstChild)):"string"===typeof d.is?a=g.createElement(e,{is:d.is}):(a=g.createElement(e),"select"===e&&(g=a,d.multiple?g.multiple=!0:d.size&&(g.size=d.size))):a=g.createElementNS(a,e);a[Aa]=b;a[vc]=d;jj(a,b,!1,!1);b.stateNode=a;g=Vd(e,d);switch(e){case "iframe":case "object":case "embed":w("load",a);h=d;break;case "video":case "audio":for(h=0;h<Db.length;h++)w(Db[h],a);h=d;break;case "source":w("error",a);
h=d;break;case "img":case "image":case "link":w("error",a);w("load",a);h=d;break;case "form":w("reset",a);w("submit",a);h=d;break;case "details":w("toggle",a);h=d;break;case "input":Hf(a,d);h=Cd(a,d);w("invalid",a);oa(c,"onChange");break;case "option":h=Fd(a,d);break;case "select":a._wrapperState={wasMultiple:!!d.multiple};h=M({},d,{value:void 0});w("invalid",a);oa(c,"onChange");break;case "textarea":Kf(a,d);h=Gd(a,d);w("invalid",a);oa(c,"onChange");break;default:h=d}Ud(e,h);var m=h;for(f in m)if(m.hasOwnProperty(f)){var n=
m[f];"style"===f?gg(a,n):"dangerouslySetInnerHTML"===f?(n=n?n.__html:void 0,null!=n&&xh(a,n)):"children"===f?"string"===typeof n?("textarea"!==e||""!==n)&&Wb(a,n):"number"===typeof n&&Wb(a,""+n):"suppressContentEditableWarning"!==f&&"suppressHydrationWarning"!==f&&"autoFocus"!==f&&(db.hasOwnProperty(f)?null!=n&&oa(c,f):null!=n&&xd(a,f,n,g))}switch(e){case "input":mc(a);Jf(a,d,!1);break;case "textarea":mc(a);Mf(a);break;case "option":null!=d.value&&a.setAttribute("value",""+va(d.value));break;case "select":a.multiple=
!!d.multiple;c=d.value;null!=c?hb(a,!!d.multiple,c,!1):null!=d.defaultValue&&hb(a,!!d.multiple,d.defaultValue,!0);break;default:"function"===typeof h.onClick&&(a.onclick=uc)}lg(e,d)&&(b.effectTag|=4)}null!==b.ref&&(b.effectTag|=128)}return null;case 6:if(a&&null!=b.stateNode)kj(a,b,a.memoizedProps,d);else{if("string"!==typeof d&&null===b.stateNode)throw Error(k(166));c=Ta(Tb.current);Ta(ja.current);Zc(b)?(c=b.stateNode,d=b.memoizedProps,c[Aa]=b,c.nodeValue!==d&&(b.effectTag|=4)):(c=(9===c.nodeType?
c:c.ownerDocument).createTextNode(d),c[Aa]=b,b.stateNode=c)}return null;case 13:q(D);d=b.memoizedState;if(0!==(b.effectTag&64))return b.expirationTime=c,b;c=null!==d;d=!1;null===a?void 0!==b.memoizedProps.fallback&&Zc(b):(e=a.memoizedState,d=null!==e,c||null===e||(e=a.child.sibling,null!==e&&(f=b.firstEffect,null!==f?(b.firstEffect=e,e.nextEffect=f):(b.firstEffect=b.lastEffect=e,e.nextEffect=null),e.effectTag=8)));if(c&&!d&&0!==(b.mode&2))if(null===a&&!0!==b.memoizedProps.unstable_avoidThisFallback||
0!==(D.current&1))F===Xa&&(F=ad);else{if(F===Xa||F===ad)F=bd;0!==Xb&&null!==U&&(Ya(U,P),yh(U,Xb))}if(c||d)b.effectTag|=4;return null;case 4:return tb(),wh(b),null;case 10:return me(b),null;case 17:return N(b.type)&&(q(G),q(B)),null;case 19:q(D);d=b.memoizedState;if(null===d)return null;e=0!==(b.effectTag&64);f=d.rendering;if(null===f)if(e)$c(d,!1);else{if(F!==Xa||null!==a&&0!==(a.effectTag&64))for(f=b.child;null!==f;){a=Rc(f);if(null!==a){b.effectTag|=64;$c(d,!1);e=a.updateQueue;null!==e&&(b.updateQueue=
e,b.effectTag|=4);null===d.lastEffect&&(b.firstEffect=null);b.lastEffect=d.lastEffect;for(d=b.child;null!==d;)e=d,f=c,e.effectTag&=2,e.nextEffect=null,e.firstEffect=null,e.lastEffect=null,a=e.alternate,null===a?(e.childExpirationTime=0,e.expirationTime=f,e.child=null,e.memoizedProps=null,e.memoizedState=null,e.updateQueue=null,e.dependencies=null):(e.childExpirationTime=a.childExpirationTime,e.expirationTime=a.expirationTime,e.child=a.child,e.memoizedProps=a.memoizedProps,e.memoizedState=a.memoizedState,
e.updateQueue=a.updateQueue,f=a.dependencies,e.dependencies=null===f?null:{expirationTime:f.expirationTime,firstContext:f.firstContext,responders:f.responders}),d=d.sibling;y(D,D.current&1|2);return b.child}f=f.sibling}}else{if(!e)if(a=Rc(f),null!==a){if(b.effectTag|=64,e=!0,c=a.updateQueue,null!==c&&(b.updateQueue=c,b.effectTag|=4),$c(d,!0),null===d.tail&&"hidden"===d.tailMode&&!f.alternate)return b=b.lastEffect=d.lastEffect,null!==b&&(b.nextEffect=null),null}else 2*Y()-d.renderingStartTime>d.tailExpiration&&
1<c&&(b.effectTag|=64,e=!0,$c(d,!1),b.expirationTime=b.childExpirationTime=c-1);d.isBackwards?(f.sibling=b.child,b.child=f):(c=d.last,null!==c?c.sibling=f:b.child=f,d.last=f)}return null!==d.tail?(0===d.tailExpiration&&(d.tailExpiration=Y()+500),c=d.tail,d.rendering=c,d.tail=c.sibling,d.lastEffect=b.lastEffect,d.renderingStartTime=Y(),c.sibling=null,b=D.current,y(D,e?b&1|2:b&1),c):null}throw Error(k(156,b.tag));}function lj(a,b){switch(a.tag){case 1:return N(a.type)&&(q(G),q(B)),b=a.effectTag,b&4096?
(a.effectTag=b&-4097|64,a):null;case 3:tb();q(G);q(B);b=a.effectTag;if(0!==(b&64))throw Error(k(285));a.effectTag=b&-4097|64;return a;case 5:return te(a),null;case 13:return q(D),b=a.effectTag,b&4096?(a.effectTag=b&-4097|64,a):null;case 19:return q(D),null;case 4:return tb(),null;case 10:return me(a),null;default:return null}}function Le(a,b){return{value:a,source:b,stack:Bd(b)}}function Me(a,b){var c=b.source,d=b.stack;null===d&&null!==c&&(d=Bd(c));null!==c&&na(c.type);b=b.value;null!==a&&1===a.tag&&
na(a.type);try{console.error(b)}catch(e){setTimeout(function(){throw e;})}}function mj(a,b){try{b.props=a.memoizedProps,b.state=a.memoizedState,b.componentWillUnmount()}catch(c){Za(a,c)}}function zh(a){var b=a.ref;if(null!==b)if("function"===typeof b)try{b(null)}catch(c){Za(a,c)}else b.current=null}function nj(a,b){switch(b.tag){case 0:case 11:case 15:case 22:return;case 1:if(b.effectTag&256&&null!==a){var c=a.memoizedProps,d=a.memoizedState;a=b.stateNode;b=a.getSnapshotBeforeUpdate(b.elementType===
b.type?c:aa(b.type,c),d);a.__reactInternalSnapshotBeforeUpdate=b}return;case 3:case 5:case 6:case 4:case 17:return}throw Error(k(163));}function Ah(a,b){b=b.updateQueue;b=null!==b?b.lastEffect:null;if(null!==b){var c=b=b.next;do{if((c.tag&a)===a){var d=c.destroy;c.destroy=void 0;void 0!==d&&d()}c=c.next}while(c!==b)}}function Bh(a,b){b=b.updateQueue;b=null!==b?b.lastEffect:null;if(null!==b){var c=b=b.next;do{if((c.tag&a)===a){var d=c.create;c.destroy=d()}c=c.next}while(c!==b)}}function oj(a,b,c,d){switch(c.tag){case 0:case 11:case 15:case 22:Bh(3,
c);return;case 1:a=c.stateNode;c.effectTag&4&&(null===b?a.componentDidMount():(d=c.elementType===c.type?b.memoizedProps:aa(c.type,b.memoizedProps),a.componentDidUpdate(d,b.memoizedState,a.__reactInternalSnapshotBeforeUpdate)));b=c.updateQueue;null!==b&&Wg(c,b,a);return;case 3:b=c.updateQueue;if(null!==b){a=null;if(null!==c.child)switch(c.child.tag){case 5:a=c.child.stateNode;break;case 1:a=c.child.stateNode}Wg(c,b,a)}return;case 5:a=c.stateNode;null===b&&c.effectTag&4&&lg(c.type,c.memoizedProps)&&
a.focus();return;case 6:return;case 4:return;case 12:return;case 13:null===c.memoizedState&&(c=c.alternate,null!==c&&(c=c.memoizedState,null!==c&&(c=c.dehydrated,null!==c&&bg(c))));return;case 19:case 17:case 20:case 21:return}throw Error(k(163));}function Ch(a,b,c){"function"===typeof Ne&&Ne(b);switch(b.tag){case 0:case 11:case 14:case 15:case 22:a=b.updateQueue;if(null!==a&&(a=a.lastEffect,null!==a)){var d=a.next;Da(97<c?97:c,function(){var a=d;do{var c=a.destroy;if(void 0!==c){var g=b;try{c()}catch(h){Za(g,
h)}}a=a.next}while(a!==d)})}break;case 1:zh(b);c=b.stateNode;"function"===typeof c.componentWillUnmount&&mj(b,c);break;case 5:zh(b);break;case 4:Dh(a,b,c)}}function Eh(a){var b=a.alternate;a.return=null;a.child=null;a.memoizedState=null;a.updateQueue=null;a.dependencies=null;a.alternate=null;a.firstEffect=null;a.lastEffect=null;a.pendingProps=null;a.memoizedProps=null;a.stateNode=null;null!==b&&Eh(b)}function Fh(a){return 5===a.tag||3===a.tag||4===a.tag}function Gh(a){a:{for(var b=a.return;null!==
b;){if(Fh(b)){var c=b;break a}b=b.return}throw Error(k(160));}b=c.stateNode;switch(c.tag){case 5:var d=!1;break;case 3:b=b.containerInfo;d=!0;break;case 4:b=b.containerInfo;d=!0;break;default:throw Error(k(161));}c.effectTag&16&&(Wb(b,""),c.effectTag&=-17);a:b:for(c=a;;){for(;null===c.sibling;){if(null===c.return||Fh(c.return)){c=null;break a}c=c.return}c.sibling.return=c.return;for(c=c.sibling;5!==c.tag&&6!==c.tag&&18!==c.tag;){if(c.effectTag&2)continue b;if(null===c.child||4===c.tag)continue b;
else c.child.return=c,c=c.child}if(!(c.effectTag&2)){c=c.stateNode;break a}}d?Oe(a,c,b):Pe(a,c,b)}function Oe(a,b,c){var d=a.tag,e=5===d||6===d;if(e)a=e?a.stateNode:a.stateNode.instance,b?8===c.nodeType?c.parentNode.insertBefore(a,b):c.insertBefore(a,b):(8===c.nodeType?(b=c.parentNode,b.insertBefore(a,c)):(b=c,b.appendChild(a)),c=c._reactRootContainer,null!==c&&void 0!==c||null!==b.onclick||(b.onclick=uc));else if(4!==d&&(a=a.child,null!==a))for(Oe(a,b,c),a=a.sibling;null!==a;)Oe(a,b,c),a=a.sibling}
function Pe(a,b,c){var d=a.tag,e=5===d||6===d;if(e)a=e?a.stateNode:a.stateNode.instance,b?c.insertBefore(a,b):c.appendChild(a);else if(4!==d&&(a=a.child,null!==a))for(Pe(a,b,c),a=a.sibling;null!==a;)Pe(a,b,c),a=a.sibling}function Dh(a,b,c){for(var d=b,e=!1,f,g;;){if(!e){e=d.return;a:for(;;){if(null===e)throw Error(k(160));f=e.stateNode;switch(e.tag){case 5:g=!1;break a;case 3:f=f.containerInfo;g=!0;break a;case 4:f=f.containerInfo;g=!0;break a}e=e.return}e=!0}if(5===d.tag||6===d.tag){a:for(var h=
a,m=d,n=c,l=m;;)if(Ch(h,l,n),null!==l.child&&4!==l.tag)l.child.return=l,l=l.child;else{if(l===m)break a;for(;null===l.sibling;){if(null===l.return||l.return===m)break a;l=l.return}l.sibling.return=l.return;l=l.sibling}g?(h=f,m=d.stateNode,8===h.nodeType?h.parentNode.removeChild(m):h.removeChild(m)):f.removeChild(d.stateNode)}else if(4===d.tag){if(null!==d.child){f=d.stateNode.containerInfo;g=!0;d.child.return=d;d=d.child;continue}}else if(Ch(a,d,c),null!==d.child){d.child.return=d;d=d.child;continue}if(d===
b)break;for(;null===d.sibling;){if(null===d.return||d.return===b)return;d=d.return;4===d.tag&&(e=!1)}d.sibling.return=d.return;d=d.sibling}}function Qe(a,b){switch(b.tag){case 0:case 11:case 14:case 15:case 22:Ah(3,b);return;case 1:return;case 5:var c=b.stateNode;if(null!=c){var d=b.memoizedProps,e=null!==a?a.memoizedProps:d;a=b.type;var f=b.updateQueue;b.updateQueue=null;if(null!==f){c[vc]=d;"input"===a&&"radio"===d.type&&null!=d.name&&If(c,d);Vd(a,e);b=Vd(a,d);for(e=0;e<f.length;e+=2){var g=f[e],
h=f[e+1];"style"===g?gg(c,h):"dangerouslySetInnerHTML"===g?xh(c,h):"children"===g?Wb(c,h):xd(c,g,h,b)}switch(a){case "input":Dd(c,d);break;case "textarea":Lf(c,d);break;case "select":b=c._wrapperState.wasMultiple,c._wrapperState.wasMultiple=!!d.multiple,a=d.value,null!=a?hb(c,!!d.multiple,a,!1):b!==!!d.multiple&&(null!=d.defaultValue?hb(c,!!d.multiple,d.defaultValue,!0):hb(c,!!d.multiple,d.multiple?[]:"",!1))}}}return;case 6:if(null===b.stateNode)throw Error(k(162));b.stateNode.nodeValue=b.memoizedProps;
return;case 3:b=b.stateNode;b.hydrate&&(b.hydrate=!1,bg(b.containerInfo));return;case 12:return;case 13:c=b;null===b.memoizedState?d=!1:(d=!0,c=b.child,Re=Y());if(null!==c)a:for(a=c;;){if(5===a.tag)f=a.stateNode,d?(f=f.style,"function"===typeof f.setProperty?f.setProperty("display","none","important"):f.display="none"):(f=a.stateNode,e=a.memoizedProps.style,e=void 0!==e&&null!==e&&e.hasOwnProperty("display")?e.display:null,f.style.display=fg("display",e));else if(6===a.tag)a.stateNode.nodeValue=d?
"":a.memoizedProps;else if(13===a.tag&&null!==a.memoizedState&&null===a.memoizedState.dehydrated){f=a.child.sibling;f.return=a;a=f;continue}else if(null!==a.child){a.child.return=a;a=a.child;continue}if(a===c)break;for(;null===a.sibling;){if(null===a.return||a.return===c)break a;a=a.return}a.sibling.return=a.return;a=a.sibling}Hh(b);return;case 19:Hh(b);return;case 17:return}throw Error(k(163));}function Hh(a){var b=a.updateQueue;if(null!==b){a.updateQueue=null;var c=a.stateNode;null===c&&(c=a.stateNode=
new pj);b.forEach(function(b){var d=qj.bind(null,a,b);c.has(b)||(c.add(b),b.then(d,d))})}}function Ih(a,b,c){c=Ea(c,null);c.tag=3;c.payload={element:null};var d=b.value;c.callback=function(){cd||(cd=!0,Se=d);Me(a,b)};return c}function Jh(a,b,c){c=Ea(c,null);c.tag=3;var d=a.type.getDerivedStateFromError;if("function"===typeof d){var e=b.value;c.payload=function(){Me(a,b);return d(e)}}var f=a.stateNode;null!==f&&"function"===typeof f.componentDidCatch&&(c.callback=function(){"function"!==typeof d&&
(null===La?La=new Set([this]):La.add(this),Me(a,b));var c=b.stack;this.componentDidCatch(b.value,{componentStack:null!==c?c:""})});return c}function ka(){return(p&(ca|ma))!==H?1073741821-(Y()/10|0):0!==dd?dd:dd=1073741821-(Y()/10|0)}function Va(a,b,c){b=b.mode;if(0===(b&2))return 1073741823;var d=Cc();if(0===(b&4))return 99===d?1073741823:1073741822;if((p&ca)!==H)return P;if(null!==c)a=Fc(a,c.timeoutMs|0||5E3,250);else switch(d){case 99:a=1073741823;break;case 98:a=Fc(a,150,100);break;case 97:case 96:a=
Fc(a,5E3,250);break;case 95:a=2;break;default:throw Error(k(326));}null!==U&&a===P&&--a;return a}function ed(a,b){a.expirationTime<b&&(a.expirationTime=b);var c=a.alternate;null!==c&&c.expirationTime<b&&(c.expirationTime=b);var d=a.return,e=null;if(null===d&&3===a.tag)e=a.stateNode;else for(;null!==d;){c=d.alternate;d.childExpirationTime<b&&(d.childExpirationTime=b);null!==c&&c.childExpirationTime<b&&(c.childExpirationTime=b);if(null===d.return&&3===d.tag){e=d.stateNode;break}d=d.return}null!==e&&
(U===e&&(Kc(b),F===bd&&Ya(e,P)),yh(e,b));return e}function fd(a){var b=a.lastExpiredTime;if(0!==b)return b;b=a.firstPendingTime;if(!Kh(a,b))return b;var c=a.lastPingedTime;a=a.nextKnownPendingLevel;a=c>a?c:a;return 2>=a&&b!==a?0:a}function V(a){if(0!==a.lastExpiredTime)a.callbackExpirationTime=1073741823,a.callbackPriority=99,a.callbackNode=Og(Te.bind(null,a));else{var b=fd(a),c=a.callbackNode;if(0===b)null!==c&&(a.callbackNode=null,a.callbackExpirationTime=0,a.callbackPriority=90);else{var d=ka();
1073741823===b?d=99:1===b||2===b?d=95:(d=10*(1073741821-b)-10*(1073741821-d),d=0>=d?99:250>=d?98:5250>=d?97:95);if(null!==c){var e=a.callbackPriority;if(a.callbackExpirationTime===b&&e>=d)return;c!==Qg&&Rg(c)}a.callbackExpirationTime=b;a.callbackPriority=d;b=1073741823===b?Og(Te.bind(null,a)):Ng(d,Lh.bind(null,a),{timeout:10*(1073741821-b)-Y()});a.callbackNode=b}}}function Lh(a,b){dd=0;if(b)return b=ka(),Ue(a,b),V(a),null;var c=fd(a);if(0!==c){b=a.callbackNode;if((p&(ca|ma))!==H)throw Error(k(327));
xb();a===U&&c===P||$a(a,c);if(null!==t){var d=p;p|=ca;var e=Mh();do try{rj();break}catch(h){Nh(a,h)}while(1);le();p=d;gd.current=e;if(F===hd)throw b=id,$a(a,c),Ya(a,c),V(a),b;if(null===t)switch(e=a.finishedWork=a.current.alternate,a.finishedExpirationTime=c,d=F,U=null,d){case Xa:case hd:throw Error(k(345));case Oh:Ue(a,2<c?2:c);break;case ad:Ya(a,c);d=a.lastSuspendedTime;c===d&&(a.nextKnownPendingLevel=Ve(e));if(1073741823===ta&&(e=Re+Ph-Y(),10<e)){if(jd){var f=a.lastPingedTime;if(0===f||f>=c){a.lastPingedTime=
c;$a(a,c);break}}f=fd(a);if(0!==f&&f!==c)break;if(0!==d&&d!==c){a.lastPingedTime=d;break}a.timeoutHandle=We(ab.bind(null,a),e);break}ab(a);break;case bd:Ya(a,c);d=a.lastSuspendedTime;c===d&&(a.nextKnownPendingLevel=Ve(e));if(jd&&(e=a.lastPingedTime,0===e||e>=c)){a.lastPingedTime=c;$a(a,c);break}e=fd(a);if(0!==e&&e!==c)break;if(0!==d&&d!==c){a.lastPingedTime=d;break}1073741823!==Yb?d=10*(1073741821-Yb)-Y():1073741823===ta?d=0:(d=10*(1073741821-ta)-5E3,e=Y(),c=10*(1073741821-c)-e,d=e-d,0>d&&(d=0),d=
(120>d?120:480>d?480:1080>d?1080:1920>d?1920:3E3>d?3E3:4320>d?4320:1960*sj(d/1960))-d,c<d&&(d=c));if(10<d){a.timeoutHandle=We(ab.bind(null,a),d);break}ab(a);break;case Xe:if(1073741823!==ta&&null!==kd){f=ta;var g=kd;d=g.busyMinDurationMs|0;0>=d?d=0:(e=g.busyDelayMs|0,f=Y()-(10*(1073741821-f)-(g.timeoutMs|0||5E3)),d=f<=e?0:e+d-f);if(10<d){Ya(a,c);a.timeoutHandle=We(ab.bind(null,a),d);break}}ab(a);break;default:throw Error(k(329));}V(a);if(a.callbackNode===b)return Lh.bind(null,a)}}return null}function Te(a){var b=
a.lastExpiredTime;b=0!==b?b:1073741823;if((p&(ca|ma))!==H)throw Error(k(327));xb();a===U&&b===P||$a(a,b);if(null!==t){var c=p;p|=ca;var d=Mh();do try{tj();break}catch(e){Nh(a,e)}while(1);le();p=c;gd.current=d;if(F===hd)throw c=id,$a(a,b),Ya(a,b),V(a),c;if(null!==t)throw Error(k(261));a.finishedWork=a.current.alternate;a.finishedExpirationTime=b;U=null;ab(a);V(a)}return null}function uj(){if(null!==bb){var a=bb;bb=null;a.forEach(function(a,c){Ue(c,a);V(c)});ha()}}function Qh(a,b){var c=p;p|=1;try{return a(b)}finally{p=
c,p===H&&ha()}}function Rh(a,b){var c=p;p&=-2;p|=Ye;try{return a(b)}finally{p=c,p===H&&ha()}}function $a(a,b){a.finishedWork=null;a.finishedExpirationTime=0;var c=a.timeoutHandle;-1!==c&&(a.timeoutHandle=-1,vj(c));if(null!==t)for(c=t.return;null!==c;){var d=c;switch(d.tag){case 1:d=d.type.childContextTypes;null!==d&&void 0!==d&&(q(G),q(B));break;case 3:tb();q(G);q(B);break;case 5:te(d);break;case 4:tb();break;case 13:q(D);break;case 19:q(D);break;case 10:me(d)}c=c.return}U=a;t=Sa(a.current,null);
P=b;F=Xa;id=null;Yb=ta=1073741823;kd=null;Xb=0;jd=!1}function Nh(a,b){do{try{le();Sc.current=Tc;if(Uc)for(var c=z.memoizedState;null!==c;){var d=c.queue;null!==d&&(d.pending=null);c=c.next}Ia=0;J=K=z=null;Uc=!1;if(null===t||null===t.return)return F=hd,id=b,t=null;a:{var e=a,f=t.return,g=t,h=b;b=P;g.effectTag|=2048;g.firstEffect=g.lastEffect=null;if(null!==h&&"object"===typeof h&&"function"===typeof h.then){var m=h;if(0===(g.mode&2)){var n=g.alternate;n?(g.updateQueue=n.updateQueue,g.memoizedState=
n.memoizedState,g.expirationTime=n.expirationTime):(g.updateQueue=null,g.memoizedState=null)}var l=0!==(D.current&1),k=f;do{var p;if(p=13===k.tag){var q=k.memoizedState;if(null!==q)p=null!==q.dehydrated?!0:!1;else{var w=k.memoizedProps;p=void 0===w.fallback?!1:!0!==w.unstable_avoidThisFallback?!0:l?!1:!0}}if(p){var y=k.updateQueue;if(null===y){var r=new Set;r.add(m);k.updateQueue=r}else y.add(m);if(0===(k.mode&2)){k.effectTag|=64;g.effectTag&=-2981;if(1===g.tag)if(null===g.alternate)g.tag=17;else{var O=
Ea(1073741823,null);O.tag=Jc;Fa(g,O)}g.expirationTime=1073741823;break a}h=void 0;g=b;var v=e.pingCache;null===v?(v=e.pingCache=new wj,h=new Set,v.set(m,h)):(h=v.get(m),void 0===h&&(h=new Set,v.set(m,h)));if(!h.has(g)){h.add(g);var x=xj.bind(null,e,m,g);m.then(x,x)}k.effectTag|=4096;k.expirationTime=b;break a}k=k.return}while(null!==k);h=Error((na(g.type)||"A React component")+" suspended while rendering, but no fallback UI was specified.\n\nAdd a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display."+
Bd(g))}F!==Xe&&(F=Oh);h=Le(h,g);k=f;do{switch(k.tag){case 3:m=h;k.effectTag|=4096;k.expirationTime=b;var A=Ih(k,m,b);Ug(k,A);break a;case 1:m=h;var u=k.type,B=k.stateNode;if(0===(k.effectTag&64)&&("function"===typeof u.getDerivedStateFromError||null!==B&&"function"===typeof B.componentDidCatch&&(null===La||!La.has(B)))){k.effectTag|=4096;k.expirationTime=b;var H=Jh(k,m,b);Ug(k,H);break a}}k=k.return}while(null!==k)}t=Sh(t)}catch(cj){b=cj;continue}break}while(1)}function Mh(a){a=gd.current;gd.current=
Tc;return null===a?Tc:a}function Vg(a,b){a<ta&&2<a&&(ta=a);null!==b&&a<Yb&&2<a&&(Yb=a,kd=b)}function Kc(a){a>Xb&&(Xb=a)}function tj(){for(;null!==t;)t=Th(t)}function rj(){for(;null!==t&&!yj();)t=Th(t)}function Th(a){var b=zj(a.alternate,a,P);a.memoizedProps=a.pendingProps;null===b&&(b=Sh(a));Uh.current=null;return b}function Sh(a){t=a;do{var b=t.alternate;a=t.return;if(0===(t.effectTag&2048)){b=hj(b,t,P);if(1===P||1!==t.childExpirationTime){for(var c=0,d=t.child;null!==d;){var e=d.expirationTime,
f=d.childExpirationTime;e>c&&(c=e);f>c&&(c=f);d=d.sibling}t.childExpirationTime=c}if(null!==b)return b;null!==a&&0===(a.effectTag&2048)&&(null===a.firstEffect&&(a.firstEffect=t.firstEffect),null!==t.lastEffect&&(null!==a.lastEffect&&(a.lastEffect.nextEffect=t.firstEffect),a.lastEffect=t.lastEffect),1<t.effectTag&&(null!==a.lastEffect?a.lastEffect.nextEffect=t:a.firstEffect=t,a.lastEffect=t))}else{b=lj(t);if(null!==b)return b.effectTag&=2047,b;null!==a&&(a.firstEffect=a.lastEffect=null,a.effectTag|=
2048)}b=t.sibling;if(null!==b)return b;t=a}while(null!==t);F===Xa&&(F=Xe);return null}function Ve(a){var b=a.expirationTime;a=a.childExpirationTime;return b>a?b:a}function ab(a){var b=Cc();Da(99,Aj.bind(null,a,b));return null}function Aj(a,b){do xb();while(null!==Zb);if((p&(ca|ma))!==H)throw Error(k(327));var c=a.finishedWork,d=a.finishedExpirationTime;if(null===c)return null;a.finishedWork=null;a.finishedExpirationTime=0;if(c===a.current)throw Error(k(177));a.callbackNode=null;a.callbackExpirationTime=
0;a.callbackPriority=90;a.nextKnownPendingLevel=0;var e=Ve(c);a.firstPendingTime=e;d<=a.lastSuspendedTime?a.firstSuspendedTime=a.lastSuspendedTime=a.nextKnownPendingLevel=0:d<=a.firstSuspendedTime&&(a.firstSuspendedTime=d-1);d<=a.lastPingedTime&&(a.lastPingedTime=0);d<=a.lastExpiredTime&&(a.lastExpiredTime=0);a===U&&(t=U=null,P=0);1<c.effectTag?null!==c.lastEffect?(c.lastEffect.nextEffect=c,e=c.firstEffect):e=c:e=c.firstEffect;if(null!==e){var f=p;p|=ma;Uh.current=null;Ze=tc;var g=kg();if(Xd(g)){if("selectionStart"in
g)var h={start:g.selectionStart,end:g.selectionEnd};else a:{h=(h=g.ownerDocument)&&h.defaultView||window;var m=h.getSelection&&h.getSelection();if(m&&0!==m.rangeCount){h=m.anchorNode;var n=m.anchorOffset,q=m.focusNode;m=m.focusOffset;try{h.nodeType,q.nodeType}catch(sb){h=null;break a}var ba=0,w=-1,y=-1,B=0,D=0,r=g,z=null;b:for(;;){for(var v;;){r!==h||0!==n&&3!==r.nodeType||(w=ba+n);r!==q||0!==m&&3!==r.nodeType||(y=ba+m);3===r.nodeType&&(ba+=r.nodeValue.length);if(null===(v=r.firstChild))break;z=r;
r=v}for(;;){if(r===g)break b;z===h&&++B===n&&(w=ba);z===q&&++D===m&&(y=ba);if(null!==(v=r.nextSibling))break;r=z;z=r.parentNode}r=v}h=-1===w||-1===y?null:{start:w,end:y}}else h=null}h=h||{start:0,end:0}}else h=null;$e={activeElementDetached:null,focusedElem:g,selectionRange:h};tc=!1;l=e;do try{Bj()}catch(sb){if(null===l)throw Error(k(330));Za(l,sb);l=l.nextEffect}while(null!==l);l=e;do try{for(g=a,h=b;null!==l;){var x=l.effectTag;x&16&&Wb(l.stateNode,"");if(x&128){var A=l.alternate;if(null!==A){var u=
A.ref;null!==u&&("function"===typeof u?u(null):u.current=null)}}switch(x&1038){case 2:Gh(l);l.effectTag&=-3;break;case 6:Gh(l);l.effectTag&=-3;Qe(l.alternate,l);break;case 1024:l.effectTag&=-1025;break;case 1028:l.effectTag&=-1025;Qe(l.alternate,l);break;case 4:Qe(l.alternate,l);break;case 8:n=l,Dh(g,n,h),Eh(n)}l=l.nextEffect}}catch(sb){if(null===l)throw Error(k(330));Za(l,sb);l=l.nextEffect}while(null!==l);u=$e;A=kg();x=u.focusedElem;h=u.selectionRange;if(A!==x&&x&&x.ownerDocument&&jg(x.ownerDocument.documentElement,
x)){null!==h&&Xd(x)&&(A=h.start,u=h.end,void 0===u&&(u=A),"selectionStart"in x?(x.selectionStart=A,x.selectionEnd=Math.min(u,x.value.length)):(u=(A=x.ownerDocument||document)&&A.defaultView||window,u.getSelection&&(u=u.getSelection(),n=x.textContent.length,g=Math.min(h.start,n),h=void 0===h.end?g:Math.min(h.end,n),!u.extend&&g>h&&(n=h,h=g,g=n),n=ig(x,g),q=ig(x,h),n&&q&&(1!==u.rangeCount||u.anchorNode!==n.node||u.anchorOffset!==n.offset||u.focusNode!==q.node||u.focusOffset!==q.offset)&&(A=A.createRange(),
A.setStart(n.node,n.offset),u.removeAllRanges(),g>h?(u.addRange(A),u.extend(q.node,q.offset)):(A.setEnd(q.node,q.offset),u.addRange(A))))));A=[];for(u=x;u=u.parentNode;)1===u.nodeType&&A.push({element:u,left:u.scrollLeft,top:u.scrollTop});"function"===typeof x.focus&&x.focus();for(x=0;x<A.length;x++)u=A[x],u.element.scrollLeft=u.left,u.element.scrollTop=u.top}tc=!!Ze;$e=Ze=null;a.current=c;l=e;do try{for(x=a;null!==l;){var F=l.effectTag;F&36&&oj(x,l.alternate,l);if(F&128){A=void 0;var E=l.ref;if(null!==
E){var G=l.stateNode;switch(l.tag){case 5:A=G;break;default:A=G}"function"===typeof E?E(A):E.current=A}}l=l.nextEffect}}catch(sb){if(null===l)throw Error(k(330));Za(l,sb);l=l.nextEffect}while(null!==l);l=null;Cj();p=f}else a.current=c;if(ld)ld=!1,Zb=a,$b=b;else for(l=e;null!==l;)b=l.nextEffect,l.nextEffect=null,l=b;b=a.firstPendingTime;0===b&&(La=null);1073741823===b?a===af?ac++:(ac=0,af=a):ac=0;"function"===typeof bf&&bf(c.stateNode,d);V(a);if(cd)throw cd=!1,a=Se,Se=null,a;if((p&Ye)!==H)return null;
ha();return null}function Bj(){for(;null!==l;){var a=l.effectTag;0!==(a&256)&&nj(l.alternate,l);0===(a&512)||ld||(ld=!0,Ng(97,function(){xb();return null}));l=l.nextEffect}}function xb(){if(90!==$b){var a=97<$b?97:$b;$b=90;return Da(a,Dj)}}function Dj(){if(null===Zb)return!1;var a=Zb;Zb=null;if((p&(ca|ma))!==H)throw Error(k(331));var b=p;p|=ma;for(a=a.current.firstEffect;null!==a;){try{var c=a;if(0!==(c.effectTag&512))switch(c.tag){case 0:case 11:case 15:case 22:Ah(5,c),Bh(5,c)}}catch(d){if(null===
a)throw Error(k(330));Za(a,d)}c=a.nextEffect;a.nextEffect=null;a=c}p=b;ha();return!0}function Vh(a,b,c){b=Le(c,b);b=Ih(a,b,1073741823);Fa(a,b);a=ed(a,1073741823);null!==a&&V(a)}function Za(a,b){if(3===a.tag)Vh(a,a,b);else for(var c=a.return;null!==c;){if(3===c.tag){Vh(c,a,b);break}else if(1===c.tag){var d=c.stateNode;if("function"===typeof c.type.getDerivedStateFromError||"function"===typeof d.componentDidCatch&&(null===La||!La.has(d))){a=Le(b,a);a=Jh(c,a,1073741823);Fa(c,a);c=ed(c,1073741823);null!==
c&&V(c);break}}c=c.return}}function xj(a,b,c){var d=a.pingCache;null!==d&&d.delete(b);U===a&&P===c?F===bd||F===ad&&1073741823===ta&&Y()-Re<Ph?$a(a,P):jd=!0:Kh(a,c)&&(b=a.lastPingedTime,0!==b&&b<c||(a.lastPingedTime=c,V(a)))}function qj(a,b){var c=a.stateNode;null!==c&&c.delete(b);b=0;0===b&&(b=ka(),b=Va(b,a,null));a=ed(a,b);null!==a&&V(a)}function Ej(a){if("undefined"===typeof __REACT_DEVTOOLS_GLOBAL_HOOK__)return!1;var b=__REACT_DEVTOOLS_GLOBAL_HOOK__;if(b.isDisabled||!b.supportsFiber)return!0;try{var c=
b.inject(a);bf=function(a,e){try{b.onCommitFiberRoot(c,a,void 0,64===(a.current.effectTag&64))}catch(f){}};Ne=function(a){try{b.onCommitFiberUnmount(c,a)}catch(e){}}}catch(d){}return!0}function Fj(a,b,c,d){this.tag=a;this.key=c;this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null;this.index=0;this.ref=null;this.pendingProps=b;this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null;this.mode=d;this.effectTag=0;this.lastEffect=this.firstEffect=this.nextEffect=
null;this.childExpirationTime=this.expirationTime=0;this.alternate=null}function Ge(a){a=a.prototype;return!(!a||!a.isReactComponent)}function Gj(a){if("function"===typeof a)return Ge(a)?1:0;if(void 0!==a&&null!==a){a=a.$$typeof;if(a===zd)return 11;if(a===Ad)return 14}return 2}function Sa(a,b){var c=a.alternate;null===c?(c=la(a.tag,b,a.key,a.mode),c.elementType=a.elementType,c.type=a.type,c.stateNode=a.stateNode,c.alternate=a,a.alternate=c):(c.pendingProps=b,c.effectTag=0,c.nextEffect=null,c.firstEffect=
null,c.lastEffect=null);c.childExpirationTime=a.childExpirationTime;c.expirationTime=a.expirationTime;c.child=a.child;c.memoizedProps=a.memoizedProps;c.memoizedState=a.memoizedState;c.updateQueue=a.updateQueue;b=a.dependencies;c.dependencies=null===b?null:{expirationTime:b.expirationTime,firstContext:b.firstContext,responders:b.responders};c.sibling=a.sibling;c.index=a.index;c.ref=a.ref;return c}function Oc(a,b,c,d,e,f){var g=2;d=a;if("function"===typeof a)Ge(a)&&(g=1);else if("string"===typeof a)g=
5;else a:switch(a){case Ma:return Ha(c.children,e,f,b);case Hj:g=8;e|=7;break;case Af:g=8;e|=1;break;case kc:return a=la(12,c,b,e|8),a.elementType=kc,a.type=kc,a.expirationTime=f,a;case lc:return a=la(13,c,b,e),a.type=lc,a.elementType=lc,a.expirationTime=f,a;case yd:return a=la(19,c,b,e),a.elementType=yd,a.expirationTime=f,a;default:if("object"===typeof a&&null!==a)switch(a.$$typeof){case Cf:g=10;break a;case Bf:g=9;break a;case zd:g=11;break a;case Ad:g=14;break a;case Ef:g=16;d=null;break a;case Df:g=
22;break a}throw Error(k(130,null==a?a:typeof a,""));}b=la(g,c,b,e);b.elementType=a;b.type=d;b.expirationTime=f;return b}function Ha(a,b,c,d){a=la(7,a,d,b);a.expirationTime=c;return a}function qe(a,b,c){a=la(6,a,null,b);a.expirationTime=c;return a}function re(a,b,c){b=la(4,null!==a.children?a.children:[],a.key,b);b.expirationTime=c;b.stateNode={containerInfo:a.containerInfo,pendingChildren:null,implementation:a.implementation};return b}function Ij(a,b,c){this.tag=b;this.current=null;this.containerInfo=
a;this.pingCache=this.pendingChildren=null;this.finishedExpirationTime=0;this.finishedWork=null;this.timeoutHandle=-1;this.pendingContext=this.context=null;this.hydrate=c;this.callbackNode=null;this.callbackPriority=90;this.lastExpiredTime=this.lastPingedTime=this.nextKnownPendingLevel=this.lastSuspendedTime=this.firstSuspendedTime=this.firstPendingTime=0}function Kh(a,b){var c=a.firstSuspendedTime;a=a.lastSuspendedTime;return 0!==c&&c>=b&&a<=b}function Ya(a,b){var c=a.firstSuspendedTime,d=a.lastSuspendedTime;
c<b&&(a.firstSuspendedTime=b);if(d>b||0===c)a.lastSuspendedTime=b;b<=a.lastPingedTime&&(a.lastPingedTime=0);b<=a.lastExpiredTime&&(a.lastExpiredTime=0)}function yh(a,b){b>a.firstPendingTime&&(a.firstPendingTime=b);var c=a.firstSuspendedTime;0!==c&&(b>=c?a.firstSuspendedTime=a.lastSuspendedTime=a.nextKnownPendingLevel=0:b>=a.lastSuspendedTime&&(a.lastSuspendedTime=b+1),b>a.nextKnownPendingLevel&&(a.nextKnownPendingLevel=b))}function Ue(a,b){var c=a.lastExpiredTime;if(0===c||c>b)a.lastExpiredTime=b}
function md(a,b,c,d){var e=b.current,f=ka(),g=Vb.suspense;f=Va(f,e,g);a:if(c){c=c._reactInternalFiber;b:{if(Na(c)!==c||1!==c.tag)throw Error(k(170));var h=c;do{switch(h.tag){case 3:h=h.stateNode.context;break b;case 1:if(N(h.type)){h=h.stateNode.__reactInternalMemoizedMergedChildContext;break b}}h=h.return}while(null!==h);throw Error(k(171));}if(1===c.tag){var m=c.type;if(N(m)){c=Gg(c,m,h);break a}}c=h}else c=Ca;null===b.context?b.context=c:b.pendingContext=c;b=Ea(f,g);b.payload={element:a};d=void 0===
d?null:d;null!==d&&(b.callback=d);Fa(e,b);Ja(e,f);return f}function cf(a){a=a.current;if(!a.child)return null;switch(a.child.tag){case 5:return a.child.stateNode;default:return a.child.stateNode}}function Wh(a,b){a=a.memoizedState;null!==a&&null!==a.dehydrated&&a.retryTime<b&&(a.retryTime=b)}function df(a,b){Wh(a,b);(a=a.alternate)&&Wh(a,b)}function ef(a,b,c){c=null!=c&&!0===c.hydrate;var d=new Ij(a,b,c),e=la(3,null,null,2===b?7:1===b?3:0);d.current=e;e.stateNode=d;ne(e);a[Lb]=d.current;c&&0!==b&&
xi(a,9===a.nodeType?a:a.ownerDocument);this._internalRoot=d}function bc(a){return!(!a||1!==a.nodeType&&9!==a.nodeType&&11!==a.nodeType&&(8!==a.nodeType||" react-mount-point-unstable "!==a.nodeValue))}function Jj(a,b){b||(b=a?9===a.nodeType?a.documentElement:a.firstChild:null,b=!(!b||1!==b.nodeType||!b.hasAttribute("data-reactroot")));if(!b)for(var c;c=a.lastChild;)a.removeChild(c);return new ef(a,0,b?{hydrate:!0}:void 0)}function nd(a,b,c,d,e){var f=c._reactRootContainer;if(f){var g=f._internalRoot;
if("function"===typeof e){var h=e;e=function(){var a=cf(g);h.call(a)}}md(b,g,a,e)}else{f=c._reactRootContainer=Jj(c,d);g=f._internalRoot;if("function"===typeof e){var m=e;e=function(){var a=cf(g);m.call(a)}}Rh(function(){md(b,g,a,e)})}return cf(g)}function Kj(a,b,c){var d=3<arguments.length&&void 0!==arguments[3]?arguments[3]:null;return{$$typeof:gb,key:null==d?null:""+d,children:a,containerInfo:b,implementation:c}}function Xh(a,b){var c=2<arguments.length&&void 0!==arguments[2]?arguments[2]:null;
if(!bc(b))throw Error(k(200));return Kj(a,b,null,c)}if(!ea)throw Error(k(227));var ki=function(a,b,c,d,e,f,g,h,m){var n=Array.prototype.slice.call(arguments,3);try{b.apply(c,n)}catch(C){this.onError(C)}},yb=!1,gc=null,hc=!1,pd=null,li={onError:function(a){yb=!0;gc=a}},td=null,rf=null,mf=null,ic=null,cb={},jc=[],qd={},db={},rd={},wa=!("undefined"===typeof window||"undefined"===typeof window.document||"undefined"===typeof window.document.createElement),M=ea.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.assign,
sd=null,eb=null,fb=null,ee=function(a,b){return a(b)},eg=function(a,b,c,d,e){return a(b,c,d,e)},vd=function(){},vf=ee,Oa=!1,wd=!1,Z=ea.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.Scheduler,Lj=Z.unstable_cancelCallback,ff=Z.unstable_now,$f=Z.unstable_scheduleCallback,Mj=Z.unstable_shouldYield,Yh=Z.unstable_requestPaint,Pd=Z.unstable_runWithPriority,Nj=Z.unstable_getCurrentPriorityLevel,Oj=Z.unstable_ImmediatePriority,Zh=Z.unstable_UserBlockingPriority,ag=Z.unstable_NormalPriority,Pj=Z.unstable_LowPriority,
Qj=Z.unstable_IdlePriority,oi=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,wf=Object.prototype.hasOwnProperty,yf={},xf={},E={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(a){E[a]=
new L(a,0,!1,a,null,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(a){var b=a[0];E[b]=new L(b,1,!1,a[1],null,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(a){E[a]=new L(a,2,!1,a.toLowerCase(),null,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(a){E[a]=new L(a,2,!1,a,null,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(a){E[a]=
new L(a,3,!1,a.toLowerCase(),null,!1)});["checked","multiple","muted","selected"].forEach(function(a){E[a]=new L(a,3,!0,a,null,!1)});["capture","download"].forEach(function(a){E[a]=new L(a,4,!1,a,null,!1)});["cols","rows","size","span"].forEach(function(a){E[a]=new L(a,6,!1,a,null,!1)});["rowSpan","start"].forEach(function(a){E[a]=new L(a,5,!1,a.toLowerCase(),null,!1)});var gf=/[\-:]([a-z])/g,hf=function(a){return a[1].toUpperCase()};"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(a){var b=
a.replace(gf,hf);E[b]=new L(b,1,!1,a,null,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(a){var b=a.replace(gf,hf);E[b]=new L(b,1,!1,a,"http://www.w3.org/1999/xlink",!1)});["xml:base","xml:lang","xml:space"].forEach(function(a){var b=a.replace(gf,hf);E[b]=new L(b,1,!1,a,"http://www.w3.org/XML/1998/namespace",!1)});["tabIndex","crossOrigin"].forEach(function(a){E[a]=new L(a,1,!1,a.toLowerCase(),null,!1)});E.xlinkHref=new L("xlinkHref",1,
!1,"xlink:href","http://www.w3.org/1999/xlink",!0);["src","href","action","formAction"].forEach(function(a){E[a]=new L(a,1,!1,a.toLowerCase(),null,!0)});var da=ea.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;da.hasOwnProperty("ReactCurrentDispatcher")||(da.ReactCurrentDispatcher={current:null});da.hasOwnProperty("ReactCurrentBatchConfig")||(da.ReactCurrentBatchConfig={suspense:null});var si=/^(.*)[\\\/]/,Q="function"===typeof Symbol&&Symbol.for,Pc=Q?Symbol.for("react.element"):60103,gb=Q?Symbol.for("react.portal"):
60106,Ma=Q?Symbol.for("react.fragment"):60107,Af=Q?Symbol.for("react.strict_mode"):60108,kc=Q?Symbol.for("react.profiler"):60114,Cf=Q?Symbol.for("react.provider"):60109,Bf=Q?Symbol.for("react.context"):60110,Hj=Q?Symbol.for("react.concurrent_mode"):60111,zd=Q?Symbol.for("react.forward_ref"):60112,lc=Q?Symbol.for("react.suspense"):60113,yd=Q?Symbol.for("react.suspense_list"):60120,Ad=Q?Symbol.for("react.memo"):60115,Ef=Q?Symbol.for("react.lazy"):60116,Df=Q?Symbol.for("react.block"):60121,zf="function"===
typeof Symbol&&Symbol.iterator,od,xh=function(a){return"undefined"!==typeof MSApp&&MSApp.execUnsafeLocalFunction?function(b,c,d,e){MSApp.execUnsafeLocalFunction(function(){return a(b,c,d,e)})}:a}(function(a,b){if("http://www.w3.org/2000/svg"!==a.namespaceURI||"innerHTML"in a)a.innerHTML=b;else{od=od||document.createElement("div");od.innerHTML="<svg>"+b.valueOf().toString()+"</svg>";for(b=od.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;b.firstChild;)a.appendChild(b.firstChild)}}),Wb=function(a,
b){if(b){var c=a.firstChild;if(c&&c===a.lastChild&&3===c.nodeType){c.nodeValue=b;return}}a.textContent=b},ib={animationend:nc("Animation","AnimationEnd"),animationiteration:nc("Animation","AnimationIteration"),animationstart:nc("Animation","AnimationStart"),transitionend:nc("Transition","TransitionEnd")},Id={},Of={};wa&&(Of=document.createElement("div").style,"AnimationEvent"in window||(delete ib.animationend.animation,delete ib.animationiteration.animation,delete ib.animationstart.animation),"TransitionEvent"in
window||delete ib.transitionend.transition);var $h=oc("animationend"),ai=oc("animationiteration"),bi=oc("animationstart"),ci=oc("transitionend"),Db="abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange seeked seeking stalled suspend timeupdate volumechange waiting".split(" "),Pf=new ("function"===typeof WeakMap?WeakMap:Map),Ab=null,wi=function(a){if(a){var b=a._dispatchListeners,c=a._dispatchInstances;
if(Array.isArray(b))for(var d=0;d<b.length&&!a.isPropagationStopped();d++)lf(a,b[d],c[d]);else b&&lf(a,b,c);a._dispatchListeners=null;a._dispatchInstances=null;a.isPersistent()||a.constructor.release(a)}},qc=[],Rd=!1,fa=[],xa=null,ya=null,za=null,Eb=new Map,Fb=new Map,Jb=[],Nd="mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput close cancel copy cut paste click change contextmenu reset submit".split(" "),
yi="focus blur dragenter dragleave mouseover mouseout pointerover pointerout gotpointercapture lostpointercapture".split(" "),dg={},cg=new Map,Td=new Map,Rj=["abort","abort",$h,"animationEnd",ai,"animationIteration",bi,"animationStart","canplay","canPlay","canplaythrough","canPlayThrough","durationchange","durationChange","emptied","emptied","encrypted","encrypted","ended","ended","error","error","gotpointercapture","gotPointerCapture","load","load","loadeddata","loadedData","loadedmetadata","loadedMetadata",
"loadstart","loadStart","lostpointercapture","lostPointerCapture","playing","playing","progress","progress","seeking","seeking","stalled","stalled","suspend","suspend","timeupdate","timeUpdate",ci,"transitionEnd","waiting","waiting"];Sd("blur blur cancel cancel click click close close contextmenu contextMenu copy copy cut cut auxclick auxClick dblclick doubleClick dragend dragEnd dragstart dragStart drop drop focus focus input input invalid invalid keydown keyDown keypress keyPress keyup keyUp mousedown mouseDown mouseup mouseUp paste paste pause pause play play pointercancel pointerCancel pointerdown pointerDown pointerup pointerUp ratechange rateChange reset reset seeked seeked submit submit touchcancel touchCancel touchend touchEnd touchstart touchStart volumechange volumeChange".split(" "),
0);Sd("drag drag dragenter dragEnter dragexit dragExit dragleave dragLeave dragover dragOver mousemove mouseMove mouseout mouseOut mouseover mouseOver pointermove pointerMove pointerout pointerOut pointerover pointerOver scroll scroll toggle toggle touchmove touchMove wheel wheel".split(" "),1);Sd(Rj,2);(function(a,b){for(var c=0;c<a.length;c++)Td.set(a[c],b)})("change selectionchange textInput compositionstart compositionend compositionupdate".split(" "),0);var Hi=Zh,Gi=Pd,tc=!0,Kb={animationIterationCount:!0,
borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,
strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Sj=["Webkit","ms","Moz","O"];Object.keys(Kb).forEach(function(a){Sj.forEach(function(b){b=b+a.charAt(0).toUpperCase()+a.substring(1);Kb[b]=Kb[a]})});var Ii=M({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}),ng="$",og="/$",$d="$?",Zd="$!",Ze=null,$e=null,We="function"===typeof setTimeout?setTimeout:void 0,vj="function"===
typeof clearTimeout?clearTimeout:void 0,jf=Math.random().toString(36).slice(2),Aa="__reactInternalInstance$"+jf,vc="__reactEventHandlers$"+jf,Lb="__reactContainere$"+jf,Ba=null,ce=null,wc=null;M(R.prototype,{preventDefault:function(){this.defaultPrevented=!0;var a=this.nativeEvent;a&&(a.preventDefault?a.preventDefault():"unknown"!==typeof a.returnValue&&(a.returnValue=!1),this.isDefaultPrevented=xc)},stopPropagation:function(){var a=this.nativeEvent;a&&(a.stopPropagation?a.stopPropagation():"unknown"!==
typeof a.cancelBubble&&(a.cancelBubble=!0),this.isPropagationStopped=xc)},persist:function(){this.isPersistent=xc},isPersistent:yc,destructor:function(){var a=this.constructor.Interface,b;for(b in a)this[b]=null;this.nativeEvent=this._targetInst=this.dispatchConfig=null;this.isPropagationStopped=this.isDefaultPrevented=yc;this._dispatchInstances=this._dispatchListeners=null}});R.Interface={type:null,target:null,currentTarget:function(){return null},eventPhase:null,bubbles:null,cancelable:null,timeStamp:function(a){return a.timeStamp||
Date.now()},defaultPrevented:null,isTrusted:null};R.extend=function(a){function b(){return c.apply(this,arguments)}var c=this,d=function(){};d.prototype=c.prototype;d=new d;M(d,b.prototype);b.prototype=d;b.prototype.constructor=b;b.Interface=M({},c.Interface,a);b.extend=c.extend;sg(b);return b};sg(R);var Tj=R.extend({data:null}),Uj=R.extend({data:null}),Ni=[9,13,27,32],de=wa&&"CompositionEvent"in window,cc=null;wa&&"documentMode"in document&&(cc=document.documentMode);var Vj=wa&&"TextEvent"in window&&
!cc,xg=wa&&(!de||cc&&8<cc&&11>=cc),wg=String.fromCharCode(32),ua={beforeInput:{phasedRegistrationNames:{bubbled:"onBeforeInput",captured:"onBeforeInputCapture"},dependencies:["compositionend","keypress","textInput","paste"]},compositionEnd:{phasedRegistrationNames:{bubbled:"onCompositionEnd",captured:"onCompositionEndCapture"},dependencies:"blur compositionend keydown keypress keyup mousedown".split(" ")},compositionStart:{phasedRegistrationNames:{bubbled:"onCompositionStart",captured:"onCompositionStartCapture"},
dependencies:"blur compositionstart keydown keypress keyup mousedown".split(" ")},compositionUpdate:{phasedRegistrationNames:{bubbled:"onCompositionUpdate",captured:"onCompositionUpdateCapture"},dependencies:"blur compositionupdate keydown keypress keyup mousedown".split(" ")}},vg=!1,mb=!1,Wj={eventTypes:ua,extractEvents:function(a,b,c,d,e){var f;if(de)b:{switch(a){case "compositionstart":var g=ua.compositionStart;break b;case "compositionend":g=ua.compositionEnd;break b;case "compositionupdate":g=
ua.compositionUpdate;break b}g=void 0}else mb?tg(a,c)&&(g=ua.compositionEnd):"keydown"===a&&229===c.keyCode&&(g=ua.compositionStart);g?(xg&&"ko"!==c.locale&&(mb||g!==ua.compositionStart?g===ua.compositionEnd&&mb&&(f=rg()):(Ba=d,ce="value"in Ba?Ba.value:Ba.textContent,mb=!0)),e=Tj.getPooled(g,b,c,d),f?e.data=f:(f=ug(c),null!==f&&(e.data=f)),lb(e),f=e):f=null;(a=Vj?Oi(a,c):Pi(a,c))?(b=Uj.getPooled(ua.beforeInput,b,c,d),b.data=a,lb(b)):b=null;return null===f?b:null===b?f:[f,b]}},Qi={color:!0,date:!0,
datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0},Ag={change:{phasedRegistrationNames:{bubbled:"onChange",captured:"onChangeCapture"},dependencies:"blur change click focus input keydown keyup selectionchange".split(" ")}},Mb=null,Nb=null,kf=!1;wa&&(kf=Tf("input")&&(!document.documentMode||9<document.documentMode));var Xj={eventTypes:Ag,_isInputEventSupported:kf,extractEvents:function(a,b,c,d,e){e=b?Pa(b):window;var f=
e.nodeName&&e.nodeName.toLowerCase();if("select"===f||"input"===f&&"file"===e.type)var g=Si;else if(yg(e))if(kf)g=Wi;else{g=Ui;var h=Ti}else(f=e.nodeName)&&"input"===f.toLowerCase()&&("checkbox"===e.type||"radio"===e.type)&&(g=Vi);if(g&&(g=g(a,b)))return zg(g,c,d);h&&h(a,e,b);"blur"===a&&(a=e._wrapperState)&&a.controlled&&"number"===e.type&&Ed(e,"number",e.value)}},dc=R.extend({view:null,detail:null}),Yi={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"},di=0,ei=0,fi=!1,gi=!1,ec=dc.extend({screenX:null,
screenY:null,clientX:null,clientY:null,pageX:null,pageY:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,getModifierState:fe,button:null,buttons:null,relatedTarget:function(a){return a.relatedTarget||(a.fromElement===a.srcElement?a.toElement:a.fromElement)},movementX:function(a){if("movementX"in a)return a.movementX;var b=di;di=a.screenX;return fi?"mousemove"===a.type?a.screenX-b:0:(fi=!0,0)},movementY:function(a){if("movementY"in a)return a.movementY;var b=ei;ei=a.screenY;return gi?"mousemove"===
a.type?a.screenY-b:0:(gi=!0,0)}}),hi=ec.extend({pointerId:null,width:null,height:null,pressure:null,tangentialPressure:null,tiltX:null,tiltY:null,twist:null,pointerType:null,isPrimary:null}),fc={mouseEnter:{registrationName:"onMouseEnter",dependencies:["mouseout","mouseover"]},mouseLeave:{registrationName:"onMouseLeave",dependencies:["mouseout","mouseover"]},pointerEnter:{registrationName:"onPointerEnter",dependencies:["pointerout","pointerover"]},pointerLeave:{registrationName:"onPointerLeave",dependencies:["pointerout",
"pointerover"]}},Yj={eventTypes:fc,extractEvents:function(a,b,c,d,e){var f="mouseover"===a||"pointerover"===a,g="mouseout"===a||"pointerout"===a;if(f&&0===(e&32)&&(c.relatedTarget||c.fromElement)||!g&&!f)return null;f=d.window===d?d:(f=d.ownerDocument)?f.defaultView||f.parentWindow:window;if(g){if(g=b,b=(b=c.relatedTarget||c.toElement)?Bb(b):null,null!==b){var h=Na(b);if(b!==h||5!==b.tag&&6!==b.tag)b=null}}else g=null;if(g===b)return null;if("mouseout"===a||"mouseover"===a){var m=ec;var n=fc.mouseLeave;
var l=fc.mouseEnter;var k="mouse"}else if("pointerout"===a||"pointerover"===a)m=hi,n=fc.pointerLeave,l=fc.pointerEnter,k="pointer";a=null==g?f:Pa(g);f=null==b?f:Pa(b);n=m.getPooled(n,g,c,d);n.type=k+"leave";n.target=a;n.relatedTarget=f;c=m.getPooled(l,b,c,d);c.type=k+"enter";c.target=f;c.relatedTarget=a;d=g;k=b;if(d&&k)a:{m=d;l=k;g=0;for(a=m;a;a=pa(a))g++;a=0;for(b=l;b;b=pa(b))a++;for(;0<g-a;)m=pa(m),g--;for(;0<a-g;)l=pa(l),a--;for(;g--;){if(m===l||m===l.alternate)break a;m=pa(m);l=pa(l)}m=null}else m=
null;l=m;for(m=[];d&&d!==l;){g=d.alternate;if(null!==g&&g===l)break;m.push(d);d=pa(d)}for(d=[];k&&k!==l;){g=k.alternate;if(null!==g&&g===l)break;d.push(k);k=pa(k)}for(k=0;k<m.length;k++)be(m[k],"bubbled",n);for(k=d.length;0<k--;)be(d[k],"captured",c);return 0===(e&64)?[n]:[n,c]}},Qa="function"===typeof Object.is?Object.is:Zi,$i=Object.prototype.hasOwnProperty,Zj=wa&&"documentMode"in document&&11>=document.documentMode,Eg={select:{phasedRegistrationNames:{bubbled:"onSelect",captured:"onSelectCapture"},
dependencies:"blur contextmenu dragend focus keydown keyup mousedown mouseup selectionchange".split(" ")}},nb=null,he=null,Pb=null,ge=!1,ak={eventTypes:Eg,extractEvents:function(a,b,c,d,e,f){e=f||(d.window===d?d.document:9===d.nodeType?d:d.ownerDocument);if(!(f=!e)){a:{e=Jd(e);f=rd.onSelect;for(var g=0;g<f.length;g++)if(!e.has(f[g])){e=!1;break a}e=!0}f=!e}if(f)return null;e=b?Pa(b):window;switch(a){case "focus":if(yg(e)||"true"===e.contentEditable)nb=e,he=b,Pb=null;break;case "blur":Pb=he=nb=null;
break;case "mousedown":ge=!0;break;case "contextmenu":case "mouseup":case "dragend":return ge=!1,Dg(c,d);case "selectionchange":if(Zj)break;case "keydown":case "keyup":return Dg(c,d)}return null}},bk=R.extend({animationName:null,elapsedTime:null,pseudoElement:null}),ck=R.extend({clipboardData:function(a){return"clipboardData"in a?a.clipboardData:window.clipboardData}}),dk=dc.extend({relatedTarget:null}),ek={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",
Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},fk={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",
224:"Meta"},gk=dc.extend({key:function(a){if(a.key){var b=ek[a.key]||a.key;if("Unidentified"!==b)return b}return"keypress"===a.type?(a=Ac(a),13===a?"Enter":String.fromCharCode(a)):"keydown"===a.type||"keyup"===a.type?fk[a.keyCode]||"Unidentified":""},location:null,ctrlKey:null,shiftKey:null,altKey:null,metaKey:null,repeat:null,locale:null,getModifierState:fe,charCode:function(a){return"keypress"===a.type?Ac(a):0},keyCode:function(a){return"keydown"===a.type||"keyup"===a.type?a.keyCode:0},which:function(a){return"keypress"===
a.type?Ac(a):"keydown"===a.type||"keyup"===a.type?a.keyCode:0}}),hk=ec.extend({dataTransfer:null}),ik=dc.extend({touches:null,targetTouches:null,changedTouches:null,altKey:null,metaKey:null,ctrlKey:null,shiftKey:null,getModifierState:fe}),jk=R.extend({propertyName:null,elapsedTime:null,pseudoElement:null}),kk=ec.extend({deltaX:function(a){return"deltaX"in a?a.deltaX:"wheelDeltaX"in a?-a.wheelDeltaX:0},deltaY:function(a){return"deltaY"in a?a.deltaY:"wheelDeltaY"in a?-a.wheelDeltaY:"wheelDelta"in a?
-a.wheelDelta:0},deltaZ:null,deltaMode:null}),lk={eventTypes:dg,extractEvents:function(a,b,c,d,e){e=cg.get(a);if(!e)return null;switch(a){case "keypress":if(0===Ac(c))return null;case "keydown":case "keyup":a=gk;break;case "blur":case "focus":a=dk;break;case "click":if(2===c.button)return null;case "auxclick":case "dblclick":case "mousedown":case "mousemove":case "mouseup":case "mouseout":case "mouseover":case "contextmenu":a=ec;break;case "drag":case "dragend":case "dragenter":case "dragexit":case "dragleave":case "dragover":case "dragstart":case "drop":a=
hk;break;case "touchcancel":case "touchend":case "touchmove":case "touchstart":a=ik;break;case $h:case ai:case bi:a=bk;break;case ci:a=jk;break;case "scroll":a=dc;break;case "wheel":a=kk;break;case "copy":case "cut":case "paste":a=ck;break;case "gotpointercapture":case "lostpointercapture":case "pointercancel":case "pointerdown":case "pointermove":case "pointerout":case "pointerover":case "pointerup":a=hi;break;default:a=R}b=a.getPooled(e,b,c,d);lb(b);return b}};(function(a){if(ic)throw Error(k(101));
ic=Array.prototype.slice.call(a);nf()})("ResponderEventPlugin SimpleEventPlugin EnterLeaveEventPlugin ChangeEventPlugin SelectEventPlugin BeforeInputEventPlugin".split(" "));(function(a,b,c){td=a;rf=b;mf=c})(ae,Hb,Pa);pf({SimpleEventPlugin:lk,EnterLeaveEventPlugin:Yj,ChangeEventPlugin:Xj,SelectEventPlugin:ak,BeforeInputEventPlugin:Wj});var ie=[],ob=-1,Ca={},B={current:Ca},G={current:!1},Ra=Ca,bj=Pd,je=$f,Rg=Lj,aj=Nj,Dc=Oj,Ig=Zh,Jg=ag,Kg=Pj,Lg=Qj,Qg={},yj=Mj,Cj=void 0!==Yh?Yh:function(){},qa=null,
Ec=null,ke=!1,ii=ff(),Y=1E4>ii?ff:function(){return ff()-ii},Ic={current:null},Hc=null,qb=null,Gc=null,Tg=0,Jc=2,Ga=!1,Vb=da.ReactCurrentBatchConfig,$g=(new ea.Component).refs,Mc={isMounted:function(a){return(a=a._reactInternalFiber)?Na(a)===a:!1},enqueueSetState:function(a,b,c){a=a._reactInternalFiber;var d=ka(),e=Vb.suspense;d=Va(d,a,e);e=Ea(d,e);e.payload=b;void 0!==c&&null!==c&&(e.callback=c);Fa(a,e);Ja(a,d)},enqueueReplaceState:function(a,b,c){a=a._reactInternalFiber;var d=ka(),e=Vb.suspense;
d=Va(d,a,e);e=Ea(d,e);e.tag=1;e.payload=b;void 0!==c&&null!==c&&(e.callback=c);Fa(a,e);Ja(a,d)},enqueueForceUpdate:function(a,b){a=a._reactInternalFiber;var c=ka(),d=Vb.suspense;c=Va(c,a,d);d=Ea(c,d);d.tag=Jc;void 0!==b&&null!==b&&(d.callback=b);Fa(a,d);Ja(a,c)}},Qc=Array.isArray,wb=ah(!0),Fe=ah(!1),Sb={},ja={current:Sb},Ub={current:Sb},Tb={current:Sb},D={current:0},Sc=da.ReactCurrentDispatcher,X=da.ReactCurrentBatchConfig,Ia=0,z=null,K=null,J=null,Uc=!1,Tc={readContext:W,useCallback:S,useContext:S,
useEffect:S,useImperativeHandle:S,useLayoutEffect:S,useMemo:S,useReducer:S,useRef:S,useState:S,useDebugValue:S,useResponder:S,useDeferredValue:S,useTransition:S},dj={readContext:W,useCallback:ih,useContext:W,useEffect:eh,useImperativeHandle:function(a,b,c){c=null!==c&&void 0!==c?c.concat([a]):null;return ze(4,2,gh.bind(null,b,a),c)},useLayoutEffect:function(a,b){return ze(4,2,a,b)},useMemo:function(a,b){var c=ub();b=void 0===b?null:b;a=a();c.memoizedState=[a,b];return a},useReducer:function(a,b,c){var d=
ub();b=void 0!==c?c(b):b;d.memoizedState=d.baseState=b;a=d.queue={pending:null,dispatch:null,lastRenderedReducer:a,lastRenderedState:b};a=a.dispatch=ch.bind(null,z,a);return[d.memoizedState,a]},useRef:function(a){var b=ub();a={current:a};return b.memoizedState=a},useState:xe,useDebugValue:Be,useResponder:ue,useDeferredValue:function(a,b){var c=xe(a),d=c[0],e=c[1];eh(function(){var c=X.suspense;X.suspense=void 0===b?null:b;try{e(a)}finally{X.suspense=c}},[a,b]);return d},useTransition:function(a){var b=
xe(!1),c=b[0];b=b[1];return[ih(Ce.bind(null,b,a),[b,a]),c]}},ej={readContext:W,useCallback:Yc,useContext:W,useEffect:Xc,useImperativeHandle:hh,useLayoutEffect:fh,useMemo:jh,useReducer:Vc,useRef:dh,useState:function(a){return Vc(Ua)},useDebugValue:Be,useResponder:ue,useDeferredValue:function(a,b){var c=Vc(Ua),d=c[0],e=c[1];Xc(function(){var c=X.suspense;X.suspense=void 0===b?null:b;try{e(a)}finally{X.suspense=c}},[a,b]);return d},useTransition:function(a){var b=Vc(Ua),c=b[0];b=b[1];return[Yc(Ce.bind(null,
b,a),[b,a]),c]}},fj={readContext:W,useCallback:Yc,useContext:W,useEffect:Xc,useImperativeHandle:hh,useLayoutEffect:fh,useMemo:jh,useReducer:Wc,useRef:dh,useState:function(a){return Wc(Ua)},useDebugValue:Be,useResponder:ue,useDeferredValue:function(a,b){var c=Wc(Ua),d=c[0],e=c[1];Xc(function(){var c=X.suspense;X.suspense=void 0===b?null:b;try{e(a)}finally{X.suspense=c}},[a,b]);return d},useTransition:function(a){var b=Wc(Ua),c=b[0];b=b[1];return[Yc(Ce.bind(null,b,a),[b,a]),c]}},ra=null,Ka=null,Wa=
!1,gj=da.ReactCurrentOwner,ia=!1,Je={dehydrated:null,retryTime:0};var jj=function(a,b,c,d){for(c=b.child;null!==c;){if(5===c.tag||6===c.tag)a.appendChild(c.stateNode);else if(4!==c.tag&&null!==c.child){c.child.return=c;c=c.child;continue}if(c===b)break;for(;null===c.sibling;){if(null===c.return||c.return===b)return;c=c.return}c.sibling.return=c.return;c=c.sibling}};var wh=function(a){};var ij=function(a,b,c,d,e){var f=a.memoizedProps;if(f!==d){var g=b.stateNode;Ta(ja.current);a=null;switch(c){case "input":f=
Cd(g,f);d=Cd(g,d);a=[];break;case "option":f=Fd(g,f);d=Fd(g,d);a=[];break;case "select":f=M({},f,{value:void 0});d=M({},d,{value:void 0});a=[];break;case "textarea":f=Gd(g,f);d=Gd(g,d);a=[];break;default:"function"!==typeof f.onClick&&"function"===typeof d.onClick&&(g.onclick=uc)}Ud(c,d);var h,m;c=null;for(h in f)if(!d.hasOwnProperty(h)&&f.hasOwnProperty(h)&&null!=f[h])if("style"===h)for(m in g=f[h],g)g.hasOwnProperty(m)&&(c||(c={}),c[m]="");else"dangerouslySetInnerHTML"!==h&&"children"!==h&&"suppressContentEditableWarning"!==
h&&"suppressHydrationWarning"!==h&&"autoFocus"!==h&&(db.hasOwnProperty(h)?a||(a=[]):(a=a||[]).push(h,null));for(h in d){var k=d[h];g=null!=f?f[h]:void 0;if(d.hasOwnProperty(h)&&k!==g&&(null!=k||null!=g))if("style"===h)if(g){for(m in g)!g.hasOwnProperty(m)||k&&k.hasOwnProperty(m)||(c||(c={}),c[m]="");for(m in k)k.hasOwnProperty(m)&&g[m]!==k[m]&&(c||(c={}),c[m]=k[m])}else c||(a||(a=[]),a.push(h,c)),c=k;else"dangerouslySetInnerHTML"===h?(k=k?k.__html:void 0,g=g?g.__html:void 0,null!=k&&g!==k&&(a=a||
[]).push(h,k)):"children"===h?g===k||"string"!==typeof k&&"number"!==typeof k||(a=a||[]).push(h,""+k):"suppressContentEditableWarning"!==h&&"suppressHydrationWarning"!==h&&(db.hasOwnProperty(h)?(null!=k&&oa(e,h),a||g===k||(a=[])):(a=a||[]).push(h,k))}c&&(a=a||[]).push("style",c);e=a;if(b.updateQueue=e)b.effectTag|=4}};var kj=function(a,b,c,d){c!==d&&(b.effectTag|=4)};var pj="function"===typeof WeakSet?WeakSet:Set,wj="function"===typeof WeakMap?WeakMap:Map,sj=Math.ceil,gd=da.ReactCurrentDispatcher,
Uh=da.ReactCurrentOwner,H=0,Ye=8,ca=16,ma=32,Xa=0,hd=1,Oh=2,ad=3,bd=4,Xe=5,p=H,U=null,t=null,P=0,F=Xa,id=null,ta=1073741823,Yb=1073741823,kd=null,Xb=0,jd=!1,Re=0,Ph=500,l=null,cd=!1,Se=null,La=null,ld=!1,Zb=null,$b=90,bb=null,ac=0,af=null,dd=0,Ja=function(a,b){if(50<ac)throw ac=0,af=null,Error(k(185));a=ed(a,b);if(null!==a){var c=Cc();1073741823===b?(p&Ye)!==H&&(p&(ca|ma))===H?Te(a):(V(a),p===H&&ha()):V(a);(p&4)===H||98!==c&&99!==c||(null===bb?bb=new Map([[a,b]]):(c=bb.get(a),(void 0===c||c>b)&&bb.set(a,
b)))}};var zj=function(a,b,c){var d=b.expirationTime;if(null!==a){var e=b.pendingProps;if(a.memoizedProps!==e||G.current)ia=!0;else{if(d<c){ia=!1;switch(b.tag){case 3:sh(b);Ee();break;case 5:bh(b);if(b.mode&4&&1!==c&&e.hidden)return b.expirationTime=b.childExpirationTime=1,null;break;case 1:N(b.type)&&Bc(b);break;case 4:se(b,b.stateNode.containerInfo);break;case 10:d=b.memoizedProps.value;e=b.type._context;y(Ic,e._currentValue);e._currentValue=d;break;case 13:if(null!==b.memoizedState){d=b.child.childExpirationTime;
if(0!==d&&d>=c)return th(a,b,c);y(D,D.current&1);b=sa(a,b,c);return null!==b?b.sibling:null}y(D,D.current&1);break;case 19:d=b.childExpirationTime>=c;if(0!==(a.effectTag&64)){if(d)return vh(a,b,c);b.effectTag|=64}e=b.memoizedState;null!==e&&(e.rendering=null,e.tail=null);y(D,D.current);if(!d)return null}return sa(a,b,c)}ia=!1}}else ia=!1;b.expirationTime=0;switch(b.tag){case 2:d=b.type;null!==a&&(a.alternate=null,b.alternate=null,b.effectTag|=2);a=b.pendingProps;e=pb(b,B.current);rb(b,c);e=we(null,
b,d,a,e,c);b.effectTag|=1;if("object"===typeof e&&null!==e&&"function"===typeof e.render&&void 0===e.$$typeof){b.tag=1;b.memoizedState=null;b.updateQueue=null;if(N(d)){var f=!0;Bc(b)}else f=!1;b.memoizedState=null!==e.state&&void 0!==e.state?e.state:null;ne(b);var g=d.getDerivedStateFromProps;"function"===typeof g&&Lc(b,d,g,a);e.updater=Mc;b.stateNode=e;e._reactInternalFiber=b;pe(b,d,a,c);b=Ie(null,b,d,!0,f,c)}else b.tag=0,T(null,b,e,c),b=b.child;return b;case 16:a:{e=b.elementType;null!==a&&(a.alternate=
null,b.alternate=null,b.effectTag|=2);a=b.pendingProps;ri(e);if(1!==e._status)throw e._result;e=e._result;b.type=e;f=b.tag=Gj(e);a=aa(e,a);switch(f){case 0:b=He(null,b,e,a,c);break a;case 1:b=rh(null,b,e,a,c);break a;case 11:b=nh(null,b,e,a,c);break a;case 14:b=oh(null,b,e,aa(e.type,a),d,c);break a}throw Error(k(306,e,""));}return b;case 0:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:aa(d,e),He(a,b,d,e,c);case 1:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:aa(d,e),rh(a,b,d,e,c);
case 3:sh(b);d=b.updateQueue;if(null===a||null===d)throw Error(k(282));d=b.pendingProps;e=b.memoizedState;e=null!==e?e.element:null;oe(a,b);Qb(b,d,null,c);d=b.memoizedState.element;if(d===e)Ee(),b=sa(a,b,c);else{if(e=b.stateNode.hydrate)Ka=kb(b.stateNode.containerInfo.firstChild),ra=b,e=Wa=!0;if(e)for(c=Fe(b,null,d,c),b.child=c;c;)c.effectTag=c.effectTag&-3|1024,c=c.sibling;else T(a,b,d,c),Ee();b=b.child}return b;case 5:return bh(b),null===a&&De(b),d=b.type,e=b.pendingProps,f=null!==a?a.memoizedProps:
null,g=e.children,Yd(d,e)?g=null:null!==f&&Yd(d,f)&&(b.effectTag|=16),qh(a,b),b.mode&4&&1!==c&&e.hidden?(b.expirationTime=b.childExpirationTime=1,b=null):(T(a,b,g,c),b=b.child),b;case 6:return null===a&&De(b),null;case 13:return th(a,b,c);case 4:return se(b,b.stateNode.containerInfo),d=b.pendingProps,null===a?b.child=wb(b,null,d,c):T(a,b,d,c),b.child;case 11:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:aa(d,e),nh(a,b,d,e,c);case 7:return T(a,b,b.pendingProps,c),b.child;case 8:return T(a,
b,b.pendingProps.children,c),b.child;case 12:return T(a,b,b.pendingProps.children,c),b.child;case 10:a:{d=b.type._context;e=b.pendingProps;g=b.memoizedProps;f=e.value;var h=b.type._context;y(Ic,h._currentValue);h._currentValue=f;if(null!==g)if(h=g.value,f=Qa(h,f)?0:("function"===typeof d._calculateChangedBits?d._calculateChangedBits(h,f):1073741823)|0,0===f){if(g.children===e.children&&!G.current){b=sa(a,b,c);break a}}else for(h=b.child,null!==h&&(h.return=b);null!==h;){var m=h.dependencies;if(null!==
m){g=h.child;for(var l=m.firstContext;null!==l;){if(l.context===d&&0!==(l.observedBits&f)){1===h.tag&&(l=Ea(c,null),l.tag=Jc,Fa(h,l));h.expirationTime<c&&(h.expirationTime=c);l=h.alternate;null!==l&&l.expirationTime<c&&(l.expirationTime=c);Sg(h.return,c);m.expirationTime<c&&(m.expirationTime=c);break}l=l.next}}else g=10===h.tag?h.type===b.type?null:h.child:h.child;if(null!==g)g.return=h;else for(g=h;null!==g;){if(g===b){g=null;break}h=g.sibling;if(null!==h){h.return=g.return;g=h;break}g=g.return}h=
g}T(a,b,e.children,c);b=b.child}return b;case 9:return e=b.type,f=b.pendingProps,d=f.children,rb(b,c),e=W(e,f.unstable_observedBits),d=d(e),b.effectTag|=1,T(a,b,d,c),b.child;case 14:return e=b.type,f=aa(e,b.pendingProps),f=aa(e.type,f),oh(a,b,e,f,d,c);case 15:return ph(a,b,b.type,b.pendingProps,d,c);case 17:return d=b.type,e=b.pendingProps,e=b.elementType===d?e:aa(d,e),null!==a&&(a.alternate=null,b.alternate=null,b.effectTag|=2),b.tag=1,N(d)?(a=!0,Bc(b)):a=!1,rb(b,c),Yg(b,d,e),pe(b,d,e,c),Ie(null,
b,d,!0,a,c);case 19:return vh(a,b,c)}throw Error(k(156,b.tag));};var bf=null,Ne=null,la=function(a,b,c,d){return new Fj(a,b,c,d)};ef.prototype.render=function(a){md(a,this._internalRoot,null,null)};ef.prototype.unmount=function(){var a=this._internalRoot,b=a.containerInfo;md(null,a,null,function(){b[Lb]=null})};var Di=function(a){if(13===a.tag){var b=Fc(ka(),150,100);Ja(a,b);df(a,b)}};var Yf=function(a){13===a.tag&&(Ja(a,3),df(a,3))};var Bi=function(a){if(13===a.tag){var b=ka();b=Va(b,a,null);Ja(a,
b);df(a,b)}};sd=function(a,b,c){switch(b){case "input":Dd(a,c);b=c.name;if("radio"===c.type&&null!=b){for(c=a;c.parentNode;)c=c.parentNode;c=c.querySelectorAll("input[name="+JSON.stringify(""+b)+'][type="radio"]');for(b=0;b<c.length;b++){var d=c[b];if(d!==a&&d.form===a.form){var e=ae(d);if(!e)throw Error(k(90));Gf(d);Dd(d,e)}}}break;case "textarea":Lf(a,c);break;case "select":b=c.value,null!=b&&hb(a,!!c.multiple,b,!1)}};(function(a,b,c,d){ee=a;eg=b;vd=c;vf=d})(Qh,function(a,b,c,d,e){var f=p;p|=4;
try{return Da(98,a.bind(null,b,c,d,e))}finally{p=f,p===H&&ha()}},function(){(p&(1|ca|ma))===H&&(uj(),xb())},function(a,b){var c=p;p|=2;try{return a(b)}finally{p=c,p===H&&ha()}});var mk={Events:[Hb,Pa,ae,pf,qd,lb,function(a){Kd(a,Ki)},sf,tf,sc,pc,xb,{current:!1}]};(function(a){var b=a.findFiberByHostInstance;return Ej(M({},a,{overrideHookState:null,overrideProps:null,setSuspenseHandler:null,scheduleUpdate:null,currentDispatcherRef:da.ReactCurrentDispatcher,findHostInstanceByFiber:function(a){a=Sf(a);
return null===a?null:a.stateNode},findFiberByHostInstance:function(a){return b?b(a):null},findHostInstancesForRefresh:null,scheduleRefresh:null,scheduleRoot:null,setRefreshHandler:null,getCurrentFiber:null}))})({findFiberByHostInstance:Bb,bundleType:0,version:"16.13.1",rendererPackageName:"react-dom"});I.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=mk;I.createPortal=Xh;I.findDOMNode=function(a){if(null==a)return null;if(1===a.nodeType)return a;var b=a._reactInternalFiber;if(void 0===
b){if("function"===typeof a.render)throw Error(k(188));throw Error(k(268,Object.keys(a)));}a=Sf(b);a=null===a?null:a.stateNode;return a};I.flushSync=function(a,b){if((p&(ca|ma))!==H)throw Error(k(187));var c=p;p|=1;try{return Da(99,a.bind(null,b))}finally{p=c,ha()}};I.hydrate=function(a,b,c){if(!bc(b))throw Error(k(200));return nd(null,a,b,!0,c)};I.render=function(a,b,c){if(!bc(b))throw Error(k(200));return nd(null,a,b,!1,c)};I.unmountComponentAtNode=function(a){if(!bc(a))throw Error(k(40));return a._reactRootContainer?
(Rh(function(){nd(null,null,a,!1,function(){a._reactRootContainer=null;a[Lb]=null})}),!0):!1};I.unstable_batchedUpdates=Qh;I.unstable_createPortal=function(a,b){return Xh(a,b,2<arguments.length&&void 0!==arguments[2]?arguments[2]:null)};I.unstable_renderSubtreeIntoContainer=function(a,b,c,d){if(!bc(c))throw Error(k(200));if(null==a||void 0===a._reactInternalFiber)throw Error(k(38));return nd(a,b,c,!1,d)};I.version="16.13.1"});
</script>
<script>const e = React.createElement;
function pathToString(path) {
if (path[0] === '/') {
return '/' + path.slice(1).join('/');
} else {
return path.join('/');
}
}
function findCommonPath(files) {
if (!files || !files.length) {
return [];
}
function isPrefix(arr, prefix) {
if (arr.length < prefix.length) {
return false;
}
for (let i = prefix.length - 1; i >= 0; --i) {
if (arr[i] !== prefix[i]) {
return false;
}
}
return true;
}
let commonPath = files[0].path.slice(0, -1);
while (commonPath.length) {
if (files.every(file => isPrefix(file.path, commonPath))) {
break;
}
commonPath.pop();
}
return commonPath;
}
function findFolders(files) {
if (!files || !files.length) {
return [];
}
let folders = files.filter(file => file.path.length > 1).map(file => file.path[0]);
folders = [...new Set(folders)]; // unique
folders.sort();
folders = folders.map(folder => {
let filesInFolder = files
.filter(file => file.path[0] === folder)
.map(file => ({
...file,
path: file.path.slice(1),
parent: [...file.parent, file.path[0]],
}));
const children = findFolders(filesInFolder); // recursion
return {
is_folder: true,
path: [folder],
parent: files[0].parent,
children,
covered: children.reduce((sum, file) => sum + file.covered, 0),
coverable: children.reduce((sum, file) => sum + file.coverable, 0),
prevRun: {
covered: children.reduce((sum, file) => sum + file.prevRun.covered, 0),
coverable: children.reduce((sum, file) => sum + file.prevRun.coverable, 0),
}
};
});
return [
...folders,
...files.filter(file => file.path.length === 1),
];
}
class App extends React.Component {
constructor(...args) {
super(...args);
this.state = {
current: [],
};
}
componentDidMount() {
this.updateStateFromLocation();
window.addEventListener("hashchange", () => this.updateStateFromLocation(), false);
}
updateStateFromLocation() {
if (window.location.hash.length > 1) {
const current = window.location.hash.substr(1).split('/');
this.setState({current});
} else {
this.setState({current: []});
}
}
getCurrentPath() {
let file = this.props.root;
let path = [file];
for (let p of this.state.current) {
file = file.children.find(file => file.path[0] === p);
if (!file) {
return path;
}
path.push(file);
}
return path;
}
render() {
const path = this.getCurrentPath();
const file = path[path.length - 1];
let w = null;
if (file.is_folder) {
w = e(FilesList, {
folder: file,
onSelectFile: this.selectFile.bind(this),
onBack: path.length > 1 ? this.back.bind(this) : null,
});
} else {
w = e(DisplayFile, {
file,
onBack: this.back.bind(this),
});
}
return e('div', {className: 'app'}, w);
}
selectFile(file) {
this.setState(({current}) => {
return {current: [...current, file.path[0]]};
}, () => this.updateHash());
}
back(file) {
this.setState(({current}) => {
return {current: current.slice(0, current.length - 1)};
}, () => this.updateHash());
}
updateHash() {
if (!this.state.current || !this.state.current.length) {
window.location = '#';
} else {
window.location = '#' + this.state.current.join('/');
}
}
}
function FilesList({folder, onSelectFile, onBack}) {
let files = folder.children;
return e('div', {className: 'display-folder'},
e(FileHeader, {file: folder, onBack}),
e('table', {className: 'files-list'},
e('thead', {className: 'files-list__head'},
e('tr', null,
e('th', null, "Path"),
e('th', null, "Coverage")
)
),
e('tbody', {className: 'files-list__body'},
files.map(file => e(File, {file, onClick: onSelectFile}))
)
)
);
}
function File({file, onClick}) {
const coverage = file.coverable ? file.covered / file.coverable * 100 : -1;
const coverageDelta = file.prevRun &&
(file.covered / file.coverable * 100 - file.prevRun.covered / file.prevRun.coverable * 100);
return e('tr', {
className: 'files-list__file'
+ (coverage >= 0 && coverage < 50 ? ' files-list__file_low': '')
+ (coverage >= 50 && coverage < 80 ? ' files-list__file_medium': '')
+ (coverage >= 80 ? ' files-list__file_high': '')
+ (file.is_folder ? ' files-list__file_folder': ''),
onClick: () => onClick(file),
},
e('td', null, e('a', null, pathToString(file.path))),
e('td', null,
file.covered + ' / ' + file.coverable +
(coverage >= 0 ? ' (' + coverage.toFixed(2) + '%)' : ''),
e('span', {title: 'Change from the previous run'},
(coverageDelta ? ` (${coverageDelta > 0 ? '+' : ''}${coverageDelta.toFixed(2)}%)` : ''))
)
);
}
function DisplayFile({file, onBack}) {
return e('div', {className: 'display-file'},
e(FileHeader, {file, onBack}),
e(FileContent, {file})
);
}
function FileHeader({file, onBack}) {
const coverage = file.covered / file.coverable * 100;
const coverageDelta = file.prevRun && (coverage - file.prevRun.covered / file.prevRun.coverable * 100);
return e('div', {className: 'file-header'},
onBack ? e('a', {className: 'file-header__back', onClick: onBack}, 'Back') : null,
e('div', {className: 'file-header__name'}, pathToString([...file.parent, ...file.path])),
e('div', {className: 'file-header__stat'},
'Covered: ' + file.covered + ' of ' + file.coverable +
(file.coverable ? ' (' + coverage.toFixed(2) + '%)' : ''),
e('span', {title: 'Change from the previous run'},
(coverageDelta ? ` (${coverageDelta > 0 ? '+' : ''}${coverageDelta.toFixed(2)}%)` : ''))
)
);
}
function FileContent({file}) {
return e('div', {className: 'file-content'},
file.content.split(/\r?\n/).map((line, index) => {
const trace = file.traces.find(trace => trace.line === index + 1);
const covered = trace && trace.stats.Line;
const uncovered = trace && !trace.stats.Line;
return e('pre', {
className: 'code-line'
+ (covered ? ' code-line_covered' : '')
+ (uncovered ? ' code-line_uncovered' : ''),
title: trace ? JSON.stringify(trace.stats, null, 2) : null,
}, line);
})
);
}
(function(){
const commonPath = findCommonPath(data.files);
const prevFilesMap = new Map();
previousData && previousData.files.forEach((file) => {
const path = file.path.slice(commonPath.length).join('/');
prevFilesMap.set(path, file);
});
const files = data.files.map((file) => {
const path = file.path.slice(commonPath.length);
const { covered = 0, coverable = 0 } = prevFilesMap.get(path.join('/')) || {};
return {
...file,
path,
parent: commonPath,
prevRun: { covered, coverable },
};
});
const children = findFolders(files);
const root = {
is_folder: true,
children,
path: commonPath,
parent: [],
covered: children.reduce((sum, file) => sum + file.covered, 0),
coverable: children.reduce((sum, file) => sum + file.coverable, 0),
prevRun: {
covered: children.reduce((sum, file) => sum + file.prevRun.covered, 0),
coverable: children.reduce((sum, file) => sum + file.prevRun.coverable, 0),
}
};
ReactDOM.render(e(App, {root, prevFilesMap}), document.getElementById('root'));
}());
</script>
</body>
</html>