Initial commit.
This commit is contained in:
commit
5fc381f7d6
9 changed files with 372 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
internal.log
|
||||||
|
log
|
||||||
|
journal.md
|
||||||
|
test.log
|
||||||
|
rust/target/*
|
17
ErrorLog
Normal file
17
ErrorLog
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
sm exts load tf2p
|
||||||
|
>>> TF2P loaded! me = IExtension(0x19de8ae0), sys = IShareSys(0xe9d604c4), late = true
|
||||||
|
[SM] Loaded extension tf2p.ext.so successfully.
|
||||||
|
sm plugins unload tf2p-network-control
|
||||||
|
[SM] Plugin tf2p-network-control.smx unloaded successfully.
|
||||||
|
sm plugins load tf2p-network-control
|
||||||
|
Got ip "192.168.178.162" and Ports 27015
|
||||||
|
thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/lib.rs:181:9
|
||||||
|
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||||
|
L 04/03/2020 - 19:43:01: [SM] Exception reported: native panicked: called `Option::unwrap()` on a `None` value
|
||||||
|
L 04/03/2020 - 19:43:01: [SM] Blaming: tf2p-network-control.smx
|
||||||
|
L 04/03/2020 - 19:43:01: [SM] Call stack trace:
|
||||||
|
L 04/03/2020 - 19:43:01: [SM] [0] Rust_Start_Manager
|
||||||
|
L 04/03/2020 - 19:43:01: [SM] [1] Line 22, tf2p-network-control.sp::OnPluginStart
|
||||||
|
[SM] Plugin tf2p-network-control.smx failed to load: Error detected in plugin startup (see error logs).
|
||||||
|
thread '<unnamed>' panicked at 'Box<Any>', src/lib.rs:107:27
|
||||||
|
thread '<unnamed>' panicked at 'Box<Any>', src/socks.rs:12:23
|
93
rust/Cargo.lock
generated
Normal file
93
rust/Cargo.lock
generated
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "c_str_macro"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2e08268d37bbcbf98f70312c449a35763d3f85beafbedbb4e28b4c438e2b5bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flume"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa697b56a44fc5e18d0892e8e01e0c5241ff8fd8bfd936d9af5aea2e113fbda0"
|
||||||
|
dependencies = [
|
||||||
|
"spin",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sm-ext"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcdcd9d45b7f6d92ab1fa4dc1a9090d59ccdceab4f94aa51991c3ef0d73c8fda"
|
||||||
|
dependencies = [
|
||||||
|
"c_str_macro",
|
||||||
|
"libc",
|
||||||
|
"sm-ext-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sm-ext-derive"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75e96380b9fa81d50460fa1240990754e7f5766a74ffa5791f0cf43f50e56fc2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spin"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tf2p"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"flume",
|
||||||
|
"sm-ext",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
12
rust/Cargo.toml
Normal file
12
rust/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "tf2p"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["TheLie0 <wf7za0XoHyYXVEkOeNu8>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
sm-ext = "0.3.0"
|
||||||
|
flume = "0.5.1"
|
200
rust/src/lib.rs
Normal file
200
rust/src/lib.rs
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
use sm_ext::{cell_t, register_natives, IExtension, IExtensionInterface, IShareSys, SMExtension, TryIntoPlugin, HandleError, HandleId, HandleType};
|
||||||
|
use std::thread;
|
||||||
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
// use std::rc::Rc; Using Rc like it's in the example threw an Error
|
||||||
|
|
||||||
|
pub mod test;
|
||||||
|
pub mod socks;
|
||||||
|
|
||||||
|
use sm_ext::{native, IPluginContext};
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
|
use flume;
|
||||||
|
|
||||||
|
/// The network plugin entrypoint.
|
||||||
|
#[native]
|
||||||
|
fn start_manager(_ctx: &IPluginContext, ip: &CStr, port1: i32) -> NMSender {
|
||||||
|
|
||||||
|
println!("Got ip {:?} and Ports {}", ip, port1);
|
||||||
|
let serv = format!("{}:{}", ip.to_str().unwrap(), port1).parse::<SocketAddr>().expect("Unable to parse socket address");
|
||||||
|
|
||||||
|
let mut sock = serv.clone();
|
||||||
|
|
||||||
|
sock.set_port(27419);
|
||||||
|
|
||||||
|
// bind sockets
|
||||||
|
let sock_r= UdpSocket::bind(sock).unwrap();
|
||||||
|
let sock_w = sock_r.try_clone().unwrap();
|
||||||
|
|
||||||
|
// Create flume channels
|
||||||
|
let (tx_s2m, rx_s2m) = flume::unbounded();
|
||||||
|
let (tx_m2s, rx_m2s) = flume::unbounded();
|
||||||
|
|
||||||
|
//create controller channel
|
||||||
|
let (tx_c, rx_c) = flume::unbounded();
|
||||||
|
|
||||||
|
// Spawn listen thread
|
||||||
|
thread::spawn(move || {
|
||||||
|
socks::usock_to_chan(sock_r, tx_s2m).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spawn send thread
|
||||||
|
thread::spawn(move || {
|
||||||
|
socks::chan_to_usock(rx_m2s, sock_w).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spawn manager thread
|
||||||
|
thread::spawn(move || {
|
||||||
|
manager(rx_c, rx_s2m, tx_m2s, serv).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
NMSender::new(tx_c)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The network manager function.
|
||||||
|
/// It handles the incoming requests and sends the corresponding answers
|
||||||
|
fn manager<'a> (controller: flume::Receiver<NMCommand>, input: flume::Receiver<(Vec<u8>, SocketAddr)>, output: flume::Sender<(Vec<u8>, SocketAddr)>, serv_addr: SocketAddr) -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
|
let mut cl_ip: Option<SocketAddr> = None;
|
||||||
|
let mut addr_queue = VecDeque::new();
|
||||||
|
|
||||||
|
let conns: [Option<SocketAddr>; 3];
|
||||||
|
|
||||||
|
// This is the String "Source Engine Query" in binary form
|
||||||
|
let cliet_query = vec!(0xff, 0xff, 0xff, 0xff, 0x54, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x20, 0x51, 0x75, 0x65, 0x72, 0x79, 0x00);
|
||||||
|
|
||||||
|
'main: loop {
|
||||||
|
|
||||||
|
// Get game info for cache
|
||||||
|
output.send((cliet_query.clone(), serv_addr)).unwrap();
|
||||||
|
let game_info = match input.recv() {
|
||||||
|
Ok((buf, src)) => {
|
||||||
|
let search = serv_addr.port().to_le_bytes();
|
||||||
|
let replace = (27419 as u16).to_le_bytes();
|
||||||
|
|
||||||
|
if src == serv_addr {
|
||||||
|
let mut buf = buf;
|
||||||
|
for i in 0..buf.len()-1 {
|
||||||
|
if buf[i..i+2] == search {
|
||||||
|
buf[i] = replace[0];
|
||||||
|
buf[i+1] = replace[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf
|
||||||
|
} else {
|
||||||
|
panic!("Expected query answer from server, got message from {:?}", src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => panic!(e),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send cached game info on query and pass any other request to server
|
||||||
|
'inner1: loop {
|
||||||
|
|
||||||
|
//check for controller input
|
||||||
|
//TODO: rewrite this so it doesn't block
|
||||||
|
match controller.recv() {
|
||||||
|
Ok(comm) => {
|
||||||
|
match comm {
|
||||||
|
NMCommand::Kill => break 'main,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => panic!(e),
|
||||||
|
}
|
||||||
|
|
||||||
|
match input.recv() {
|
||||||
|
Ok((buf, source)) => {
|
||||||
|
if source == serv_addr {
|
||||||
|
match addr_queue.pop_front() {
|
||||||
|
Some(ip) => {
|
||||||
|
output.send((buf.clone(), ip)).unwrap();
|
||||||
|
}
|
||||||
|
None => println!("No clients in queue."),
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if buf[0 .. cliet_query.len()] == cliet_query[..] {
|
||||||
|
output.send((game_info.clone(), source)).unwrap();
|
||||||
|
}else {
|
||||||
|
output.send((buf.clone(), serv_addr)).unwrap();
|
||||||
|
addr_queue.push_back(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => panic!(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Get game info again
|
||||||
|
|
||||||
|
//TODO: Actual p2p communication
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NMCommand{
|
||||||
|
Connect(u8, SocketAddr),
|
||||||
|
Kill
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct NMSender(flume::Sender<NMCommand>);
|
||||||
|
|
||||||
|
impl<'ctx> TryIntoPlugin<'ctx> for NMSender {
|
||||||
|
type Error = HandleError;
|
||||||
|
|
||||||
|
fn try_into_plugin(self, ctx: &'ctx IPluginContext) -> Result<cell_t, Self::Error> {
|
||||||
|
let object = RefCell::new(self);
|
||||||
|
let handle = Tf2pNetworking::handle_type().create_handle(object, ctx.get_identity())?;
|
||||||
|
|
||||||
|
Ok(handle.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NMSender {
|
||||||
|
|
||||||
|
fn new(s: flume::Sender<NMCommand>) -> Self {
|
||||||
|
Self(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive (Default, SMExtension)]
|
||||||
|
#[extension(name = "TF2P", description = "Decentralize all the things!")]
|
||||||
|
pub struct Tf2pNetworking{
|
||||||
|
handle_type: Option<HandleType<RefCell<NMSender>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tf2pNetworking {
|
||||||
|
|
||||||
|
fn get() -> &'static Self {
|
||||||
|
EXTENSION_GLOBAL.with(|ext| unsafe { &(*ext.borrow().unwrap()).delegate })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_type() -> &'static HandleType<RefCell<NMSender>> {
|
||||||
|
Self::get().handle_type.as_ref().unwrap() // This line panics
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IExtensionInterface for Tf2pNetworking {
|
||||||
|
fn on_extension_load(&mut self, myself: IExtension, sys: IShareSys, late: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
println!(">>> TF2P loaded! me = {:?}, sys = {:?}, late = {:?}", myself, sys, late);
|
||||||
|
|
||||||
|
register_natives!(
|
||||||
|
&sys,
|
||||||
|
&myself,
|
||||||
|
[
|
||||||
|
("Rust_Start_Manager", start_manager),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
34
rust/src/socks.rs
Normal file
34
rust/src/socks.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use std::net::{UdpSocket, SocketAddr};
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use flume;
|
||||||
|
|
||||||
|
/// Sends buffer messages from a mpsc channel to an udp socket.
|
||||||
|
pub fn chan_to_usock(input: flume::Receiver<(Vec<u8>, SocketAddr)>, output: UdpSocket) -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match input.recv() {
|
||||||
|
Ok((buf, target)) => output.send_to(&buf, &target)?,
|
||||||
|
Err(e) => panic!(e),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends buffer messages from an udp socket to a mpsc channel.
|
||||||
|
pub fn usock_to_chan(input: UdpSocket, output: flume::Sender<(Vec<u8>, SocketAddr)>) -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
|
let mut buf = [0; 2048];
|
||||||
|
let mut tup;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
{
|
||||||
|
tup = input.recv_from(&mut buf).unwrap();
|
||||||
|
}
|
||||||
|
match output.send((buf[0..tup.0 + 1].to_vec(), tup.1)) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(e) => panic!(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
rust/src/test.rs
Normal file
9
rust/src/test.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use std::net::UdpSocket;
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
/// Udp ping helper function
|
||||||
|
pub fn test_ping(ip: String) -> Result<(), Box<dyn Error>> {
|
||||||
|
let socket = UdpSocket::bind("127.0.0.1:6969")?;
|
||||||
|
socket.send_to("ping".as_bytes(), ip)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
1
sourcepawn/include/tf2p.inc
Symbolic link
1
sourcepawn/include/tf2p.inc
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/mnt/disk3/TF2DS/tf/addons/sourcemod/scripting/include//tf2p.inc
|
1
sourcepawn/tf2p-network-control.sp
Symbolic link
1
sourcepawn/tf2p-network-control.sp
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
/mnt/disk3/TF2DS/tf/addons/sourcemod/scripting/tf2p-network-control.sp
|
Loading…
Reference in a new issue