forked from M-Labs/artiq
Rust: implement moninj.
This commit is contained in:
parent
2e4d19a1ce
commit
2fefd0ad4a
|
@ -9,6 +9,7 @@ extern crate std_artiq as std;
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
use core::fmt;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use collections::LinkedList;
|
use collections::LinkedList;
|
||||||
use libc::c_void;
|
use libc::c_void;
|
||||||
|
@ -102,19 +103,54 @@ fn result_from<T, F>(err: lwip_sys::err, f: F) -> Result<T>
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum IpAddr {
|
pub enum IpAddr {
|
||||||
Ip4([u8; 4]),
|
V4([u8; 4]),
|
||||||
Ip6([u16; 8]),
|
V6([u16; 8]),
|
||||||
IpAny
|
Any
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const IP4_ANY: IpAddr = IpAddr::Ip4([0, 0, 0, 0]);
|
pub const IP4_ANY: IpAddr = IpAddr::V4([0, 0, 0, 0]);
|
||||||
pub const IP6_ANY: IpAddr = IpAddr::Ip6([0, 0, 0, 0, 0, 0, 0, 0]);
|
pub const IP6_ANY: IpAddr = IpAddr::V6([0, 0, 0, 0, 0, 0, 0, 0]);
|
||||||
pub const IP_ANY: IpAddr = IpAddr::IpAny;
|
pub const IP_ANY: IpAddr = IpAddr::Any;
|
||||||
|
|
||||||
|
impl fmt::Display for IpAddr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
IpAddr::V4(ref octets) =>
|
||||||
|
write!(f, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]),
|
||||||
|
|
||||||
|
IpAddr::V6(ref segments) => {
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum State { Head, Skip, Tail };
|
||||||
|
|
||||||
|
let mut state = State::Head;
|
||||||
|
for (idx, &segment) in segments.iter().enumerate() {
|
||||||
|
match state {
|
||||||
|
State::Head | State::Skip if segment == 0 =>
|
||||||
|
state = State::Skip,
|
||||||
|
State::Skip if segment != 0 => {
|
||||||
|
state = State::Tail;
|
||||||
|
try!(write!(f, ":{:x}", segment))
|
||||||
|
}
|
||||||
|
_ => try!(write!(f, "{:x}", segment))
|
||||||
|
}
|
||||||
|
|
||||||
|
if state != State::Skip && idx != 15 {
|
||||||
|
try!(write!(f, ":"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
|
||||||
|
IpAddr::Any =>
|
||||||
|
write!(f, "*")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IpAddr {
|
impl IpAddr {
|
||||||
fn into_raw(self) -> lwip_sys::ip_addr {
|
fn into_raw(self) -> lwip_sys::ip_addr {
|
||||||
match self {
|
match self {
|
||||||
IpAddr::Ip4(ref octets) =>
|
IpAddr::V4(octets) =>
|
||||||
lwip_sys::ip_addr {
|
lwip_sys::ip_addr {
|
||||||
data: [(octets[0] as u32) << 24 |
|
data: [(octets[0] as u32) << 24 |
|
||||||
(octets[1] as u32) << 16 |
|
(octets[1] as u32) << 16 |
|
||||||
|
@ -123,7 +159,7 @@ impl IpAddr {
|
||||||
0, 0, 0],
|
0, 0, 0],
|
||||||
type_: lwip_sys::IPADDR_TYPE_V4
|
type_: lwip_sys::IPADDR_TYPE_V4
|
||||||
},
|
},
|
||||||
IpAddr::Ip6(ref segments) =>
|
IpAddr::V6(segments) =>
|
||||||
lwip_sys::ip_addr {
|
lwip_sys::ip_addr {
|
||||||
data: [(segments[0] as u32) << 16 | (segments[1] as u32),
|
data: [(segments[0] as u32) << 16 | (segments[1] as u32),
|
||||||
(segments[2] as u32) << 16 | (segments[3] as u32),
|
(segments[2] as u32) << 16 | (segments[3] as u32),
|
||||||
|
@ -131,7 +167,7 @@ impl IpAddr {
|
||||||
(segments[6] as u32) << 16 | (segments[7] as u32)],
|
(segments[6] as u32) << 16 | (segments[7] as u32)],
|
||||||
type_: lwip_sys::IPADDR_TYPE_V6
|
type_: lwip_sys::IPADDR_TYPE_V6
|
||||||
},
|
},
|
||||||
IpAddr::IpAny =>
|
IpAddr::Any =>
|
||||||
lwip_sys::ip_addr {
|
lwip_sys::ip_addr {
|
||||||
data: [0; 4],
|
data: [0; 4],
|
||||||
type_: lwip_sys::IPADDR_TYPE_ANY
|
type_: lwip_sys::IPADDR_TYPE_ANY
|
||||||
|
@ -142,17 +178,17 @@ impl IpAddr {
|
||||||
unsafe fn from_raw(raw: *mut lwip_sys::ip_addr) -> IpAddr {
|
unsafe fn from_raw(raw: *mut lwip_sys::ip_addr) -> IpAddr {
|
||||||
match *raw {
|
match *raw {
|
||||||
lwip_sys::ip_addr { type_: lwip_sys::IPADDR_TYPE_V4, data } =>
|
lwip_sys::ip_addr { type_: lwip_sys::IPADDR_TYPE_V4, data } =>
|
||||||
IpAddr::Ip4([(data[0] >> 24) as u8,
|
IpAddr::V4([(data[0] >> 24) as u8,
|
||||||
(data[0] >> 16) as u8,
|
(data[0] >> 16) as u8,
|
||||||
(data[0] >> 8) as u8,
|
(data[0] >> 8) as u8,
|
||||||
(data[0] >> 0) as u8]),
|
(data[0] >> 0) as u8]),
|
||||||
lwip_sys::ip_addr { type_: lwip_sys::IPADDR_TYPE_V6, data } =>
|
lwip_sys::ip_addr { type_: lwip_sys::IPADDR_TYPE_V6, data } =>
|
||||||
IpAddr::Ip6([(data[0] >> 16) as u16, data[0] as u16,
|
IpAddr::V6([(data[0] >> 16) as u16, data[0] as u16,
|
||||||
(data[1] >> 16) as u16, data[1] as u16,
|
(data[1] >> 16) as u16, data[1] as u16,
|
||||||
(data[2] >> 16) as u16, data[2] as u16,
|
(data[2] >> 16) as u16, data[2] as u16,
|
||||||
(data[3] >> 16) as u16, data[3] as u16]),
|
(data[3] >> 16) as u16, data[3] as u16]),
|
||||||
lwip_sys::ip_addr { type_: lwip_sys::IPADDR_TYPE_ANY, .. } =>
|
lwip_sys::ip_addr { type_: lwip_sys::IPADDR_TYPE_ANY, .. } =>
|
||||||
IpAddr::IpAny
|
IpAddr::Any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,6 +199,12 @@ pub struct SocketAddr {
|
||||||
pub port: u16
|
pub port: u16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SocketAddr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}:{}", self.ip, self.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SocketAddr {
|
impl SocketAddr {
|
||||||
pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
|
pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
|
||||||
SocketAddr { ip: ip, port: port }
|
SocketAddr { ip: ip, port: port }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(libc, const_fn, try_borrow)]
|
#![feature(libc, const_fn, try_borrow, stmt_expr_attributes)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate std_artiq as std;
|
extern crate std_artiq as std;
|
||||||
|
@ -24,11 +24,14 @@ mod sched;
|
||||||
mod logger;
|
mod logger;
|
||||||
mod cache;
|
mod cache;
|
||||||
|
|
||||||
|
mod proto;
|
||||||
mod kernel_proto;
|
mod kernel_proto;
|
||||||
mod session_proto;
|
mod session_proto;
|
||||||
|
mod moninj_proto;
|
||||||
|
|
||||||
mod kernel;
|
mod kernel;
|
||||||
mod session;
|
mod session;
|
||||||
|
mod moninj;
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
fn network_init();
|
fn network_init();
|
||||||
|
@ -52,6 +55,7 @@ pub unsafe extern fn rust_main() {
|
||||||
|
|
||||||
let mut scheduler = sched::Scheduler::new();
|
let mut scheduler = sched::Scheduler::new();
|
||||||
scheduler.spawner().spawn(8192, session::thread);
|
scheduler.spawner().spawn(8192, session::thread);
|
||||||
|
scheduler.spawner().spawn(4096, moninj::thread);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
scheduler.run();
|
scheduler.run();
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
use std::vec::Vec;
|
||||||
|
use std::io;
|
||||||
|
use board::csr;
|
||||||
|
use sched::{Waiter, Spawner};
|
||||||
|
use sched::{UdpSocket, SocketAddr, IP_ANY};
|
||||||
|
use moninj_proto::*;
|
||||||
|
|
||||||
|
const MONINJ_TTL_OVERRIDE_ENABLE: u8 = 0;
|
||||||
|
const MONINJ_TTL_OVERRIDE_O: u8 = 1;
|
||||||
|
const MONINJ_TTL_OVERRIDE_OE: u8 = 2;
|
||||||
|
|
||||||
|
fn worker(socket: &mut UdpSocket) -> io::Result<()> {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
loop {
|
||||||
|
let addr = try!(socket.recv_from(&mut buf));
|
||||||
|
let request = try!(Request::read_from(&mut io::Cursor::new(&buf)));
|
||||||
|
trace!("{} -> {:?}", addr, request);
|
||||||
|
|
||||||
|
match request {
|
||||||
|
Request::Monitor => {
|
||||||
|
let mut dds_ftws = [0; (csr::CONFIG_RTIO_DDS_COUNT as usize *
|
||||||
|
csr::CONFIG_DDS_CHANNELS_PER_BUS as usize)];
|
||||||
|
let mut reply = Reply::default();
|
||||||
|
|
||||||
|
for i in 0..csr::CONFIG_RTIO_REGULAR_TTL_COUNT as u8 {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio_moninj::mon_chan_sel_write(i);
|
||||||
|
csr::rtio_moninj::mon_probe_sel_write(0);
|
||||||
|
csr::rtio_moninj::mon_value_update_write(1);
|
||||||
|
if csr::rtio_moninj::mon_value_read() != 0 {
|
||||||
|
reply.ttl_levels |= 1 << i;
|
||||||
|
}
|
||||||
|
csr::rtio_moninj::mon_probe_sel_write(1);
|
||||||
|
csr::rtio_moninj::mon_value_update_write(1);
|
||||||
|
if csr::rtio_moninj::mon_value_read() != 0 {
|
||||||
|
reply.ttl_oes |= 1 << i;
|
||||||
|
}
|
||||||
|
csr::rtio_moninj::inj_chan_sel_write(i);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
|
||||||
|
if csr::rtio_moninj::inj_value_read() != 0 {
|
||||||
|
reply.ttl_overrides |= 1 << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.dds_rtio_first_channel = csr::CONFIG_RTIO_FIRST_DDS_CHANNEL as u16;
|
||||||
|
reply.dds_channels_per_bus = csr::CONFIG_DDS_CHANNELS_PER_BUS as u16;
|
||||||
|
|
||||||
|
for j in 0..csr::CONFIG_RTIO_DDS_COUNT {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio_moninj::mon_chan_sel_write(
|
||||||
|
(csr::CONFIG_RTIO_FIRST_DDS_CHANNEL + j) as u8);
|
||||||
|
for i in 0..csr::CONFIG_DDS_CHANNELS_PER_BUS {
|
||||||
|
csr::rtio_moninj::mon_probe_sel_write(i as u8);
|
||||||
|
csr::rtio_moninj::mon_value_update_write(1);
|
||||||
|
dds_ftws[(csr::CONFIG_DDS_CHANNELS_PER_BUS * j + i) as usize] =
|
||||||
|
csr::rtio_moninj::mon_value_read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply.dds_ftws = &dds_ftws;
|
||||||
|
|
||||||
|
trace!("{} <- {:?}", addr, reply);
|
||||||
|
buf.clear();
|
||||||
|
try!(reply.write_to(&mut buf));
|
||||||
|
try!(socket.send_to(&buf, addr));
|
||||||
|
},
|
||||||
|
|
||||||
|
Request::TtlSet { channel, mode: TtlMode::Experiment } => {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio_moninj::inj_chan_sel_write(channel);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
|
||||||
|
csr::rtio_moninj::inj_value_write(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Request::TtlSet { channel, mode: TtlMode::High } => {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio_moninj::inj_chan_sel_write(channel);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_O);
|
||||||
|
csr::rtio_moninj::inj_value_write(1);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_OE);
|
||||||
|
csr::rtio_moninj::inj_value_write(1);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
|
||||||
|
csr::rtio_moninj::inj_value_write(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Request::TtlSet { channel, mode: TtlMode::Low } => {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio_moninj::inj_chan_sel_write(channel);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_O);
|
||||||
|
csr::rtio_moninj::inj_value_write(0);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_OE);
|
||||||
|
csr::rtio_moninj::inj_value_write(1);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
|
||||||
|
csr::rtio_moninj::inj_value_write(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Request::TtlSet { channel, mode: TtlMode::Input } => {
|
||||||
|
unsafe {
|
||||||
|
csr::rtio_moninj::inj_chan_sel_write(channel);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_OE);
|
||||||
|
csr::rtio_moninj::inj_value_write(0);
|
||||||
|
csr::rtio_moninj::inj_override_sel_write(MONINJ_TTL_OVERRIDE_ENABLE);
|
||||||
|
csr::rtio_moninj::inj_value_write(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn thread(waiter: Waiter, _spawner: Spawner) {
|
||||||
|
let mut socket = UdpSocket::new(waiter).expect("cannot create socket");
|
||||||
|
socket.bind(SocketAddr::new(IP_ANY, 3250)).expect("cannot bind socket");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match worker(&mut socket) {
|
||||||
|
Ok(()) => unreachable!(),
|
||||||
|
Err(err) => error!("moninj aborted: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use proto::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TtlMode {
|
||||||
|
Experiment,
|
||||||
|
High,
|
||||||
|
Low,
|
||||||
|
Input
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TtlMode {
|
||||||
|
pub fn read_from(reader: &mut Read) -> io::Result<TtlMode> {
|
||||||
|
Ok(match try!(read_u8(reader)) {
|
||||||
|
0 => TtlMode::Experiment,
|
||||||
|
1 => TtlMode::High,
|
||||||
|
2 => TtlMode::Low,
|
||||||
|
3 => TtlMode::Input,
|
||||||
|
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unknown TTL mode"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Request {
|
||||||
|
Monitor,
|
||||||
|
TtlSet { channel: u8, mode: TtlMode }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Request {
|
||||||
|
pub fn read_from(reader: &mut Read) -> io::Result<Request> {
|
||||||
|
Ok(match try!(read_u8(reader)) {
|
||||||
|
1 => Request::Monitor,
|
||||||
|
2 => Request::TtlSet {
|
||||||
|
channel: try!(read_u8(reader)),
|
||||||
|
mode: try!(TtlMode::read_from(reader))
|
||||||
|
},
|
||||||
|
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unknown request type"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Reply<'a> {
|
||||||
|
pub ttl_levels: u64,
|
||||||
|
pub ttl_oes: u64,
|
||||||
|
pub ttl_overrides: u64,
|
||||||
|
pub dds_rtio_first_channel: u16,
|
||||||
|
pub dds_channels_per_bus: u16,
|
||||||
|
pub dds_ftws: &'a [u32]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Reply<'a> {
|
||||||
|
pub fn write_to(&self, writer: &mut Write) -> io::Result<()> {
|
||||||
|
try!(write_u64(writer, self.ttl_levels));
|
||||||
|
try!(write_u64(writer, self.ttl_oes));
|
||||||
|
try!(write_u64(writer, self.ttl_overrides));
|
||||||
|
try!(write_u16(writer, self.dds_rtio_first_channel));
|
||||||
|
try!(write_u16(writer, self.dds_channels_per_bus));
|
||||||
|
for dds_ftw in self.dds_ftws {
|
||||||
|
try!(write_u32(writer, *dds_ftw));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
|
|
||||||
|
// FIXME: replace these with byteorder core io traits once those are in
|
||||||
|
pub fn read_u8(reader: &mut Read) -> io::Result<u8> {
|
||||||
|
let mut bytes = [0; 1];
|
||||||
|
try!(reader.read_exact(&mut bytes));
|
||||||
|
Ok(bytes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u8(writer: &mut Write, value: u8) -> io::Result<()> {
|
||||||
|
let bytes = [value; 1];
|
||||||
|
writer.write_all(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u16(reader: &mut Read) -> io::Result<u16> {
|
||||||
|
let mut bytes = [0; 2];
|
||||||
|
try!(reader.read_exact(&mut bytes));
|
||||||
|
Ok(NetworkEndian::read_u16(&bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u16(writer: &mut Write, value: u16) -> io::Result<()> {
|
||||||
|
let mut bytes = [0; 2];
|
||||||
|
NetworkEndian::write_u16(&mut bytes, value);
|
||||||
|
writer.write_all(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u32(reader: &mut Read) -> io::Result<u32> {
|
||||||
|
let mut bytes = [0; 4];
|
||||||
|
try!(reader.read_exact(&mut bytes));
|
||||||
|
Ok(NetworkEndian::read_u32(&bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u32(writer: &mut Write, value: u32) -> io::Result<()> {
|
||||||
|
let mut bytes = [0; 4];
|
||||||
|
NetworkEndian::write_u32(&mut bytes, value);
|
||||||
|
writer.write_all(&bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_u64(reader: &mut Read) -> io::Result<u64> {
|
||||||
|
let mut bytes = [0; 8];
|
||||||
|
try!(reader.read_exact(&mut bytes));
|
||||||
|
Ok(NetworkEndian::read_u64(&bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_u64(writer: &mut Write, value: u64) -> io::Result<()> {
|
||||||
|
let mut bytes = [0; 8];
|
||||||
|
NetworkEndian::write_u64(&mut bytes, value);
|
||||||
|
writer.write_all(&bytes)
|
||||||
|
}
|
|
@ -328,12 +328,12 @@ impl<'a> UdpSocket<'a> {
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
|
pub fn recv_from(&self, buf: &mut Vec<u8>) -> Result<SocketAddr> {
|
||||||
try!(self.waiter.udp_readable(&self.lower));
|
try!(self.waiter.udp_readable(&self.lower));
|
||||||
let (pbuf, addr) = self.lower.try_recv().unwrap();
|
let (pbuf, addr) = self.lower.try_recv().unwrap();
|
||||||
let len = ::std::cmp::min(buf.len(), pbuf.len());
|
buf.clear();
|
||||||
(&mut buf[..len]).copy_from_slice(&pbuf.as_slice()[..len]);
|
buf.extend_from_slice(&pbuf.as_slice());
|
||||||
Ok((len, addr))
|
Ok(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send(&self, buf: &[u8]) -> Result<usize> {
|
pub fn send(&self, buf: &[u8]) -> Result<usize> {
|
||||||
|
|
|
@ -1,42 +1,6 @@
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use proto::*;
|
||||||
|
|
||||||
// FIXME: replace these with byteorder core io traits once those are in
|
|
||||||
fn read_u8(reader: &mut Read) -> io::Result<u8> {
|
|
||||||
let mut bytes = [0; 1];
|
|
||||||
try!(reader.read_exact(&mut bytes));
|
|
||||||
Ok(bytes[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u8(writer: &mut Write, value: u8) -> io::Result<()> {
|
|
||||||
let bytes = [value; 1];
|
|
||||||
writer.write_all(&bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_u32(reader: &mut Read) -> io::Result<u32> {
|
|
||||||
let mut bytes = [0; 4];
|
|
||||||
try!(reader.read_exact(&mut bytes));
|
|
||||||
Ok(NetworkEndian::read_u32(&bytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u32(writer: &mut Write, value: u32) -> io::Result<()> {
|
|
||||||
let mut bytes = [0; 4];
|
|
||||||
NetworkEndian::write_u32(&mut bytes, value);
|
|
||||||
writer.write_all(&bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_u64(reader: &mut Read) -> io::Result<u64> {
|
|
||||||
let mut bytes = [0; 4];
|
|
||||||
try!(reader.read_exact(&mut bytes));
|
|
||||||
Ok(NetworkEndian::read_u64(&bytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u64(writer: &mut Write, value: u64) -> io::Result<()> {
|
|
||||||
let mut bytes = [0; 4];
|
|
||||||
NetworkEndian::write_u64(&mut bytes, value);
|
|
||||||
writer.write_all(&bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_bytes(reader: &mut Read) -> io::Result<Vec<u8>> {
|
fn read_bytes(reader: &mut Read) -> io::Result<Vec<u8>> {
|
||||||
let length = try!(read_u32(reader));
|
let length = try!(read_u32(reader));
|
||||||
|
@ -140,9 +104,9 @@ impl Request {
|
||||||
|
|
||||||
try!(read_sync(reader));
|
try!(read_sync(reader));
|
||||||
let length = try!(read_u32(reader)) as usize;
|
let length = try!(read_u32(reader)) as usize;
|
||||||
let type_ = try!(read_u8(reader));
|
let ty = try!(read_u8(reader));
|
||||||
|
|
||||||
Ok(match type_ {
|
Ok(match ty {
|
||||||
1 => Request::Log,
|
1 => Request::Log,
|
||||||
2 => Request::LogClear,
|
2 => Request::LogClear,
|
||||||
3 => Request::Ident,
|
3 => Request::Ident,
|
||||||
|
@ -168,7 +132,7 @@ impl Request {
|
||||||
12 => Request::FlashRemove {
|
12 => Request::FlashRemove {
|
||||||
key: try!(read_string(reader))
|
key: try!(read_string(reader))
|
||||||
},
|
},
|
||||||
_ => unreachable!()
|
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, "unknown request type"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue