Initial protocol
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
pub mod packet;
|
||||
|
||||
use tracing::{info, info_span};
|
||||
use tracing::{debug_span, info, info_span};
|
||||
|
||||
use crate::error::HError;
|
||||
use std::{
|
||||
@@ -95,6 +95,7 @@ impl EventBus {
|
||||
|
||||
for s in &bus.subscription_handles {
|
||||
if let Err(e) = s.new_event_signal.send(1) {
|
||||
// TODO: Multiple failures should automatically unsubscribe
|
||||
tracing::error!("Failed to notify {}", e);
|
||||
}
|
||||
}
|
||||
@@ -195,7 +196,7 @@ impl Subscription {
|
||||
fn start_delivery(mut subscription: Subscription, bus: EventBus) -> JoinHandle<Result<(), HError>> {
|
||||
thread::spawn(move || {
|
||||
loop {
|
||||
let _scope = info_span!("subscription_delivery", subscription.id).entered();
|
||||
let _scope = debug_span!("subscription_delivery", subscription.id).entered();
|
||||
loop {
|
||||
if let Ok(evt) = bus.get_next_event(subscription.cursor) {
|
||||
info!("Delivering event {} ", evt.id);
|
||||
|
||||
@@ -18,6 +18,23 @@ pub enum PacketType {
|
||||
Disconnect,
|
||||
}
|
||||
|
||||
impl Display for PacketType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let to_write = match self {
|
||||
PacketType::Connect => "CONNECT",
|
||||
PacketType::Subscribe => "SUBSCRIBE",
|
||||
PacketType::Unsubscribe => "UNSUBSCRIBE",
|
||||
PacketType::Publish => "PUBLISH",
|
||||
PacketType::SendEvent => "SEND_EVENT",
|
||||
PacketType::Settle => "SETTLE_EVENT",
|
||||
PacketType::Ack => "ACK",
|
||||
PacketType::Disconnect => "DISCONNECT",
|
||||
};
|
||||
|
||||
write!(f, "{}", to_write)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Packet {
|
||||
Connect,
|
||||
Subscribe(SubscribePacket),
|
||||
@@ -49,11 +66,15 @@ pub struct SettlePacket {
|
||||
}
|
||||
|
||||
pub struct AckPacket {
|
||||
packet_type: PacketType,
|
||||
pub packet_type: PacketType,
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
pub fn create_connect_packet(cursor: u64) -> Packet {
|
||||
pub fn create_connect_packet() -> Packet {
|
||||
Packet::Connect
|
||||
}
|
||||
|
||||
pub fn create_subscribe_packet(cursor: u64) -> Packet {
|
||||
Packet::Subscribe(SubscribePacket { cursor })
|
||||
}
|
||||
|
||||
@@ -115,7 +136,7 @@ pub struct ReadPacketState {
|
||||
|
||||
pub fn start_read_packet(buf: &mut [u8; packet_constants::HEADER_SIZE]) -> Result<ReadPacketState, PacketError> {
|
||||
let packet_type = get_packet_type_from_byte(buf[0])?;
|
||||
let required_buffer_size = read_u16(&buf[1..3]);
|
||||
let required_buffer_size = read_u16(&buf[1..3])?;
|
||||
|
||||
Ok(ReadPacketState {
|
||||
required_buffer_size,
|
||||
@@ -133,31 +154,29 @@ pub fn read_packet(buf: &[u8], read_state: ReadPacketState) -> Result<Packet, Pa
|
||||
PacketType::Unsubscribe => Ok(Packet::Unsubscribe),
|
||||
PacketType::Publish => {
|
||||
let event_type = buf[0];
|
||||
let len = read_u16(&buf[1..]);
|
||||
let event_len = read_u16(&buf[1..3])?;
|
||||
|
||||
// TODO: Share underlying bytes without copying
|
||||
let publish_packet = PublishPacket {
|
||||
event_type,
|
||||
data_utf8: buf[3..len].to_vec(),
|
||||
data_utf8: buf[3..3 + event_len].to_vec(),
|
||||
};
|
||||
Ok(Packet::Publish(publish_packet))
|
||||
}
|
||||
PacketType::SendEvent => {
|
||||
let event_id = read_u64(&buf)?;
|
||||
let event_id = read_u64(&buf[0..8])?;
|
||||
let event_type = buf[8];
|
||||
let len = usize::from_le_bytes([buf[9], buf[10], 0, 0, 0, 0, 0, 0]);
|
||||
let event_len = read_u16(&buf[9..11])?;
|
||||
|
||||
let send_event_packet = SendEventPacket {
|
||||
event_id,
|
||||
event_type,
|
||||
data_utf8: buf[11..len].to_vec(),
|
||||
data_utf8: buf[11..11 + event_len].to_vec(),
|
||||
};
|
||||
Ok(Packet::SendEvent(send_event_packet))
|
||||
}
|
||||
PacketType::Settle => {
|
||||
let mut le_bytes = [0u8; 8];
|
||||
le_bytes.copy_from_slice(&buf[0..8]);
|
||||
let cursor = u64::from_le_bytes(le_bytes);
|
||||
let cursor = read_u64(&buf[0..8])?;
|
||||
Ok(Packet::Settle(SettlePacket { cursor }))
|
||||
}
|
||||
PacketType::Ack => {
|
||||
@@ -214,7 +233,7 @@ fn write_data_frame(data_frame: &mut [u8], packet: &Packet) {
|
||||
write_event_data(
|
||||
send_event_packet.event_type,
|
||||
&send_event_packet.data_utf8,
|
||||
&mut data_frame[1..],
|
||||
&mut data_frame[8..],
|
||||
);
|
||||
}
|
||||
Packet::Settle(settle_packet) => {
|
||||
@@ -231,12 +250,12 @@ fn write_event_data(event_type: u8, data_utf8: &[u8], buf: &mut [u8]) {
|
||||
buf[0] = event_type;
|
||||
write_u16(data_utf8.len(), &mut buf[1..3]);
|
||||
let available_length = buf.len() - 3;
|
||||
buf[3..].copy_from_slice(&data_utf8[..available_length]);
|
||||
buf[3..].copy_from_slice(&data_utf8[0..available_length]);
|
||||
}
|
||||
|
||||
fn write_u64(v64: u64, data_frame: &mut [u8]) {
|
||||
let bytes = v64.to_le_bytes();
|
||||
data_frame[0..8].copy_from_slice(&bytes);
|
||||
data_frame[0..8].copy_from_slice(&bytes[0..8]);
|
||||
}
|
||||
|
||||
fn write_u16(mut length: usize, buf: &mut [u8]) {
|
||||
@@ -245,17 +264,25 @@ fn write_u16(mut length: usize, buf: &mut [u8]) {
|
||||
}
|
||||
|
||||
let bytes = length.to_le_bytes();
|
||||
buf[0..2].copy_from_slice(&bytes);
|
||||
buf[0..2].copy_from_slice(&bytes[0..2]);
|
||||
}
|
||||
|
||||
fn read_u64(buf: &[u8]) -> Result<u64, PacketError> {
|
||||
let mut le_bytes = [0u8; 8];
|
||||
if le_bytes.len() != buf.len() {
|
||||
return Err(PacketError::PacketProtocolError);
|
||||
}
|
||||
|
||||
le_bytes.copy_from_slice(buf);
|
||||
Ok(u64::from_le_bytes(le_bytes))
|
||||
}
|
||||
|
||||
fn read_u16(buf: &[u8]) -> usize {
|
||||
usize::from_le_bytes([buf[0], buf[1], 0, 0, 0, 0, 0, 0])
|
||||
fn read_u16(buf: &[u8]) -> Result<usize, PacketError> {
|
||||
if buf.len() != 2 {
|
||||
return Err(PacketError::PacketProtocolError);
|
||||
}
|
||||
|
||||
Ok(usize::from_le_bytes([buf[0], buf[1], 0, 0, 0, 0, 0, 0]))
|
||||
}
|
||||
|
||||
pub fn get_packet_type(packet: &Packet) -> PacketType {
|
||||
@@ -286,13 +313,14 @@ fn get_byte_from_packet_type(packet_type: &PacketType) -> u8 {
|
||||
|
||||
fn get_packet_type_from_byte(byte: u8) -> Result<PacketType, PacketError> {
|
||||
let packet_type = match byte {
|
||||
0 => Some(PacketType::Subscribe),
|
||||
1 => Some(PacketType::Unsubscribe),
|
||||
2 => Some(PacketType::Publish),
|
||||
3 => Some(PacketType::SendEvent),
|
||||
4 => Some(PacketType::Settle),
|
||||
5 => Some(PacketType::Ack),
|
||||
6 => Some(PacketType::Disconnect),
|
||||
0 => Some(PacketType::Connect),
|
||||
1 => Some(PacketType::Subscribe),
|
||||
2 => Some(PacketType::Unsubscribe),
|
||||
3 => Some(PacketType::Publish),
|
||||
4 => Some(PacketType::SendEvent),
|
||||
5 => Some(PacketType::Settle),
|
||||
6 => Some(PacketType::Ack),
|
||||
7 => Some(PacketType::Disconnect),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,62 @@
|
||||
pub mod bus;
|
||||
pub mod error;
|
||||
pub mod thread_pool;
|
||||
pub mod bus;
|
||||
|
||||
pub mod hd_tcp {
|
||||
use std::{
|
||||
io::{Read, Write},
|
||||
net::TcpStream,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
bus::packet::{self, Packet, PacketType},
|
||||
error::HError,
|
||||
};
|
||||
|
||||
pub fn read_packet(stream: &mut TcpStream) -> Result<Packet, HError> {
|
||||
let mut header_buf = [0u8; 3];
|
||||
stream.read_exact(&mut header_buf)?;
|
||||
let read_state = packet::start_read_packet(&mut header_buf)?;
|
||||
|
||||
let mut buf = vec![0u8; read_state.required_buffer_size];
|
||||
if read_state.required_buffer_size > 0 {
|
||||
stream.read_exact(&mut buf)?;
|
||||
}
|
||||
let packet = packet::read_packet(&buf[0..], read_state)?;
|
||||
|
||||
if let Packet::Disconnect = packet {
|
||||
return Err(HError::PeerDisconnect);
|
||||
};
|
||||
|
||||
Ok(packet)
|
||||
}
|
||||
|
||||
pub fn read_ack(stream: &mut TcpStream, packet_types: &[PacketType]) -> Result<Packet, HError> {
|
||||
let packet = read_packet(stream)?;
|
||||
if let Packet::Ack(ack_packet) = &packet {
|
||||
for packet_type in packet_types.iter() {
|
||||
if *packet_type == ack_packet.packet_type {
|
||||
return Ok(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(HError::ProtocolError)
|
||||
}
|
||||
|
||||
pub fn write_ack(stream: &mut TcpStream, packet_type: PacketType) -> Result<(), HError> {
|
||||
let packet = Packet::create_ack_packet(packet_type);
|
||||
write_packet(stream, &packet)
|
||||
}
|
||||
|
||||
pub fn write_packet(stream: &mut TcpStream, packet: &Packet) -> Result<(), HError> {
|
||||
let write_state = packet::start_write_packet(packet);
|
||||
let mut buf = vec![0u8; write_state.required_buffer_size];
|
||||
packet::write_packet(&mut buf, packet, write_state)?;
|
||||
|
||||
stream.write_all(&mut buf)?;
|
||||
stream.flush()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user