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