1#![crate_name = "http2byond"]
2
3use std::io::prelude::*;
4use std::net::{SocketAddr,TcpStream};
5use bytes::{Bytes, BytesMut, Buf, BufMut};
6use std::time::Duration;
7
8pub enum ByondTopicValue {
11 None,
12 String(String),
13 Number(f32),
14}
15
16pub fn send_byond(target: &SocketAddr, topic: &str) -> std::io::Result<ByondTopicValue> {
39 let mut stream = TcpStream::connect(target)?;
40 stream.set_read_timeout(Some(Duration::new(5, 0)))?;
41
42 let topic_bytes = topic.as_bytes();
43
44 let mut buf = BytesMut::with_capacity(1024);
45 buf.put_u16(0x0083);
47
48 buf.put_u16(topic_bytes.len() as u16 + 6);
50
51 buf.put_u32(0x0);
53 buf.put_u8(0x0);
54
55 buf.put(topic_bytes);
57
58 buf.put_u8(0x0);
60
61 println!("{:02X?}", &buf[..]);
62
63 stream.write(&buf)?;
64
65 let mut recv_buf = [0; 1024];
66
67 let bytes_read = stream.read(&mut recv_buf)?;
68
69 if bytes_read == 0 {
70 return Ok(ByondTopicValue::None);
71 }
72
73 let mut recv_buf = Bytes::from(Vec::from(recv_buf));
74
75 if recv_buf.get_u16() == 0x0083 {
76 let mut size = recv_buf.get_u16() - 1;
77 let data_type = recv_buf.get_u8();
78
79 let ret = match data_type {
80 0x2a => ByondTopicValue::Number(recv_buf.get_f32_le()),
81 0x06 => {
82 let mut str = String::new();
83 while size > 0 {
84 str.push(recv_buf.get_u8() as char);
85 size -= 1;
86 }
87 ByondTopicValue::String(str)
88 },
89 _ => ByondTopicValue::None,
90 };
91
92 return Ok(ret)
93 }
94
95 Ok(ByondTopicValue::None)
96}
97
98#[test]
99fn it_works() {
100 let res = send_byond(&SocketAddr::from(([127, 0, 0, 1], 1337)), "?status");
101 match res {
102 Err(x) => panic!("Error from send_byond {}", x),
103 Ok(wrapper) => {
104 match wrapper {
105 ByondTopicValue::None => println!("Returned NONE"),
106 ByondTopicValue::String(str) => println!("Returned string {}", str),
107 ByondTopicValue::Number(num) => println!("Returned f32 {}", num)
108 }
109 }
110 }
111}