Initial protocol

This commit is contained in:
2026-09-08 19:30:24 +05:30
parent 6a62c33f42
commit a3385e7702
9 changed files with 236 additions and 145 deletions
+5 -2
View File
@@ -10,14 +10,17 @@ fn main() -> Result<(), HError> {
.init();
let addr = "0.0.0.0:21368";
let _scope = info_span!("example_server").entered();
let server = Arc::new(TcpEventBus::new());
server.publish(EventData::new(1, "Hello"))?;
server.publish(EventData::new(1, "World"))?;
let server_clone = server.clone();
thread::spawn(move || server.start(addr));
thread::spawn(move || {
let _scope = info_span!("tcp_server").entered();
server.start(addr)
});
let _scope = info_span!("health_checks").entered();
for i in 0..255 {
thread::sleep(Duration::from_secs(5));
server_clone.publish(EventData::new(i, "asd"))?;
+84 -86
View File
@@ -1,5 +1,4 @@
use std::{
io::{Read, Write},
net::TcpStream,
sync::{Arc, mpsc::Receiver},
time::Duration,
@@ -8,13 +7,14 @@ use std::{
use hd_lib::{
bus::{
Event, EventBus, EventData,
packet::{self, Packet, PacketType},
packet::{self, Packet, PacketType, PublishPacket, get_packet_type},
},
error::HError,
hd_tcp,
thread_pool::ThreadPool,
};
use tracing::{Span, info, info_span};
use tracing::{debug, error, info, info_span};
use std::net::TcpListener;
@@ -40,11 +40,11 @@ impl TcpEventBus {
impl TcpEventBus {
pub fn start(&self, addr: &'static str) -> Result<(), HError> {
let listener = TcpListener::bind(addr)?;
info!("Heimdall listening at {}", addr);
info!("Heimdall running at {}", addr);
for stream in listener.incoming() {
match stream {
Ok(stream) => handle_event_bus_client(&self.pool, self.bus.clone(), stream)?,
Err(e) => tracing::error!("TCP connection failed {}", e),
Err(e) => error!("TCP connection failed {}", e),
}
}
@@ -90,57 +90,11 @@ impl EventBusClientConnection {
}
}
fn read_ack(stream: &mut TcpStream, packet_type: PacketType) -> Result<(), HError> {
let packet = read_packet(stream)?;
if packet_type == packet::get_packet_type(&packet) {
return Ok(())
}
Err(HError::ProtocolError)
}
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];
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)
}
fn write_ack(stream: &mut TcpStream, packet_type: PacketType) -> Result<(), HError> {
let packet = Packet::create_ack_packet(packet_type);
write_packet(stream, &packet)
}
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(())
}
pub fn handle_event_bus_client(thread_pool: &ThreadPool, bus: EventBus, stream: TcpStream) -> Result<(), HError> {
thread_pool.execute(move || {
let mut client = EventBusClientConnection::new(bus, stream)?;
let _scope = info_span!(
"handle_event_bus_client",
addr = client.addr,
state = %client.state
)
.entered();
let _scope = info_span!("handle_client", addr = client.addr,).entered();
loop {
if let EventBusClientConnectionState::Disconnect = client.state {
@@ -154,8 +108,6 @@ pub fn handle_event_bus_client(thread_pool: &ThreadPool, bus: EventBus, stream:
if prev_state != client.state {
info!("State change {} -> {}", prev_state, client.state);
}
Span::current().record("state", format!("{}", client.state));
}
})
}
@@ -163,7 +115,7 @@ pub fn handle_event_bus_client(thread_pool: &ThreadPool, bus: EventBus, stream:
fn handle_event_bus_client_state(client: &mut EventBusClientConnection) -> Result<(), HError> {
let next_state = match client.state {
EventBusClientConnectionState::Connect => handle_state_connect(client),
EventBusClientConnectionState::Command => handle_state_connect(client),
EventBusClientConnectionState::Command => handle_state_command(client),
EventBusClientConnectionState::SendEvent => handle_state_send_event(client),
EventBusClientConnectionState::WaitEvent => handle_state_wait_event(client),
EventBusClientConnectionState::Disconnect => Ok(EventBusClientConnectionState::Disconnect),
@@ -174,66 +126,112 @@ fn handle_event_bus_client_state(client: &mut EventBusClientConnection) -> Resul
}
fn handle_state_connect(client: &mut EventBusClientConnection) -> Result<EventBusClientConnectionState, HError> {
let Packet::Connect = read_packet(&mut client.stream)? else {
return Ok(EventBusClientConnectionState::Disconnect);
};
match hd_tcp::read_packet(&mut client.stream)? {
Packet::Connect => {
info!("Received connect, acking");
write_ack(&mut client.stream, PacketType::Connect)?;
Ok(EventBusClientConnectionState::Command)
hd_tcp::write_ack(&mut client.stream, PacketType::Connect)?;
info!("Connect ack complete");
Ok(EventBusClientConnectionState::Command)
}
p => {
error!(
"Received wrong packet of type {}, expected {}. Will disconnect",
get_packet_type(&p),
PacketType::Connect
);
Ok(EventBusClientConnectionState::Disconnect)
}
}
}
fn handle_state_command(client: &mut EventBusClientConnection) -> Result<EventBusClientConnectionState, HError> {
match read_packet(&mut client.stream)? {
match hd_tcp::read_packet(&mut client.stream)? {
// TODO: Read cursor
Packet::Subscribe(_) => {
write_ack(&mut client.stream, PacketType::Subscribe)?;
info!("Received subscribe");
let subscription = client.bus.subscribe()?;
info!("Subscribed to the event bus");
client.subscription = Some(subscription);
// TODO: Return error if any
hd_tcp::write_ack(&mut client.stream, PacketType::Subscribe)?;
info!("Subscribe ack complete");
Ok(EventBusClientConnectionState::SendEvent)
}
Packet::Publish(publish_packet) => {
write_ack(&mut client.stream, PacketType::Publish)?;
info!("Received publish packet");
publish_packet_to_bus(client, publish_packet)?;
// TODO: Possible without copying data_utf8?
let data = String::from_utf8(publish_packet.data_utf8)?;
client.bus.publish(EventData::new(publish_packet.event_type, &data))?;
// TODO: Return error if any
hd_tcp::write_ack(&mut client.stream, PacketType::Publish)?;
debug!("Publish ack complete");
Ok(EventBusClientConnectionState::WaitEvent)
}
_ => Ok(EventBusClientConnectionState::Disconnect),
p => {
error!(
"Received wrong packet of type {}, expected {}. Will disconnect",
get_packet_type(&p),
PacketType::Connect
);
Ok(EventBusClientConnectionState::Disconnect)
}
}
}
fn handle_state_send_event(client: &mut EventBusClientConnection) -> Result<EventBusClientConnectionState, HError> {
if let Some(subscription) = &mut client.subscription {
loop {
let Ok(evt) = subscription.recv() else {
return Ok(EventBusClientConnectionState::Disconnect);
};
// TODO: When client sends unsubscribe, server shouldn't take forever
// to ack that.
let Ok(evt) = subscription.recv() else {
error!("Failed to receive a message for this subscription, disconnecting");
return Ok(EventBusClientConnectionState::Disconnect);
};
info!(
"SEND => ID: {} TYPE: {} LEN: {} <=",
evt.id,
evt.data.event_type,
evt.data.data_utf8.len()
);
let packet = Packet::create_send_event_packet(evt);
hd_tcp::write_packet(&mut client.stream, &packet)?;
debug!("Published event to client, waiting for ack");
let packet = Packet::create_send_event_packet(evt);
write_packet(&mut client.stream, &packet)?;
read_ack(&mut client.stream, PacketType::SendEvent)?;
let ack_packet = hd_tcp::read_ack(&mut client.stream, &[PacketType::SendEvent, PacketType::Unsubscribe])?;
if packet::get_packet_type(&ack_packet) == PacketType::Unsubscribe {
info!("Subscriber unsubscribed");
return Ok(EventBusClientConnectionState::Command);
}
debug!("Publish ack received, message is settled");
}
Ok(EventBusClientConnectionState::Disconnect)
Ok(EventBusClientConnectionState::SendEvent)
}
fn handle_state_wait_event(client: &mut EventBusClientConnection) -> Result<EventBusClientConnectionState, HError> {
todo!()
match hd_tcp::read_packet(&mut client.stream)? {
Packet::Publish(publish_packet) => {
debug!("Received event from client, publishing to bus");
publish_packet_to_bus(client, publish_packet)?;
hd_tcp::write_ack(&mut client.stream, PacketType::Publish)?;
debug!("Ack receive event complete");
Ok(EventBusClientConnectionState::WaitEvent)
}
p => {
error!(
"Received wrong packet of type {}, expected {}. Will disconnect",
get_packet_type(&p),
PacketType::Connect
);
Ok(EventBusClientConnectionState::Disconnect)
}
}
}
fn write_le_bytes(v64: u64, buf: &mut [u8]) {
let le_bytes = v64.to_le_bytes();
buf[0..8].copy_from_slice(&le_bytes);
fn publish_packet_to_bus(client: &mut EventBusClientConnection, packet: PublishPacket) -> Result<(), HError> {
let data = String::from_utf8(packet.data_utf8)?;
let evt = EventData::new(packet.event_type, &data);
client.bus.publish(evt)?;
Ok(())
}
impl std::fmt::Display for EventBusClientConnectionState {