Skip to content

Commit

Permalink
hell yeah
Browse files Browse the repository at this point in the history
  • Loading branch information
dankmeme01 committed Nov 23, 2023
1 parent 113fc37 commit 3e2c3e7
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 90 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This repository contains the complete rewrite of Globed, for Geometry Dash 2.2 a

* Real-time multiplayer
* Voice chat and text messages with full encryption and zero logging
* blazing fast server written in pure Rust 🚀
* blazing fast server written in pure Rust 🚀 (feauring only **one** unsafe block)

## Installation

Expand Down
9 changes: 8 additions & 1 deletion server/central/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
#![allow(
clippy::must_use_candidate,
clippy::module_name_repetitions,
clippy::missing_errors_doc,
clippy::missing_panics_doc
)]

use std::{error::Error, path::PathBuf, sync::Arc, time::Duration};

use async_watcher::{notify::RecursiveMode, AsyncDebouncer};
Expand Down Expand Up @@ -63,7 +70,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let state_skey = config.secret_key.clone();

let state = ServerState {
inner: Arc::new(RwLock::new(ServerStateData::new(config_path.clone(), config, state_skey))),
inner: Arc::new(RwLock::new(ServerStateData::new(config_path.clone(), config, &state_skey))),
};

// config file watcher
Expand Down
2 changes: 1 addition & 1 deletion server/central/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub struct ServerStateData {
}

impl ServerStateData {
pub fn new(config_path: PathBuf, config: ServerConfig, secret_key: String) -> Self {
pub fn new(config_path: PathBuf, config: ServerConfig, secret_key: &str) -> Self {
let skey_bytes = secret_key.as_bytes();
let hmac_obj = Hmac::<Sha256>::new_from_slice(skey_bytes).unwrap();

Expand Down
1 change: 1 addition & 0 deletions server/central/src/web/routes/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ pub async fn challenge_start(context: &mut Context<ServerState>) -> roa::Result
Ok(())
}

#[allow(clippy::too_many_lines)]
pub async fn challenge_finish(context: &mut Context<ServerState>) -> roa::Result {
check_user_agent!(context, _ua);

Expand Down
2 changes: 2 additions & 0 deletions server/game/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ tokio = { version = "1.34.0", features = ["full"] }
parking_lot = "0.12.1"
array-init = "2.1.0"
num_enum = "0.7.1"
alloca = "0.4.0"
lazy_static = "1.4.0"
211 changes: 177 additions & 34 deletions server/game/src/bytebufferext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use bytebuffer::{ByteBuffer, ByteReader};

pub trait Encodable {
fn encode(&self, buf: &mut ByteBuffer);
fn encode_fast(&self, buf: &mut FastByteBuffer);
}

pub trait Decodable {
Expand All @@ -21,6 +22,10 @@ macro_rules! encode_impl {
fn encode(&$self, $buf: &mut bytebuffer::ByteBuffer) {
$encode
}

fn encode_fast(&$self, $buf: &mut crate::bytebufferext::FastByteBuffer) {
$encode
}
}
};
}
Expand Down Expand Up @@ -48,6 +53,13 @@ macro_rules! encode_unimpl {
stringify!($packet_type)
);
}

fn encode_fast(&self, _: &mut crate::bytebufferext::FastByteBuffer) {
panic!(
"Tried to call {}::encode_fast when Encodable was not implemented for this type",
stringify!($packet_type)
);
}
}
};
}
Expand Down Expand Up @@ -77,6 +89,7 @@ pub(crate) use decode_unimpl;
pub(crate) use encode_impl;
pub(crate) use encode_unimpl;

/* ByteBuffer extensions */
pub trait ByteBufferExt {
fn with_capacity(capacity: usize) -> Self;
}
Expand Down Expand Up @@ -117,63 +130,177 @@ pub trait ByteBufferExtRead {
fn read_point(&mut self) -> Result<cocos::Point>;
}

impl ByteBufferExt for ByteBuffer {
fn with_capacity(capacity: usize) -> Self {
let mut ret = Self::from_vec(Vec::with_capacity(capacity));
ret.set_wpos(0);
ret
}
/* FastByteBuffer - zero heap allocation buffer for encoding but also limited functionality */
// will panic on writes if there isn't enough space.

pub struct FastByteBuffer<'a> {
pos: usize,
data: &'a mut [u8],
}

impl ByteBufferExtWrite for ByteBuffer {
fn write_bool(&mut self, val: bool) {
self.write_u8(u8::from(val));
impl<'a> FastByteBuffer<'a> {
// Create a new FastByteBuffer given this mutable slice
pub fn new(src: &'a mut [u8]) -> Self {
Self { pos: 0, data: src }
}

fn write_byte_array(&mut self, val: &[u8]) {
self.write_u32(val.len() as u32);
self.write_bytes(val);
#[inline]
pub fn write_u8(&mut self, val: u8) {
self.internal_write(&val.to_be_bytes());
}

fn write_value<T: Encodable>(&mut self, val: &T) {
val.encode(self);
#[inline]
pub fn write_u16(&mut self, val: u16) {
self.internal_write(&val.to_be_bytes());
}

fn write_optional_value<T: Encodable>(&mut self, val: Option<&T>) {
self.write_bool(val.is_some());
if let Some(val) = val {
self.write_value(val);
}
#[inline]
pub fn write_u32(&mut self, val: u32) {
self.internal_write(&val.to_be_bytes());
}

#[inline]
pub fn write_u64(&mut self, val: u64) {
self.internal_write(&val.to_be_bytes());
}

fn write_value_array<T: Encodable, const N: usize>(&mut self, val: &[T; N]) {
val.iter().for_each(|v| self.write_value(v));
#[inline]
pub fn write_i8(&mut self, val: i8) {
self.internal_write(&val.to_be_bytes());
}

fn write_value_vec<T: Encodable>(&mut self, val: &[T]) {
#[inline]
pub fn write_i16(&mut self, val: i16) {
self.internal_write(&val.to_be_bytes());
}

#[inline]
pub fn write_i32(&mut self, val: i32) {
self.internal_write(&val.to_be_bytes());
}

#[inline]
pub fn write_i64(&mut self, val: i64) {
self.internal_write(&val.to_be_bytes());
}

#[inline]
pub fn write_f32(&mut self, val: f32) {
self.internal_write(&val.to_be_bytes());
}

#[inline]
pub fn write_f64(&mut self, val: f64) {
self.internal_write(&val.to_be_bytes());
}

#[inline]
pub fn write_bytes(&mut self, data: &[u8]) {
self.internal_write(data);
}

#[inline]
pub fn write_string(&mut self, val: &str) {
self.write_u32(val.len() as u32);
for elem in val {
elem.encode(self);
}
self.write_bytes(val.as_bytes());
}

#[inline]
pub fn as_bytes(&'a mut self) -> &'a [u8] {
&self.data[..self.pos]
}

fn write_enum<E: Into<B>, B: Encodable>(&mut self, val: E) {
self.write_value(&val.into());
#[inline]
pub fn len(&self) -> usize {
self.pos
}

fn write_color3(&mut self, val: cocos::Color3B) {
self.write_value(&val);
#[inline]
pub fn is_empty(&self) -> bool {
self.pos == 0
}

fn write_color4(&mut self, val: cocos::Color4B) {
self.write_value(&val);
#[inline]
pub fn capacity(&self) -> usize {
self.data.len()
}

fn write_point(&mut self, val: cocos::Point) {
self.write_value(&val);
// Panics if there is not enough capacity left to write the data.
fn internal_write(&mut self, data: &[u8]) {
debug_assert!(
self.pos + data.len() <= self.capacity(),
"not enough space to write data into FastByteBuffer, capacity: {}, pos: {}, attempted write size: {}",
self.capacity(),
self.pos,
data.len()
);

self.data[self.pos..self.pos + data.len()].copy_from_slice(data);
self.pos += data.len();
}
}

/* ByteBuffer extension implementation for ByteBuffer, ByteReader and FastByteBuffer */

impl ByteBufferExt for ByteBuffer {
fn with_capacity(capacity: usize) -> Self {
let mut ret = Self::from_vec(Vec::with_capacity(capacity));
ret.set_wpos(0);
ret
}
}

macro_rules! impl_extwrite {
($encode_fn:ident) => {
fn write_bool(&mut self, val: bool) {
self.write_u8(u8::from(val));
}

fn write_byte_array(&mut self, val: &[u8]) {
self.write_u32(val.len() as u32);
self.write_bytes(val);
}

fn write_value<T: Encodable>(&mut self, val: &T) {
val.$encode_fn(self);
}

fn write_optional_value<T: Encodable>(&mut self, val: Option<&T>) {
self.write_bool(val.is_some());
if let Some(val) = val {
self.write_value(val);
}
}

fn write_value_array<T: Encodable, const N: usize>(&mut self, val: &[T; N]) {
val.iter().for_each(|v| self.write_value(v));
}

fn write_value_vec<T: Encodable>(&mut self, val: &[T]) {
self.write_u32(val.len() as u32);
for elem in val {
elem.$encode_fn(self);
}
}

fn write_enum<E: Into<B>, B: Encodable>(&mut self, val: E) {
self.write_value(&val.into());
}

fn write_color3(&mut self, val: cocos::Color3B) {
self.write_value(&val);
}

fn write_color4(&mut self, val: cocos::Color4B) {
self.write_value(&val);
}

fn write_point(&mut self, val: cocos::Point) {
self.write_value(&val);
}
};
}

macro_rules! impl_extread {
($decode_fn:ident) => {
fn read_bool(&mut self) -> Result<bool> {
Expand Down Expand Up @@ -231,6 +358,14 @@ macro_rules! impl_extread {
};
}

impl ByteBufferExtWrite for ByteBuffer {
impl_extwrite!(encode);
}

impl<'a> ByteBufferExtWrite for FastByteBuffer<'a> {
impl_extwrite!(encode_fast);
}

impl ByteBufferExtRead for ByteBuffer {
impl_extread!(decode);
}
Expand All @@ -239,14 +374,18 @@ impl<'a> ByteBufferExtRead for ByteReader<'a> {
impl_extread!(decode_from_reader);
}

/* Implementations for common types */
/* Encodable/Decodable implementations for common types */

macro_rules! impl_primitive {
($typ:ty,$read:ident,$write:ident) => {
impl Encodable for $typ {
fn encode(&self, buf: &mut ByteBuffer) {
buf.$write(*self);
}

fn encode_fast(&self, buf: &mut FastByteBuffer) {
buf.$write(*self);
}
}

impl Decodable for $typ {
Expand Down Expand Up @@ -279,6 +418,10 @@ impl Encodable for Vec<u8> {
fn encode(&self, buf: &mut ByteBuffer) {
buf.write_byte_array(self);
}

fn encode_fast(&self, buf: &mut FastByteBuffer) {
buf.write_byte_array(self);
}
}

impl Decodable for Vec<u8> {
Expand Down
8 changes: 5 additions & 3 deletions server/game/src/data/packets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ macro_rules! packet {
}
}

impl crate::data::packets::PacketWithId for $packet_type {
impl crate::data::packets::PacketMetadata for $packet_type {
const PACKET_ID: crate::data::packets::PacketId = $packet_id;
const ENCRYPTED: bool = $encrypted;
}
};
}
Expand Down Expand Up @@ -76,14 +77,15 @@ pub(crate) use empty_client_packet;
pub(crate) use empty_server_packet;
pub(crate) use packet;

pub trait Packet: Encodable + Decodable + Send + Sync {
pub trait Packet: Encodable + Decodable + Send + Sync + PacketMetadata {
fn get_packet_id(&self) -> PacketId;
fn get_encrypted(&self) -> bool;
}

// god i hate this
pub trait PacketWithId {
pub trait PacketMetadata {
const PACKET_ID: PacketId;
const ENCRYPTED: bool;
}

pub const PACKET_HEADER_LEN: usize = std::mem::size_of::<PacketId>() + std::mem::size_of::<bool>();
Loading

0 comments on commit 3e2c3e7

Please sign in to comment.