Skip to content

Commit e10c1d2

Browse files
update
1 parent e7b253a commit e10c1d2

File tree

14 files changed

+355
-423
lines changed

14 files changed

+355
-423
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
[package]
22
name = "tine"
3-
version = "0.1.0"
3+
version = "1.0.0"
44
edition = "2021"
55
authors = ["Sergio Ivanuzzo <sergio.ivanuzzo@gmail.com>"]
66
description = "TINE IS NOT EMULATOR, it is just a tiny wow server for v3.3.5a (currently only this version)"
77
readme = "README.md"
88
keywords = ["idewave", "wow-server"]
99
license-file = "LICENSE"
1010
repository = "https://github.com/idewave/tine"
11+
publish = false
1112

1213
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1314

1415
[dependencies]
1516
anyhow = "1.0"
1617
arc4 = "0.1.0"
17-
async-broadcast = "0.7.1"
1818
async-trait = "0.1.77"
1919
bitflags = "2.4.2"
2020
byteorder = "1.4.3"
@@ -33,7 +33,7 @@ tentacli-formatters = "0.1.0"
3333
tentacli-packet = "7.0.0"
3434
tentacli-traits = "9.2.1"
3535
tentacli-utils = "2.1.0"
36-
tokio = { version = "1", features = ["sync", "net", "io-util", "macros", "time", "rt-multi-thread"] }
36+
tokio = { version = "1", features = ["sync", "net", "io-util", "macros", "time", "rt-multi-thread", "signal"] }
3737

3838
[features]
3939
# use this feature to turn on println

src/lib.rs

Lines changed: 0 additions & 80 deletions
This file was deleted.

src/main.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use anyhow::Result as AnyResult;
22

3-
use tine::{Options, Server};
3+
use crate::primary::{Options, Server};
4+
5+
mod primary;
46

57
#[tokio::main]
68
async fn main() -> AnyResult<()> {
79
Server::run(Options {
810
login_port: 3724,
911
world_port: 19999,
10-
..Options::default()
1112
})
1213
.await?;
1314

src/primary/crypto/header_crypt.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::fmt::{Debug, Formatter};
21
use hmacsha::HmacSha;
32
use sha1::Sha1;
43

@@ -12,41 +11,48 @@ const DECRYPTION_KEY: [u8; 16] = [
1211
0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE
1312
];
1413

15-
pub struct HeaderCrypt {
16-
encryptor: RC4,
17-
decryptor: RC4,
14+
#[derive(Debug)]
15+
pub struct HeaderEncryptor {
16+
_instance: RC4,
1817
}
1918

20-
impl HeaderCrypt {
19+
impl HeaderEncryptor {
2120
pub fn new(secret: &[u8]) -> Self {
2221
let mut encryptor = RC4::new(
2322
HmacSha::new(&ENCRYPTION_KEY, secret, Sha1::default()).compute_digest().to_vec()
2423
);
2524

26-
let mut decryptor = RC4::new(
27-
HmacSha::new(&DECRYPTION_KEY, secret, Sha1::default()).compute_digest().to_vec()
28-
);
29-
3025
let _ = &encryptor.encrypt(&vec![0; 1024]);
31-
let _ = &decryptor.encrypt(&vec![0; 1024]);
3226

3327
Self {
34-
encryptor,
35-
decryptor,
28+
_instance: encryptor,
3629
}
3730
}
3831

3932
pub fn encrypt(&mut self, data: &[u8]) -> Vec<u8> {
40-
self.encryptor.encrypt(data)
33+
self._instance.encrypt(data)
4134
}
35+
}
4236

43-
pub fn decrypt(&mut self, data: &[u8]) -> Vec<u8> {
44-
self.decryptor.encrypt(data)
45-
}
37+
#[derive(Debug)]
38+
pub struct HeaderDecryptor {
39+
_instance: RC4,
4640
}
4741

48-
impl Debug for HeaderCrypt {
49-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50-
write!(f, "AuthCrypt")
42+
impl HeaderDecryptor {
43+
pub fn new(secret: &[u8]) -> Self {
44+
let mut decryptor = RC4::new(
45+
HmacSha::new(&DECRYPTION_KEY, secret, Sha1::default()).compute_digest().to_vec()
46+
);
47+
48+
let _ = &decryptor.encrypt(&vec![0; 1024]);
49+
50+
Self {
51+
_instance: decryptor,
52+
}
53+
}
54+
55+
pub fn decrypt(&mut self, data: &[u8]) -> Vec<u8> {
56+
self._instance.encrypt(data)
5157
}
5258
}

src/primary/mod.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
use std::sync::Arc;
2+
3+
use futures::future::join_all;
4+
use tokio::sync::Mutex;
5+
6+
use crate::primary::crypto::srp::Srp;
7+
use crate::primary::server::{LoginServer, WorldServer};
8+
use crate::primary::traits::server::{BaseServer, RunOptions};
9+
110
pub mod crypto;
211
pub mod server;
312
pub mod traits;
@@ -11,3 +20,45 @@ macro_rules! debug {
1120
}
1221

1322
pub(crate) use debug;
23+
24+
#[derive(Default)]
25+
pub struct Options {
26+
pub login_port: u16,
27+
pub world_port: u16,
28+
}
29+
30+
pub struct Server;
31+
impl Server {
32+
pub async fn run(
33+
Options {
34+
login_port,
35+
world_port,
36+
}: Options,
37+
) -> anyhow::Result<()> {
38+
let srp = Arc::new(Mutex::new(Srp::new()));
39+
40+
let run_login_server = |port: u16| {
41+
let options = RunOptions { srp: srp.clone(), port, world_port };
42+
43+
tokio::spawn(async move {
44+
if let Err(err) = LoginServer::default().start(options).await {
45+
debug!("Error running Login Server: {}", err);
46+
}
47+
})
48+
};
49+
50+
let run_world_server = |port: u16| {
51+
let options = RunOptions { srp: srp.clone(), port, world_port };
52+
53+
tokio::spawn(async move {
54+
if let Err(err) = WorldServer::default().start(options).await {
55+
debug!("Error running World Server: {}", err);
56+
}
57+
})
58+
};
59+
60+
join_all(vec![run_login_server(login_port), run_world_server(world_port)]).await;
61+
62+
Ok(())
63+
}
64+
}

src/primary/server/auth/realmlist.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl PacketHandler for Handler {
3333
}
3434

3535
RealmsSerializer {
36-
realms: vec![Self::generate_realm(input.server_info.world_port)],
36+
realms: vec![Self::generate_realm(input.world_port)],
3737
}
3838
.to_binary()
3939
.unwrap()

src/primary/server/login_server.rs

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,49 @@
11
use std::sync::Arc;
22

3-
use anyhow::Result as AnyResult;
43
use async_trait::async_trait;
54
use tentacli_traits::types::opcodes::Opcode;
65
use tokio::io::{AsyncReadExt, BufReader};
76
use tokio::net::tcp::OwnedReadHalf;
7+
use tokio::sync::mpsc::Sender;
88
use tokio::sync::Mutex;
9+
use tokio::task::JoinHandle;
910

11+
use crate::primary::crypto::header_crypt::HeaderDecryptor;
1012
use crate::primary::server::auth::{
1113
AuthProcessor, LoginChallengeIncoming, LoginProofIncoming, RealmlistIncoming,
1214
};
1315
use crate::primary::server::types::Packet;
14-
use crate::primary::traits::base_server::{BaseServer, Connection};
1516
use crate::primary::traits::processor::Processor;
17+
use crate::primary::traits::server::BaseServer;
1618
use crate::primary::types::ProcessorFunction;
17-
use crate::RunOptions;
1819

19-
pub struct LoginServer {}
20-
impl LoginServer {
21-
pub fn new() -> Self {
22-
Self {}
23-
}
24-
}
20+
#[derive(Default)]
21+
pub struct LoginServer;
2522

2623
#[async_trait]
2724
impl BaseServer for LoginServer {
28-
async fn read_packet(
29-
socket: &mut OwnedReadHalf,
30-
_: Arc<Mutex<Connection>>,
31-
) -> AnyResult<Packet> {
32-
let opcode = socket.read_u8().await?;
33-
let mut reader = BufReader::new(socket);
34-
35-
let data = match opcode {
36-
Opcode::LOGIN_CHALLENGE => LoginChallengeIncoming::from_stream(&mut reader).await?,
37-
Opcode::LOGIN_PROOF => LoginProofIncoming::from_stream(&mut reader).await?,
38-
Opcode::REALM_LIST => RealmlistIncoming::from_stream(&mut reader).await?,
39-
_ => vec![],
40-
};
41-
42-
Ok(Packet {
43-
opcode: opcode as u32,
44-
data,
25+
fn handle_read(
26+
input_sender: Sender<Packet>,
27+
mut reader: BufReader<OwnedReadHalf>,
28+
_: Arc<Mutex<Option<HeaderDecryptor>>>,
29+
) -> JoinHandle<anyhow::Result<()>> {
30+
tokio::spawn(async move {
31+
loop {
32+
let opcode = reader.read_u8().await?;
33+
34+
let body = match opcode {
35+
Opcode::LOGIN_CHALLENGE => {
36+
LoginChallengeIncoming::from_stream(&mut reader).await?
37+
}
38+
Opcode::LOGIN_PROOF => LoginProofIncoming::from_stream(&mut reader).await?,
39+
Opcode::REALM_LIST => RealmlistIncoming::from_stream(&mut reader).await?,
40+
_ => vec![],
41+
};
42+
43+
if !body.is_empty() {
44+
input_sender.send(Packet { opcode: opcode as u32, body }).await?;
45+
}
46+
}
4547
})
4648
}
4749

@@ -52,8 +54,4 @@ impl BaseServer for LoginServer {
5254
fn server_name<'a>() -> &'a str {
5355
"Login Server"
5456
}
55-
56-
fn port(options: Arc<RunOptions>) -> u16 {
57-
options.login_port
58-
}
5957
}
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
use async_trait::async_trait;
22

3-
use crate::primary::crypto::header_crypt::HeaderCrypt;
3+
use crate::primary::crypto::header_crypt::{HeaderDecryptor, HeaderEncryptor};
44
use crate::primary::traits::packet_handler::PacketHandler;
5-
use crate::primary::types::{HandlerInput, HandlerResult};
5+
use crate::primary::types::{HandlerInput, HandlerOutput, HandlerResult};
66

77
pub struct Handler;
88
#[async_trait]
99
impl PacketHandler for Handler {
1010
async fn handle(&mut self, input: &mut HandlerInput) -> HandlerResult {
11-
let response = Vec::new();
1211
let session_key = {
1312
let guard = input.srp.lock().await;
1413
guard.session_key.as_ref().unwrap().clone()
1514
};
1615

17-
let mut guard = input.connection.lock().await;
18-
guard.header_crypt = Some(HeaderCrypt::new(&session_key));
19-
20-
Ok(response)
16+
Ok(vec![
17+
HandlerOutput::HeaderCrypt(
18+
HeaderEncryptor::new(&session_key),
19+
HeaderDecryptor::new(&session_key),
20+
)
21+
])
2122
}
2223
}

src/primary/server/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
pub struct Packet {
22
pub opcode: u32,
3-
pub data: Vec<u8>,
4-
}
3+
pub body: Vec<u8>,
4+
}

0 commit comments

Comments
 (0)