feat: new stuff
This commit is contained in:
parent
3eece7ecd9
commit
f88706bac8
20 changed files with 232 additions and 77 deletions
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
14
.idea/domo.iml
Normal file
14
.idea/domo.iml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/domo_node/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/domo_proto/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/domo_node/target" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/domo_proto/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
6
.idea/encodings.xml
Normal file
6
.idea/encodings.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding">
|
||||||
|
<file url="file://$PROJECT_DIR$/domo_node/packet" charset="ISO-8859-1" />
|
||||||
|
</component>
|
||||||
|
</project>
|
10
.idea/misc.xml
Normal file
10
.idea/misc.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DiscordProjectSettings">
|
||||||
|
<option name="show" value="ASK" />
|
||||||
|
<option name="description" value="" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/domo.iml" filepath="$PROJECT_DIR$/.idea/domo.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -8,7 +8,7 @@ The job of a master node is rather complex.
|
||||||
## Forwarding packets
|
## Forwarding packets
|
||||||
The most straight forward job of the node.
|
The most straight forward job of the node.
|
||||||
It works by essentially having a hashmap with a reference to a socket.
|
It works by essentially having a hashmap with a reference to a socket.
|
||||||
When a packet comes in the node gets forwarded to the right socket.
|
When a packet comes in the packet gets forwarded to the right node and socket.
|
||||||
|
|
||||||
## Handling network state
|
## Handling network state
|
||||||
The master node ensures there are no duplicate identifiers and therefore nodes.
|
The master node ensures there are no duplicate identifiers and therefore nodes.
|
||||||
|
@ -16,7 +16,7 @@ Also, it will make sure no invalid updates can be sent.
|
||||||
Most packets go through the master node before getting to the source.
|
Most packets go through the master node before getting to the source.
|
||||||
Most because the subnet node can have private nodes and handle those themselves.
|
Most because the subnet node can have private nodes and handle those themselves.
|
||||||
|
|
||||||
# The Bridge node (`relay`)
|
# The Bridge node (`bridge`)
|
||||||
The bridge node is simple.
|
The bridge node is simple.
|
||||||
In config you define where to forward the packets to, and they get delivered to there.
|
In config you define where to forward the packets to, and they get delivered to there.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[node.type.master]
|
[node.type.master]
|
||||||
bind = "127.0.0.1:4480"
|
bind = "0.0.0.0:4480"
|
||||||
|
|
||||||
[node]
|
[node]
|
||||||
device_id = "ffffffff"
|
device_id = "ffffffff"
|
||||||
|
|
BIN
domo_node/ping_packet
Normal file
BIN
domo_node/ping_packet
Normal file
Binary file not shown.
BIN
domo_node/register_packet
Normal file
BIN
domo_node/register_packet
Normal file
Binary file not shown.
72
domo_node/src/app/master.rs
Normal file
72
domo_node/src/app/master.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use log::{info, trace};
|
||||||
|
use domo_proto::data_types::DataType;
|
||||||
|
use domo_proto::identifier::Identifier;
|
||||||
|
|
||||||
|
pub struct Device {
|
||||||
|
/// Device identifier
|
||||||
|
pub device_id: Identifier,
|
||||||
|
/// Device socket address
|
||||||
|
pub socket_addr: SocketAddr,
|
||||||
|
/// List of properties and last state.
|
||||||
|
pub properties: HashMap<String, DataType>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Devices {
|
||||||
|
devices: HashMap<Identifier, Device>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Devices {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
devices: HashMap::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_device_random(&mut self, socket_addr: SocketAddr) -> Identifier {
|
||||||
|
let random_id = loop {
|
||||||
|
// TODO: random should avoid 0xFFFF----
|
||||||
|
let id = Identifier::random();
|
||||||
|
trace!("checking if id is taken: {}", id);
|
||||||
|
if !self.devices.contains_key(&id) { break id; }
|
||||||
|
};
|
||||||
|
self.devices.insert(random_id, Device {
|
||||||
|
device_id: random_id,
|
||||||
|
socket_addr,
|
||||||
|
properties: HashMap::new()
|
||||||
|
});
|
||||||
|
info!("Registered new device: {}", random_id);
|
||||||
|
random_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_device(&mut self, socket_addr: SocketAddr, identifier: Identifier) -> Identifier {
|
||||||
|
self.devices.insert(identifier, Device {
|
||||||
|
device_id: identifier,
|
||||||
|
socket_addr,
|
||||||
|
properties: HashMap::new()
|
||||||
|
});
|
||||||
|
identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_device_auto(&mut self, socket_addr: SocketAddr, identifier: Option<Identifier>) -> Identifier {
|
||||||
|
let identifier = if identifier == Some(Identifier::default()) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
identifier
|
||||||
|
};
|
||||||
|
if let Some(identifier) = identifier {
|
||||||
|
match (identifier, self.devices.contains_key(&identifier)) {
|
||||||
|
(identifier, false) => self.add_device(socket_addr, identifier),
|
||||||
|
_ => self.add_device_random(socket_addr)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.add_device_random(socket_addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_device(&self, identifier: Identifier) -> Option<&Device> {
|
||||||
|
self.devices.get(&identifier)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,21 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
use log::{error, trace, warn};
|
use log::{error, info, trace, warn};
|
||||||
use tokio::sync::mpsc::channel;
|
|
||||||
use domo_proto::commands::node_management::NodeManagementCommand;
|
use domo_proto::commands::node_management::NodeManagementCommand;
|
||||||
use domo_proto::identifier::Identifier;
|
use domo_proto::identifier::Identifier;
|
||||||
use domo_proto::packet::{Packet, ToPacket};
|
use domo_proto::packet::{ToPacket};
|
||||||
use domo_proto::packet::packet_data::PacketData;
|
use domo_proto::packet::packet_data::PacketData;
|
||||||
use domo_proto::packet::raw_packet::RawPacket;
|
|
||||||
use crate::{CONFIG, prelude};
|
use crate::{CONFIG, prelude};
|
||||||
|
use crate::app::master::Devices;
|
||||||
use crate::config::node::NodeType;
|
use crate::config::node::NodeType;
|
||||||
use crate::connection::server::Server;
|
use crate::connection::server::Server;
|
||||||
|
|
||||||
|
pub mod master;
|
||||||
|
|
||||||
impl NodeType {
|
impl NodeType {
|
||||||
pub async fn start(self) -> io::Result<()> {
|
pub async fn start(self) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
NodeType::Master { bind } => {
|
NodeType::Master { bind } => {
|
||||||
let server = Server::new(
|
let mut server = Server::new(
|
||||||
bind,
|
bind,
|
||||||
Some(
|
Some(
|
||||||
Identifier::from(
|
Identifier::from(
|
||||||
|
@ -24,25 +25,51 @@ impl NodeType {
|
||||||
),
|
),
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
|
info!("Started server at {}", server.sock().local_addr()?);
|
||||||
|
|
||||||
|
let mut devices = Devices::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
let p = NodeManagementCommand::Ping.to_packet(
|
std::fs::write("./register_packet", Into::<Vec<u8>>::into(NodeManagementCommand::RegisterNode {
|
||||||
|
device_id: Identifier::from(0x000000AA)
|
||||||
|
}.to_packet(
|
||||||
Identifier::random(),
|
Identifier::random(),
|
||||||
server.device_id(),
|
server.device_id(),
|
||||||
Identifier::random(),
|
Identifier::random(),
|
||||||
Identifier::default(),
|
Identifier::default(),
|
||||||
);
|
)))?;
|
||||||
std::fs::write("./packet", Into::<Vec<u8>>::into(p))?;
|
std::fs::write("./ping_packet", Into::<Vec<u8>>::into(NodeManagementCommand::Ping.to_packet(
|
||||||
|
Identifier::from(0x000000AA),
|
||||||
|
server.device_id(),
|
||||||
|
Identifier::random(),
|
||||||
|
Identifier::default(),
|
||||||
|
)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match server.recv_packet().await {
|
match server.recv_packet().await {
|
||||||
(Ok(p), Some(s)) => {
|
(Ok(p), Some(s)) => {
|
||||||
if p.dest != server.device_id() {
|
if devices.get_device(p.src).is_none() {
|
||||||
if let Some(d) = server.devices().get(&p.dest) {
|
if let PacketData::NodeManagement(NodeManagementCommand::RegisterNode { device_id }) = p.data {
|
||||||
let _ = &server.send(d.socket_addr, p).await;
|
let device_id = devices.add_device_auto(s, Some(device_id));
|
||||||
}
|
let _ = server.send(s, NodeManagementCommand::RegisterNode {
|
||||||
|
device_id
|
||||||
|
}.to_packet(
|
||||||
|
server.device_id(),
|
||||||
|
device_id,
|
||||||
|
Identifier::random(),
|
||||||
|
p.packet_id
|
||||||
|
)).await;
|
||||||
|
} else {
|
||||||
|
warn!("{s} is unregistered and tried to send a packet {p:#?}.");
|
||||||
|
let _ = server.send(s, prelude::quick_err::errc_not_registered(
|
||||||
|
server.device_id(),
|
||||||
|
p.src,
|
||||||
|
p.packet_id
|
||||||
|
)).await;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
match p.data {
|
match p.data {
|
||||||
PacketData::NodeManagement(NodeManagementCommand::Ping) => {
|
PacketData::NodeManagement(NodeManagementCommand::Ping) => {
|
||||||
trace!("ping from: [{s}->{}]", p.src);
|
trace!("ping from: [{s}->{}]", p.src);
|
||||||
|
@ -53,7 +80,7 @@ impl NodeType {
|
||||||
p.packet_id,
|
p.packet_id,
|
||||||
)).await;
|
)).await;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => warn!("dropped packet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Err(e), Some(source)) => {
|
(Err(e), Some(source)) => {
|
|
@ -5,20 +5,15 @@ use std::net::SocketAddr;
|
||||||
use std::io;
|
use std::io;
|
||||||
use domo_proto::packet::{FULL_PACKET_SIZE, Packet};
|
use domo_proto::packet::{FULL_PACKET_SIZE, Packet};
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use log::error;
|
use log::{error, trace};
|
||||||
|
use domo_proto::data_types::DataType;
|
||||||
use domo_proto::packet::raw_packet::RawPacket;
|
use domo_proto::packet::raw_packet::RawPacket;
|
||||||
|
|
||||||
pub struct Device {
|
|
||||||
/// Device identifier
|
|
||||||
pub device_id: Identifier,
|
|
||||||
/// Device socket address
|
|
||||||
pub socket_addr: SocketAddr,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
sock: UdpSocket,
|
sock: UdpSocket,
|
||||||
device_id: Identifier,
|
device_id: Identifier,
|
||||||
devices: HashMap<Identifier, Device>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
|
@ -26,7 +21,6 @@ impl Server {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
sock: UdpSocket::bind(socket_addr).await?,
|
sock: UdpSocket::bind(socket_addr).await?,
|
||||||
device_id: device_id.unwrap_or(Identifier::random()),
|
device_id: device_id.unwrap_or(Identifier::random()),
|
||||||
devices: HashMap::new()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +32,8 @@ impl Server {
|
||||||
Err(e) => return (Err(e), None)
|
Err(e) => return (Err(e), None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
trace!("received: {} bytes from {}", size, socket_addr);
|
||||||
|
|
||||||
(
|
(
|
||||||
Packet::try_from(buf[..size].to_vec()),
|
Packet::try_from(buf[..size].to_vec()),
|
||||||
Some(socket_addr)
|
Some(socket_addr)
|
||||||
|
@ -59,8 +55,4 @@ impl Server {
|
||||||
pub fn sock(&self) -> &UdpSocket {
|
pub fn sock(&self) -> &UdpSocket {
|
||||||
&self.sock
|
&self.sock
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn devices(&self) -> &HashMap<Identifier, Device> {
|
|
||||||
&self.devices
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,4 +39,16 @@ pub mod quick_err {
|
||||||
reply_to
|
reply_to
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn errc_not_registered(src: Identifier, dest: Identifier, reply_to: Identifier) -> Packet {
|
||||||
|
NodeManagementCommand::Error {
|
||||||
|
error_code: NodeManagementError::errc_not_registered.into(),
|
||||||
|
metadata: "this node is not registered".to_string().into_bytes()
|
||||||
|
}.to_packet(
|
||||||
|
src,
|
||||||
|
dest,
|
||||||
|
Identifier::random(),
|
||||||
|
reply_to
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
36
domo_node/test.py
Normal file
36
domo_node/test.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import socket
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Create a UDP socket
|
||||||
|
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
|
||||||
|
def send_file_contents(filename):
|
||||||
|
try:
|
||||||
|
print(f"reading {filename}...")
|
||||||
|
with open(filename, 'rb') as file:
|
||||||
|
file_contents = file.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"File '{filename}' not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"sending content len: {len(file_contents)}...")
|
||||||
|
# Send the file contents to the UDP socket
|
||||||
|
udp_socket.sendto(file_contents, ('0.0.0.0', 4480))
|
||||||
|
|
||||||
|
print("waiting for response...")
|
||||||
|
# Receive and display the response
|
||||||
|
response, server_address = udp_socket.recvfrom(1024)
|
||||||
|
print(f"Received response from {server_address}:")
|
||||||
|
print(response.hex())
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
filename = input("Enter a file name (or 'exit' to quit): ")
|
||||||
|
if filename == 'exit':
|
||||||
|
break
|
||||||
|
send_file_contents(filename)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nExiting the program.")
|
||||||
|
finally:
|
||||||
|
udp_socket.close()
|
|
@ -5,7 +5,9 @@ impl Into<Vec<u8>> for NodeManagementCommand {
|
||||||
fn into(self) -> Vec<u8> {
|
fn into(self) -> Vec<u8> {
|
||||||
match self {
|
match self {
|
||||||
NodeManagementCommand::Ping => vec![],
|
NodeManagementCommand::Ping => vec![],
|
||||||
NodeManagementCommand::RegisterNode { device_id } => device_id.bytes.to_vec(),
|
NodeManagementCommand::RegisterNode { device_id } => {
|
||||||
|
vec![device_id.bytes[0], device_id.bytes[1], device_id.bytes[2], device_id.bytes[3]]
|
||||||
|
},
|
||||||
NodeManagementCommand::RemoveNode => vec![],
|
NodeManagementCommand::RemoveNode => vec![],
|
||||||
NodeManagementCommand::RegisterProperty { property_name, data_type, read_only } => {
|
NodeManagementCommand::RegisterProperty { property_name, data_type, read_only } => {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
|
|
|
@ -31,7 +31,9 @@ impl PacketData {
|
||||||
impl TryFrom<RawPacket> for PacketData {
|
impl TryFrom<RawPacket> for PacketData {
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
fn try_from(raw_packet: RawPacket) -> io::Result<Self> {
|
fn try_from(raw_packet: RawPacket) -> io::Result<Self> {
|
||||||
match raw_packet.command {
|
match {
|
||||||
|
raw_packet.command >> 4
|
||||||
|
} {
|
||||||
0x0 => Ok(PacketData::NodeManagement(NodeManagementCommand::try_from(raw_packet)?)),
|
0x0 => Ok(PacketData::NodeManagement(NodeManagementCommand::try_from(raw_packet)?)),
|
||||||
0x1 => Ok(PacketData::PropertyControl(PropertyControlCommand::try_from(raw_packet)?)),
|
0x1 => Ok(PacketData::PropertyControl(PropertyControlCommand::try_from(raw_packet)?)),
|
||||||
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "command group is unsupported"))
|
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "command group is unsupported"))
|
||||||
|
|
|
@ -40,6 +40,10 @@ impl Into<Packet> for RawPacket {
|
||||||
reply_to: Identifier::from(self.reply_to),
|
reply_to: Identifier::from(self.reply_to),
|
||||||
command: self.command,
|
command: self.command,
|
||||||
data: PacketData::try_from(self.clone())
|
data: PacketData::try_from(self.clone())
|
||||||
|
.map_err(|e| {
|
||||||
|
println!("{}", e);
|
||||||
|
e
|
||||||
|
})
|
||||||
.unwrap_or(PacketData::Raw(self.data)),
|
.unwrap_or(PacketData::Raw(self.data)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,11 @@ impl TryFrom<Vec<u8>> for RawPacket {
|
||||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "Can't parse data into RawPacket"))
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "Can't parse data into RawPacket"))
|
||||||
}
|
}
|
||||||
let data_length = (((data[0x12] as u16) << 8) | data[0x13] as u16) as usize;
|
let data_length = (((data[0x12] as u16) << 8) | data[0x13] as u16) as usize;
|
||||||
|
println!("LENGTH {data_length}");
|
||||||
if data.len() < 0x14 + data_length {
|
if data.len() < 0x14 + data_length {
|
||||||
return Err(io::Error::new(io::ErrorKind::InvalidData, "Can't parse data into RawPacket"))
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "Can't parse data into RawPacket"))
|
||||||
}
|
}
|
||||||
let checksum = as_u32_be(data[(data.len() - 4)..].as_ref());
|
let checksum = as_u32_be(data[(0x14 + data_length)..].as_ref());
|
||||||
let built_checksum = crc32fast::hash(data[..(data.len() - 4)].as_ref());
|
let built_checksum = crc32fast::hash(data[..(data.len() - 4)].as_ref());
|
||||||
if checksum != built_checksum {
|
if checksum != built_checksum {
|
||||||
return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Checksum does not match {checksum:X?} != {built_checksum:X?}")))
|
return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Checksum does not match {checksum:X?} != {built_checksum:X?}")))
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
|
|
||||||
import socket, zlib
|
|
||||||
|
|
||||||
HOST = "127.0.0.1" # Standard loopback interface address (localhost)
|
|
||||||
PORT = 2000 # Port to listen on (non-privileged ports are > 1023)
|
|
||||||
|
|
||||||
def calculate_crc(data):
|
|
||||||
# Calculate the CRC32 checksum of the data
|
|
||||||
crc = zlib.crc32(data)
|
|
||||||
# Convert the CRC32 value to a 4-byte big-endian byte array
|
|
||||||
crc_bytes = crc.to_bytes(4, byteorder='big')
|
|
||||||
return crc_bytes
|
|
||||||
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
||||||
s.bind((HOST, PORT))
|
|
||||||
s.listen()
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
conn, addr = s.accept()
|
|
||||||
with conn:
|
|
||||||
print(f"Connected by {addr}")
|
|
||||||
while True:
|
|
||||||
data = conn.recv(1024)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
print(f'RECV: {data.hex()} [{len(data)}]')
|
|
||||||
if data[0x11] == 0x01:
|
|
||||||
pckt = bytearray([0x01])
|
|
||||||
pckt.extend([0x00, 0x00, 0x00, 0x00]) # src
|
|
||||||
pckt.extend([0x00, 0x00, 0x00, 0xFF]) # dest
|
|
||||||
pckt.extend([0x00, 0x00, 0x00, 0x00]) # packet_id
|
|
||||||
pckt.extend(data[0x09:0x0D]) # reply_to
|
|
||||||
pckt.extend([0x01]) # command
|
|
||||||
pckt.extend([0x00, 0x04]) # data_length
|
|
||||||
pckt.extend([0x00, 0x00, 0x00, 0xFF])
|
|
||||||
|
|
||||||
# Calculate CRC for the received data
|
|
||||||
crc = calculate_crc(pckt)
|
|
||||||
# Append the CRC value to the data
|
|
||||||
data_with_crc = pckt + crc
|
|
||||||
# Send the modified data (with CRC) back to the client
|
|
||||||
conn.sendall(data_with_crc)
|
|
||||||
print(f'SEND: {data_with_crc.hex()} [{len(data_with_crc)}]')
|
|
||||||
except:
|
|
||||||
s.close()
|
|
Loading…
Reference in a new issue