playit-agent-proto 1.2.0

Contains the protocol messages for a playit.gg agent
Documentation
use std::io::{Error, ErrorKind, Read, Write};
use std::net::IpAddr;

use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use message_encoding::MessageEncoding;
use serde::{Deserialize, Serialize};

pub mod control_messages;
pub mod control_feed;
pub mod rpc;
pub mod hmac;
pub mod raw_slice;

#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug, Hash)]
pub struct AgentSessionId {
    pub session_id: u64,
    pub account_id: u64,
    pub agent_id: u64,
}

#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Serialize, Deserialize, Hash, Clone)]
pub struct PortRange {
    pub ip: IpAddr,
    pub port_start: u16,
    pub port_end: u16,
    pub port_proto: PortProto,
}

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Serialize, Hash, Deserialize)]
pub enum PortProto {
    #[serde(rename = "both")]
    Both,
    #[serde(rename = "tcp")]
    Tcp,
    #[serde(rename = "udp")]
    Udp,
}

impl MessageEncoding for AgentSessionId {
    const STATIC_SIZE: Option<usize> = Some(8 * 3);

    fn write_to<T: Write>(&self, out: &mut T) -> std::io::Result<usize> {
        let mut sum = 0;
        sum += self.session_id.write_to(out)?;
        sum += self.account_id.write_to(out)?;
        sum += self.agent_id.write_to(out)?;
        Ok(sum)
    }

    fn read_from<T: Read>(read: &mut T) -> std::io::Result<Self> {
        Ok(AgentSessionId {
            session_id: read.read_u64::<BigEndian>()?,
            account_id: read.read_u64::<BigEndian>()?,
            agent_id: read.read_u64::<BigEndian>()?,
        })
    }
}

impl MessageEncoding for PortRange {
    const MAX_SIZE: Option<usize> = Some(
        match IpAddr::MAX_SIZE { Some(v) => v, _ => panic!() }
        + 4
        + match PortProto::MAX_SIZE { Some(v) => v, _ => panic!() }
    );

    fn write_to<T: Write>(&self, out: &mut T) -> std::io::Result<usize> {
        let mut len = 4;
        len += self.ip.write_to(out)?;
        out.write_u16::<BigEndian>(self.port_start)?;
        out.write_u16::<BigEndian>(self.port_end)?;
        len += self.port_proto.write_to(out)?;
        Ok(len)
    }

    fn read_from<T: Read>(read: &mut T) -> std::io::Result<Self> {
        Ok(PortRange {
            ip: IpAddr::read_from(read)?,
            port_start: read.read_u16::<BigEndian>()?,
            port_end: read.read_u16::<BigEndian>()?,
            port_proto: PortProto::read_from(read)?,
        })
    }
}

impl MessageEncoding for PortProto {
    const STATIC_SIZE: Option<usize> = Some(1);

    fn write_to<T: Write>(&self, out: &mut T) -> std::io::Result<usize> {
        match self {
            PortProto::Tcp => out.write_u8(1),
            PortProto::Udp => out.write_u8(2),
            PortProto::Both => out.write_u8(3),
        }?;

        Ok(1)
    }

    fn read_from<T: Read>(read: &mut T) -> std::io::Result<Self> {
        match read.read_u8()? {
            1 => Ok(PortProto::Tcp),
            2 => Ok(PortProto::Udp),
            3 => Ok(PortProto::Both),
            _ => Err(Error::new(ErrorKind::Other, "invalid port proto")),
        }
    }
}