Skip to content

Commit

Permalink
Potentially breaking changes.
Browse files Browse the repository at this point in the history
  • Loading branch information
dankmeme01 committed Nov 28, 2023
1 parent 66f57ed commit 911de53
Show file tree
Hide file tree
Showing 75 changed files with 1,744 additions and 748 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@

build.sh
build-android.sh
build-android/

mod-w.json
mod-a.json

server/bench-client
server/target
Expand Down
21 changes: 7 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ This repository contains the complete rewrite of Globed, for Geometry Dash 2.2 a
## Features

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

## Installation

Expand All @@ -30,13 +30,6 @@ Known issues:

See the [server readme](./server/readme.md) for more information about the server and how you can host it.

## Building

```sh
cmake -DCMAKE_BUILD_TYPE=Release -B build
cmake --build build --config Release
```

## Credit

ca7x3, Firee, Croozington, Coloride, Cvolton, mat, alk, maki, xTymon - thank you for being awesome, whether it's because you helped me, suggested ideas, helped with testing, or if I just found you awesome in general :D
Expand All @@ -45,9 +38,9 @@ camila314 - thank you for [UIBuilder](https://github.com/camila314/uibuilder)

RobTop - thank you for releasing this awesome game :)

## Open source acknowledgments
### Used libraries

* [Geode](https://geode-sdk.org/) - the one thing that made all of this possible :)
* [UIBuilder](https://github.com/camila314/uibuilder) - something you should 100% use when creating GD mods
* [Opus](https://github.com/xiph/opus) - audio codec used for audio compression
* [libsodium](https://github.com/jedisct1/libsodium) - library used for data encryption
* [Geode](https://geode-sdk.org/)
* [UIBuilder](https://github.com/camila314/uibuilder)
* [Opus](https://github.com/xiph/opus)
* [libsodium](https://github.com/jedisct1/libsodium)
19 changes: 13 additions & 6 deletions mod.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
{
"geode": "1.3.5",
"version": "v1.0.0-alpha.1",
"id": "dankmeme.globed2",
"name": "Globed",
"developer": "dankmeme",
"description": "Feature-rich multiplayer mod for Geometry Dash"
"geode": "1.3.5",
"version": "v1.0.0-alpha.1",
"id": "dankmeme.globed2",
"name": "Globed",
"developer": "dankmeme",
"description": "Feature-rich multiplayer mod for Geometry Dash",
"dependencies": [
{
"id": "geode.custom-keybinds",
"version": ">=v1.2.2",
"importance": "required"
}
]
}
3 changes: 1 addition & 2 deletions server/central/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ edition = "2021"
globed-shared = { path = "../shared" }

anyhow = "1.0.75"
async-rate-limit = "0.0.3"
async-watcher = "0.2.0"
base64 = "0.21.5"
blake2 = "0.10.6"
Expand All @@ -25,7 +26,5 @@ sha2 = "0.10.8"
time = { version = "0.3.30", features = ["formatting"] }
tokio = { version = "1.34.0", features = ["full"] }
totp-rs = "5.4.0"
lazy_static = "1.4.0"
iprange = "0.6.7"
ipnet = "2.9.0"
async-rate-limit = "0.0.3"
10 changes: 5 additions & 5 deletions server/central/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::{
collections::HashMap,
collections::{HashMap, HashSet},
fs::{File, OpenOptions},
path::Path,
};
Expand Down Expand Up @@ -47,8 +47,8 @@ fn default_userlist_mode() -> UserlistMode {
UserlistMode::None
}

fn default_userlist() -> Vec<i32> {
Vec::new()
fn default_userlist() -> HashSet<i32> {
HashSet::new()
}

fn default_secret_key() -> String {
Expand Down Expand Up @@ -117,9 +117,9 @@ pub struct ServerConfig {
#[serde(default = "default_userlist_mode")]
pub userlist_mode: UserlistMode,
#[serde(default = "default_userlist")]
pub userlist: Vec<i32>,
pub userlist: HashSet<i32>,
#[serde(default = "default_userlist")]
pub no_chat_list: Vec<i32>,
pub no_chat_list: HashSet<i32>,

// security
#[serde(default = "default_use_gd_api")]
Expand Down
58 changes: 29 additions & 29 deletions server/central/src/ip_blocker.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,42 @@
use std::net::IpAddr;
use std::{net::IpAddr, sync::OnceLock};

use ipnet::{Ipv4Net, Ipv6Net};
use iprange::IpRange;
use lazy_static::lazy_static;

pub struct IpBlocker {
range_v4: IpRange<Ipv4Net>,
range_v6: IpRange<Ipv6Net>,
}

impl IpBlocker {
pub fn instance() -> &'static Self {
static INSTANCE: OnceLock<IpBlocker> = OnceLock::new();
INSTANCE.get_or_init(|| {
let contents = include_str!("allowed_ranges.txt");
let mut v4 = Vec::new();
let mut v6 = Vec::new();

for line in contents.lines() {
let line = line.trim().to_lowercase();
if line.is_empty() || line.starts_with('#') || !line.contains(' ') {
continue;
}

let (proto, range) = line.split_once(' ').unwrap();

if proto == "v4" {
v4.push(range.to_string());
} else if proto == "v6" {
v6.push(range.to_string());
} else {
eprintln!("ignoring invalid IP address entry: {line}");
}
}

IpBlocker::new(&v4, &v6)
})
}

pub fn new(v4: &[String], v6: &[String]) -> Self {
let range_v4 = v4.iter().map(|s| s.parse().unwrap()).collect();
let range_v6 = v6.iter().map(|s| s.parse().unwrap()).collect();
Expand All @@ -24,30 +51,3 @@ impl IpBlocker {
}
}
}

lazy_static! {
pub static ref IP_BLOCKER: IpBlocker = {
let contents = include_str!("allowed_ranges.txt");
let mut v4 = Vec::new();
let mut v6 = Vec::new();

for line in contents.lines() {
let line = line.trim().to_lowercase();
if line.is_empty() || line.starts_with('#') || !line.contains(' ') {
continue;
}

let (proto, range) = line.split_once(' ').unwrap();

if proto == "v4" {
v4.push(range.to_string());
} else if proto == "v6" {
v6.push(range.to_string());
} else {
eprintln!("ignoring invalid IP address entry: {line}");
}
}

IpBlocker::new(&v4, &v6)
};
}
56 changes: 34 additions & 22 deletions server/central/src/logger.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
use std::time::SystemTime;
use std::{sync::OnceLock, time::SystemTime};

use colored::Colorize;
use log::Level;
use time::{format_description, OffsetDateTime};

pub struct Logger;
pub struct Logger {
format_desc: Vec<format_description::FormatItem<'static>>,
}

const TIME_FORMAT: &str = "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:3]";

impl Logger {
pub fn instance() -> &'static Self {
static INSTANCE: OnceLock<Logger> = OnceLock::new();
INSTANCE.get_or_init(|| Logger {
format_desc: format_description::parse(TIME_FORMAT).unwrap(),
})
}
}

impl log::Log for Logger {
fn enabled(&self, metadata: &log::Metadata) -> bool {
if metadata.target().starts_with("globed_central_server") {
Expand All @@ -18,27 +29,28 @@ impl log::Log for Logger {
}

fn log(&self, record: &log::Record) {
if self.enabled(record.metadata()) {
let now: OffsetDateTime = SystemTime::now().into();
let format_desc = format_description::parse(TIME_FORMAT).unwrap();
let formatted_time = now.format(&format_desc).unwrap();

let (level, args) = match record.level() {
Level::Error => (
record.level().to_string().bright_red(),
record.args().to_string().bright_red(),
),
Level::Warn => (
record.level().to_string().bright_yellow(),
record.args().to_string().bright_yellow(),
),
Level::Info => (record.level().to_string().cyan(), record.args().to_string().cyan()),
Level::Debug => (record.level().to_string().normal(), record.args().to_string().normal()),
Level::Trace => (record.level().to_string().black(), record.args().to_string().black()),
};

println!("[{formatted_time}] [{level}] - {args}");
if !self.enabled(record.metadata()) {
return;
}

let now: OffsetDateTime = SystemTime::now().into();
let formatted_time = now.format(&self.format_desc).unwrap();

let (level, args) = match record.level() {
Level::Error => (
record.level().to_string().bright_red(),
record.args().to_string().bright_red(),
),
Level::Warn => (
record.level().to_string().bright_yellow(),
record.args().to_string().bright_yellow(),
),
Level::Info => (record.level().to_string().cyan(), record.args().to_string().cyan()),
Level::Debug => (record.level().to_string().normal(), record.args().to_string().normal()),
Level::Trace => (record.level().to_string().black(), record.args().to_string().black()),
};

println!("[{formatted_time}] [{level}] - {args}");
}

fn flush(&self) {}
Expand Down
4 changes: 1 addition & 3 deletions server/central/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ pub mod logger;
pub mod state;
pub mod web;

static LOGGER: Logger = Logger;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
log::set_logger(&LOGGER).unwrap();
log::set_logger(Logger::instance()).unwrap();

if std::env::var("GLOBED_LESS_LOG").unwrap_or("0".to_string()) == "1" {
log::set_max_level(LevelFilter::Warn);
Expand Down
4 changes: 2 additions & 2 deletions server/central/src/web/routes/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rand::{distributions::Alphanumeric, Rng};
use roa::{http::StatusCode, preload::PowerBody, query::Query, throw, Context};

use crate::state::{ActiveChallenge, ServerState};
use crate::{config::UserlistMode, ip_blocker::IP_BLOCKER};
use crate::{config::UserlistMode, ip_blocker::IpBlocker};

macro_rules! check_user_agent {
($ctx:expr, $ua:ident) => {
Expand All @@ -35,7 +35,7 @@ macro_rules! get_user_ip {
($state:expr,$context:expr,$out:ident) => {
let user_ip: anyhow::Result<IpAddr> = if $state.config.cloudflare_protection && !cfg!(debug_assertions) {
// verify if the actual peer is cloudflare
if !IP_BLOCKER.is_allowed(&$context.remote_addr.ip()) {
if !IpBlocker::instance().is_allowed(&$context.remote_addr.ip()) {
warn!("blocking unknown non-cloudflare address: {}", $context.remote_addr.ip());
throw!(StatusCode::UNAUTHORIZED, "access is denied from this IP address");
}
Expand Down
1 change: 0 additions & 1 deletion server/game/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ array-init = "2.1.0"
bytebuffer = "2.2.0"
colored = "2.0.4"
crypto_box = { version = "0.9.1", features = ["std", "chacha20"] }
lazy_static = "1.4.0"
log = { version = "0.4.20" }
num_enum = "0.7.1"
parking_lot = "0.12.1"
Expand Down
Loading

0 comments on commit 911de53

Please sign in to comment.