use toxcore::crypto_core::*;
use toxcore::tcp::packet::*;
use toxcore::io_tokio::*;
use toxcore::onion::packet::InnerOnionResponse;
use std::net::IpAddr;
use std::slice::Iter;
use futures::Future;
use futures::sync::mpsc;
pub struct Client {
pk: PublicKey,
ip_addr: IpAddr,
port: u16,
tx: mpsc::UnboundedSender<Packet>,
links: [Option<PublicKey>; 240],
ping_id: u64
}
impl Client {
pub fn new(tx: mpsc::UnboundedSender<Packet>, pk: &PublicKey, ip_addr: IpAddr, port: u16) -> Client {
Client {
pk: *pk,
ip_addr,
port,
tx,
links: [None; 240],
ping_id: 0
}
}
pub fn pk(&self) -> PublicKey {
self.pk
}
pub fn ip_addr(&self) -> IpAddr {
self.ip_addr
}
pub fn port(&self) -> u16 {
self.port
}
pub fn ping_id(&self) -> u64 {
self.ping_id
}
pub fn get_connection_id(&self, to: &PublicKey) -> Option<u8> {
self.links.iter().position(|&link| link == Some(*to)).map(|x| x as u8).map(|x| x + 16)
}
pub fn insert_connection_id(&mut self, to: &PublicKey) -> Option<u8> {
match self.get_connection_id(to) {
Some(index) => Some(index), None => {
if let Some(index) = self.links.iter().position(|link| link.is_none()) {
self.links[index] = Some(*to);
Some(index as u8).map(|x| x + 16)
} else {
None
}
}
}
}
pub fn get_link(&self, connection_id: u8) -> Option<PublicKey> {
self.links[connection_id as usize - 16]
}
pub fn take_link(&mut self, connection_id: u8) -> Option<PublicKey> {
self.links[connection_id as usize - 16].take()
}
pub fn iter_links(&self) -> Iter<Option<PublicKey>> {
self.links.iter()
}
fn send_impl(&self, packet: Packet) -> IoFuture<()> {
send_to(&self.tx, packet)
}
fn send(&self, packet: Packet) -> IoFuture<()> {
self.send_impl(packet)
}
fn send_ignore_error(&self, packet: Packet) -> IoFuture<()> {
Box::new(self.send_impl(packet)
.then(|_| Ok(()) ) )
}
pub fn send_route_response(&self, pk: &PublicKey, connection_id: u8) -> IoFuture<()> {
self.send(
Packet::RouteResponse(RouteResponse { connection_id, pk: *pk })
)
}
pub fn send_connect_notification(&self, connection_id: u8) -> IoFuture<()> {
self.send_ignore_error(
Packet::ConnectNotification(ConnectNotification { connection_id })
)
}
pub fn send_disconnect_notification(&self, connection_id: u8) -> IoFuture<()> {
self.send_ignore_error(
Packet::DisconnectNotification(DisconnectNotification { connection_id })
)
}
pub fn send_pong_response(&self, ping_id: u64) -> IoFuture<()> {
self.send(
Packet::PongResponse(PongResponse { ping_id })
)
}
pub fn send_oob(&self, sender_pk: &PublicKey, data: Vec<u8>) -> IoFuture<()> {
self.send_ignore_error(
Packet::OobReceive(OobReceive { sender_pk: *sender_pk, data })
)
}
pub fn send_onion_response(&self, payload: InnerOnionResponse) -> IoFuture<()> {
self.send(
Packet::OnionResponse(OnionResponse { payload })
)
}
pub fn send_data(&self, connection_id: u8, data: Vec<u8>) -> IoFuture<()> {
self.send(
Packet::Data(Data { connection_id, data })
)
}
}