Compare commits

...

2 commits
master ... dev

Author SHA1 Message Date
7ae296bf0e Undo me 2021-08-02 23:26:27 +02:00
TheLie0
cb50318a5f Got closer to completion and split up the files. 2020-04-20 15:29:24 +02:00
118 changed files with 357 additions and 113 deletions

BIN
lo Normal file

Binary file not shown.

BIN
new.log Normal file

Binary file not shown.

18
rust/Cargo.lock generated
View file

@ -17,24 +17,24 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.67"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
[[package]]
name = "proc-macro2"
version = "1.0.9"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.2"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
dependencies = [
"proc-macro2",
]
@ -69,9 +69,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "syn"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
dependencies = [
"proc-macro2",
"quote",
@ -79,7 +79,7 @@ dependencies = [
]
[[package]]
name = "tf2p"
name = "tf2p-network"
version = "0.1.0"
dependencies = [
"flume",

View file

@ -1,5 +1,5 @@
[package]
name = "tf2p"
name = "tf2p-network"
version = "0.1.0"
authors = ["TheLie0 <wf7za0XoHyYXVEkOeNu8>"]
edition = "2018"

3
rust/build_and_run.sh Normal file
View file

@ -0,0 +1,3 @@
cargo build --all --all-targets --target=i686-unknown-linux-gnu &&
cp target/i686-unknown-linux-gnu/debug/libtf2p_network.so /mnt/disk3/TF2DS/tf/addons/sourcemod/extensions/tf2p-network.ext.so &&
/mnt/disk3/TF2DS/srcds_run +map ctf_2fort

View file

@ -1,19 +1,29 @@
use sm_ext::{cell_t, register_natives, IExtension, IExtensionInterface, IShareSys, SMExtension, TryIntoPlugin, HandleError, HandleId, HandleType};
use sm_ext::*;
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};
mod socks;
mod netman;
use std::ffi::CStr;
use flume;
#[forwards]
struct Tf2pNetworkingForwards {
#[global_forward("OnConnectionRequest", ExecType::Single)]
on_con_req: fn(ip: &CStr) -> i32,
}
fn forward_wrapper(ip: &CStr) -> Result<i32, sm_ext::SPError> {
let result = Tf2pNetworkingForwards::on_con_req(|fwd| fwd.execute(ip))?;
Ok(result)
}
/// The network plugin entrypoint.
#[native]
fn start_manager(_ctx: &IPluginContext, ip: &CStr, port1: i32) -> NMSender {
@ -48,103 +58,14 @@ fn start_manager(_ctx: &IPluginContext, ip: &CStr, port1: i32) -> NMSender {
// Spawn manager thread
thread::spawn(move || {
manager(rx_c, rx_s2m, tx_m2s, serv).unwrap();
netman::manager(rx_s2m, tx_m2s, forward_wrapper, 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>);
struct NMSender(flume::Sender<netman::NMMessage>);
impl<'ctx> TryIntoPlugin<'ctx> for NMSender {
type Error = HandleError;
@ -159,7 +80,7 @@ impl<'ctx> TryIntoPlugin<'ctx> for NMSender {
impl NMSender {
fn new(s: flume::Sender<NMCommand>) -> Self {
fn new(s: flume::Sender<netman::NMMessage>) -> Self {
Self(s)
}
@ -174,7 +95,12 @@ pub struct Tf2pNetworking{
impl Tf2pNetworking {
fn get() -> &'static Self {
EXTENSION_GLOBAL.with(|ext| unsafe { &(*ext.borrow().unwrap()).delegate })
EXTENSION_GLOBAL.with(|ext| unsafe {
&(*(match *ext.borrow(){
Some(e) => e,
None => panic!("Couldn't find myself"),
})).delegate
})
}
fn handle_type() -> &'static HandleType<RefCell<NMSender>> {
@ -185,7 +111,17 @@ impl Tf2pNetworking {
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);
println!(">>> TF2P loaded! me = {:?}, sys = {:?}, late = {:?}", myself, sys, late);
let handlesys: IHandleSys = sys.request_interface(&myself)?;
println!(">>> Got interface: {:?} v{:?}", handlesys.get_interface_name(), handlesys.get_interface_version());
self.handle_type = Some(handlesys.create_type("NMSender", myself.get_identity())?);
let forward_manager: IForwardManager = sys.request_interface(&myself)?;
println!(">>> Got interface: {:?} v{:?}", forward_manager.get_interface_name(), forward_manager.get_interface_version());
Tf2pNetworkingForwards::register(&forward_manager)?;
register_natives!(
&sys,
@ -197,4 +133,9 @@ impl IExtensionInterface for Tf2pNetworking {
Ok(())
}
fn on_extension_unload(&mut self) {
Tf2pNetworkingForwards::unregister();
}
}

202
rust/src/netman.rs Normal file
View file

@ -0,0 +1,202 @@
use std::net::SocketAddr;
use std::error::Error;
use std::collections::VecDeque;
use std::ffi::CStr;
// use crate::Tf2pNetworkingForwards;
use flume;
pub enum NMMessage{
Connect(u8, SocketAddr),
Ping(SocketAddr),
UDPMessage(Vec<u8>, SocketAddr),
Kill
}
fn check_if_in_peer_ips (cl_ip: SocketAddr, peer_ips: &[Option<SocketAddr>]) -> bool {
let mut answer = false;
for ip_opt in peer_ips {
match ip_opt {
Some(ip) => {
if ip.ip() == cl_ip.ip() {
answer == true;
}
}
_ => ()
}
}
return answer;
}
/// The network manager function.
/// It handles the incoming requests and sends the corresponding answers
pub fn manager<'a> (input: flume::Receiver<NMMessage>, output: flume::Sender<(Vec<u8>, SocketAddr)>, forward: fn(&CStr) -> Result<i32, sm_ext::SPError>, serv_addr: SocketAddr) -> Result<(), Box<dyn Error>> {
let mut cl_ip: Option<SocketAddr> = None;
let mut addr_queue = VecDeque::new();
let mut conns = [None, None, None];
// 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
let mut game_info = None;
let search = serv_addr.port().to_le_bytes();
let replace = (27419 as u16).to_le_bytes();
output.send((cliet_query.clone(), serv_addr)).unwrap();
while game_info == None {
match input.recv() {
Ok(m) => {
match m {
NMMessage::UDPMessage(buf, src) => {
if src == serv_addr {
let buf = &mut *buf.clone();
for i in 0..buf.len()-1{
if buf[i..i+2] == search {
println!("Port replaced.");
buf[i] = replace[0];
buf[i+1] = replace[1];
}
}
game_info = Some(Vec::from(buf));
} else {
panic!("Expected query answer from server, got message from {:?}", src);
}
}
NMMessage::Kill => break 'main,
_ => ()
}
}
Err(e) => panic!(e),
}
};
// Send cached game info on query and pass any other request to server
// Break when player data has been received
let mut player_data = [None, None];
'inner1: loop {
match input.recv() {
Ok(m) => {
match m {
NMMessage::UDPMessage(buf, src) => {
if src == serv_addr {
match addr_queue.pop_front() {
Some(ip) => {
output.send((buf.clone(), ip)).unwrap();
}
None => println!("No clients in queue."),
}
}else {
if buf.len() <= cliet_query.len() && buf[..] == cliet_query[..buf.len()] ||
buf.len() > cliet_query.len() && buf[..cliet_query.len()] == cliet_query[..] {
output.send((game_info.clone().unwrap(), src)).unwrap();
}else if buf.len() >= 256 && buf[0..6] == [0xff, 0xff, 0xff, 0xff, 0x6b, 0x18] {
cl_ip = Some(src);
player_data[0] = Some(buf);
output.send((player_data[0].clone().unwrap(), serv_addr)).unwrap();
println!("Got player Data pt 1.");
// This loop is activated when a player starts sending theur data and
// breaks the outer loop when the transmission is complete.
'even_more_inner: loop {
match input.recv() {
Ok(m) => {
match m {
NMMessage::UDPMessage(buf, src) => {
if src == serv_addr {
output.send((buf.clone(), cl_ip.unwrap())).unwrap();
} else if src == cl_ip.unwrap() {
if buf.len() >= 256 {
player_data[1] = Some(buf);
output.send((player_data[1].clone().unwrap(), serv_addr)).unwrap();
println!("Got player Data pt 2.");
break 'even_more_inner;
}
}
},
NMMessage::Kill => break 'main,
_ => {},
}
},
Err(e) => panic!(e),
}
}
break 'inner1;
}else {
output.send((buf.clone(), serv_addr)).unwrap();
addr_queue.push_back(src);
}
}
},
NMMessage::Kill => break 'main,
_ => {},
}
},
Err(e) => panic!(e),
}
}
// Exchange game data with peers and send updates to client.
'inner2: loop {
match input.recv() {
Ok(m) => {
match m {
NMMessage::UDPMessage(buf, src) => {
if src == serv_addr { // from server?
output.send((buf, cl_ip.unwrap())); // send to client
} else if check_if_in_peer_ips(src, &conns) { // from peer?
// handle request (quit, peers, gameinfo)
// send to cliet port (forward)
} else { // else
if buf == "TF2P?".as_bytes() {// handshake
output.send((Vec::from("Hey Ho!".as_bytes()), src));
}
else if buf == "Connect?".as_bytes() {
match forward(CStr::from_bytes_with_nul(src.ip().to_string()[..].as_bytes())?) {
Ok(i) => {
if i < 3 {
conns[i as usize] = Some(src);
// 'Ack ServPort CliPort' -> src
output.send((Vec::from(format!("Ack {:05}", serv_addr.port()).as_bytes()), src));
} else {
output.send((Vec::from("No".as_bytes()), src));
}
},
_ => (),
}
}
else if buf == "".as_bytes() { // Ack, SPort
// add to list TODO: Check internal state of place and validity
output.send((Vec::from("QInfo?".as_bytes()), src));
}
}
},
NMMessage::Connect(i, addr) => {
// TODO: Create internal state to check place and validity
output.send((Vec::from("Connect?".as_bytes()), addr));
},
NMMessage::Ping(addr) => {
output.send((Vec::from("TF2P?".as_bytes()), addr));
}
NMMessage::Kill => break 'main,
}
}
Err(e) => panic!(e),
}
}
}
Ok(())
}

View file

@ -1,6 +1,8 @@
use std::net::{UdpSocket, SocketAddr};
use std::error::Error;
use crate::netman::NMMessage;
use flume;
/// Sends buffer messages from a mpsc channel to an udp socket.
@ -16,7 +18,7 @@ pub fn chan_to_usock(input: flume::Receiver<(Vec<u8>, SocketAddr)>, output: UdpS
}
/// 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>> {
pub fn usock_to_chan(input: UdpSocket, output: flume::Sender<NMMessage>) -> Result<(), Box<dyn Error>> {
let mut buf = [0; 2048];
let mut tup;
@ -25,9 +27,12 @@ pub fn usock_to_chan(input: UdpSocket, output: flume::Sender<(Vec<u8>, SocketAdd
{
tup = input.recv_from(&mut buf).unwrap();
}
match output.send((buf[0..tup.0 + 1].to_vec(), tup.1)) {
match output.send(NMMessage::UDPMessage(buf[0..tup.0 + 1].to_vec(), tup.1)) {
Ok(s) => s,
Err(e) => panic!(e)
Err(e) => {
println!("Whoops");
panic!(e)
}
}
}
}

6
tests/Cargo.lock generated Normal file
View file

@ -0,0 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "tests"
version = "0.1.0"

9
tests/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "tests"
version = "0.1.0"
authors = ["TheLie0 <wf7za0XoHyYXVEkOeNu8>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

41
tests/src/main.rs Normal file
View file

@ -0,0 +1,41 @@
use std::env;
use std::net::{UdpSocket, SocketAddr};
fn main() {
println!("Hello, world!");
let args: Vec<String> = env::args().collect();
let mut server_adress = None;
for i in 0..args.len()-1 {
if args[i] == "-s" {
server_adress = Some(args[i + 1].parse::<SocketAddr>()
.expect("Unable to parse output socket address"));
}
}
let server_message = [0xff, 0xff, 0xff, 0xff, 0x41, 0x33, 0x49, 0x4f, 0x5a,
0x7c, 0x71, 0x34, 0x2d, 0xf9, 0x23, 0x30, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0xc0, 0x56, 0x25, 0x42, 0x38, 0x40, 0x01, 0x01, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x00];
let server_socket = UdpSocket::bind("127.0.0.1:27123")
.expect("Could not bind to 127.0.0.1:27123.");
// Connect to client port
match server_adress {
Some(a) => server_socket.connect(a).expect("Couldn't connect to server."),
None => panic!("No Server adress provided!")
}
server_socket.send(& server_message).expect("Send failed.");
// print all traffic from cl
loop{
let mut output = [0; 128];
server_socket.recv(&mut output).unwrap();
}
}

View file

@ -0,0 +1 @@
{"rustc_fingerprint":1683364760131821644,"outputs":{"1164083562126845933":["rustc 1.44.0 (49cae5576 2020-06-01)\nbinary: rustc\ncommit-hash: 49cae55760da0a43428eba73abcb659bb70cf2e4\ncommit-date: 2020-06-01\nhost: x86_64-unknown-linux-gnu\nrelease: 1.44.0\nLLVM version: 9.0\n",""],"4476964694761187371":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/dannieboy/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n",""]},"successes":{}}

View file

View file

@ -0,0 +1 @@
657008ade131bb46

View file

@ -0,0 +1 @@
{"rustc":5807094999684781751,"features":"[]","target":8443017735982037405,"profile":14891217944882224483,"path":1036222786711178230,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/tests-c066b971b0bbd15a/dep-bin-tests-c066b971b0bbd15a"}}],"rustflags":[],"metadata":7884812644471753209}

View file

@ -0,0 +1 @@
This file has an mtime of when this was started.

View file

@ -0,0 +1 @@
aee87f802deaab67

View file

@ -0,0 +1 @@
{"rustc":5807094999684781751,"features":"[]","target":8443017735982037405,"profile":14996655781355331481,"path":1036222786711178230,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/tests-e7efc60f064cff81/dep-bin-tests-e7efc60f064cff81"}}],"rustflags":[],"metadata":7884812644471753209}

View file

@ -0,0 +1 @@
This file has an mtime of when this was started.

View file

@ -0,0 +1,5 @@
/mnt/disk1/projects/TF2P/tests/target/debug/deps/tests-c066b971b0bbd15a.rmeta: src/main.rs
/mnt/disk1/projects/TF2P/tests/target/debug/deps/tests-c066b971b0bbd15a.d: src/main.rs
src/main.rs:

Binary file not shown.

View file

@ -0,0 +1,5 @@
/mnt/disk1/projects/TF2P/tests/target/debug/deps/tests-e7efc60f064cff81: src/main.rs
/mnt/disk1/projects/TF2P/tests/target/debug/deps/tests-e7efc60f064cff81.d: src/main.rs
src/main.rs:

BIN
tests/target/debug/tests Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
/mnt/disk1/projects/TF2P/tests/target/debug/tests: /mnt/disk1/projects/TF2P/tests/src/main.rs

View file

@ -0,0 +1 @@
{"rustc_fingerprint":4567211532567258067,"outputs":{"1138116330425514636":["___\n",""],"4476964694761187371":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/dannieboy/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/rls\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"mmx\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"cas\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n",""],"1164083562126845933":["rustc 1.39.0-nightly (c6e9c76c5 2019-09-04)\nbinary: rustc\ncommit-hash: c6e9c76c59e3c10acd63ca9ec157a8894ea1a068\ncommit-date: 2019-09-04\nhost: x86_64-unknown-linux-gnu\nrelease: 1.39.0-nightly\nLLVM version: 9.0\n",""],"2196823701345282402":["___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/dannieboy/.vim/bundle/YouCompleteMe/third_party/ycmd/third_party/rls\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"mmx\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"cas\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"unknown\"\nunix\n",""]},"successes":{}}

View file

View file

@ -0,0 +1 @@
ec4873444cbdaeef

View file

@ -0,0 +1 @@
{"rustc":14587545897571530554,"features":"[]","target":8443017735982037405,"profile":14891217944882224483,"path":1036222786711178230,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/tests-2d2ee19b1caaa0fc/dep-bin-tests-2d2ee19b1caaa0fc"}}],"rustflags":[],"metadata":7884812644471753209}

View file

@ -0,0 +1 @@
This file has an mtime of when this was started.

Some files were not shown because too many files have changed in this diff Show more