removed all posts
All checks were successful
Restart Website Service / restart_service (push) Successful in 30s
|
@ -63,7 +63,16 @@
|
|||
if (response.status != 200)
|
||||
return;
|
||||
|
||||
let posts = (await response.text()).split("\n");
|
||||
let posts = (await response.text()).split("\n").filter(x => x != "");
|
||||
|
||||
if (posts.length == 0) {
|
||||
let p = document.querySelector("#content>.content.posts>h2");
|
||||
p.innerHTML = "This is where I would put my posts...<br>IF I HAD ANY!";
|
||||
let elem = document.querySelector("#content>.content.posts>ul");
|
||||
elem.remove();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let p = document.querySelector("#content>.content.posts>h2");
|
||||
p.innerHTML = "Recent <a href=\"/posts\">posts</a>";
|
||||
|
|
|
@ -178,6 +178,8 @@ const maps = {
|
|||
keyword("Ok"),
|
||||
keyword("Err"),
|
||||
keyword("in"),
|
||||
keyword("Self"),
|
||||
keyword("mut"),
|
||||
|
||||
altKeyword("if"),
|
||||
altKeyword("else"),
|
||||
|
@ -185,6 +187,9 @@ const maps = {
|
|||
altKeyword("loop"),
|
||||
altKeyword("for"),
|
||||
altKeyword("while"),
|
||||
altKeyword("return"),
|
||||
altKeyword("async"),
|
||||
altKeyword("await"),
|
||||
|
||||
altKeyword("mod"),
|
||||
altKeyword("use"),
|
||||
|
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
BIN
public/posts/_Putting hungry minecraft servers to sleep/ping.png
Normal file
After Width: | Height: | Size: 43 KiB |
|
@ -61,17 +61,74 @@ wanted. [One crate](https://www.youtube.com/watch?v=E4WlUXrJgy4) was useful
|
|||
for seeing how an implementation of parsing packets was done, but ultimately
|
||||
I had to write my own parser.
|
||||
|
||||
***images of minecraft protocol***
|
||||

|
||||
|
||||
## Detecting the subdomain
|
||||
|
||||
The first step in routing the traffic was determining where to send it to.
|
||||
|
||||
Luckily for me, the Minecraft procotol sends the full address it is trying to
|
||||
connect to during the handshake. This meant that I simply had to parse the
|
||||
handshake and extract the subdomain from the address, see if it matches any
|
||||
configured server, and then redirect all traffic to the internal port that
|
||||
server runs on.
|
||||
|
||||
***code explanation***
|
||||
`$ vim protocol/handshake.rs`
|
||||
```rust
|
||||
impl Handshake {
|
||||
pub async fn new(buf: &mut BufferedReader) -> Result<Self, Error> {
|
||||
// Packets start with their type id. The handshake is id 0x00
|
||||
if !check_bytes(&[0x00], buf).await? {
|
||||
return Err(Error::Err(
|
||||
"Wrong packet type for handshake. Expected {} got {}".into(),
|
||||
));
|
||||
}
|
||||
buf.read(1).await?; // Consume handhake byte
|
||||
|
||||
let protocol_version = VarInt::read_from(buf).await?;
|
||||
let address = read_string(buf).await?;
|
||||
let port = buf.read_u16().await?;
|
||||
let next_state = VarInt::read_from(buf).await?;
|
||||
|
||||
return Ok(
|
||||
Self {
|
||||
protocol_version,
|
||||
address,
|
||||
port,
|
||||
next_state,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The only thing I was interrested in was the `address` part of the packet. This is a full string
|
||||
containing the text the user typed in the `IP Address` field in their client.
|
||||
|
||||
Once I had this it was as simple as splitting by `.` and taking the first result. This "server name" would now be used to look up the corosponding servers information in a table.
|
||||
|
||||
```rust
|
||||
|
||||
let result = Handshake::new(&mut reader).await;
|
||||
if !result.is_ok() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let handshake = result.ok().unwrap();
|
||||
let split = handshake.address.split(".").collect::<Vec<&str>>();
|
||||
let server_name = *split.first().unwrap();
|
||||
|
||||
if !SERVERS.lock().unwrap().contains_key(server_name) {
|
||||
println!("Unknown server {}", server_name);
|
||||
write_unknown_server_status(server_name.into(), &mut reader).await?;
|
||||
return Ok(None);
|
||||
}
|
||||
let mut server_lock = SERVERS.lock().unwrap();
|
||||
let server = server_lock.get_mut(server_name).unwrap();
|
||||
status = server.status;
|
||||
port = server.port;
|
||||
|
||||
```
|
||||
|
||||
***show images of hibernation and starting***
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
@ -127,10 +127,10 @@ fn handle_connection(mut stream: TcpStream) {
|
|||
let y = file_name.to_str();
|
||||
let ft = x.file_type();
|
||||
if y.is_some() {
|
||||
if ft.is_ok() && ft.unwrap().is_dir() {
|
||||
true
|
||||
} else if y.unwrap().starts_with("_") {
|
||||
if y.unwrap().starts_with("_") {
|
||||
false
|
||||
} else if ft.is_ok() && ft.unwrap().is_dir() {
|
||||
true
|
||||
} else if y.unwrap().ends_with(".md") {
|
||||
true
|
||||
} else {
|
||||
|
@ -228,7 +228,7 @@ fn handle_connection(mut stream: TcpStream) {
|
|||
}
|
||||
})
|
||||
.reduce(|a, b| format!("{}\n{}", b, a))
|
||||
.unwrap();
|
||||
.unwrap_or("".to_owned());
|
||||
format!("HTTP/1.1 200 OK\r\nContent-Type: text/text\r\nContent-Length: {}\r\n\r\n{}", data.len(), data)
|
||||
}
|
||||
Err(e) => {
|
||||
|
|