rust/hedgewars-server/src/protocol.rs
author S.D.
Tue, 27 Sep 2022 14:59:03 +0300
changeset 15900 fc3cb23fd26f
parent 15854 a4d505a32879
child 16018 fb389df02e3e
permissions -rw-r--r--
Allow to see rooms of incompatible versions in the lobby For the new clients the room version is shown in a separate column. There is also a hack for previous versions clients: the room vesion specifier is prepended to the room names for rooms of incompatible versions, and the server shows 'incompatible version' error if the client tries to join them.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
     1
use bytes::{Buf, BufMut, BytesMut};
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
     2
use log::*;
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
     3
use std::{
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
     4
    error::Error,
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
     5
    fmt::{Debug, Display, Formatter},
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
     6
    io,
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
     7
    io::ErrorKind,
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
     8
    marker::Unpin,
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
     9
    time::Duration,
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    10
};
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    11
use tokio::{io::AsyncReadExt, time::timeout};
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    12
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    13
use crate::protocol::ProtocolError::Timeout;
15826
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15817
diff changeset
    14
use hedgewars_network_protocol::{
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15817
diff changeset
    15
    messages::HwProtocolMessage,
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    16
    parser::HwProtocolError,
15826
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15817
diff changeset
    17
    parser::{malformed_message, message},
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15817
diff changeset
    18
};
12129
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
    19
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    20
#[derive(Debug)]
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    21
pub enum ProtocolError {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    22
    Eof,
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    23
    Timeout,
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    24
    Network(Box<dyn Error + Send>),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    25
}
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    26
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    27
impl Display for ProtocolError {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    28
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    29
        match self {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    30
            ProtocolError::Eof => write!(f, "Connection reset by peer"),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    31
            ProtocolError::Timeout => write!(f, "Read operation timed out"),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    32
            ProtocolError::Network(source) => write!(f, "{:?}", source),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    33
        }
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    34
    }
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    35
}
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    36
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    37
impl Error for ProtocolError {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    38
    fn source(&self) -> Option<&(dyn Error + 'static)> {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    39
        if let Self::Network(source) = self {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    40
            Some(source.as_ref())
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    41
        } else {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    42
            None
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    43
        }
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    44
    }
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    45
}
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    46
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    47
pub type Result<T> = std::result::Result<T, ProtocolError>;
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    48
12136
e25a82ce2374 - Render messages to string
unc0rr
parents: 12133
diff changeset
    49
pub struct ProtocolDecoder {
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    50
    buffer: BytesMut,
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    51
    read_timeout: Duration,
14816
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    52
    is_recovering: bool,
12129
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
    53
}
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
    54
12136
e25a82ce2374 - Render messages to string
unc0rr
parents: 12133
diff changeset
    55
impl ProtocolDecoder {
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    56
    pub fn new(read_timeout: Duration) -> ProtocolDecoder {
12136
e25a82ce2374 - Render messages to string
unc0rr
parents: 12133
diff changeset
    57
        ProtocolDecoder {
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    58
            buffer: BytesMut::with_capacity(1024),
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
    59
            read_timeout,
14816
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    60
            is_recovering: false,
12129
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
    61
        }
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
    62
    }
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
    63
14816
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    64
    fn recover(&mut self) -> bool {
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    65
        self.is_recovering = match malformed_message(&self.buffer[..]) {
14816
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    66
            Ok((tail, ())) => {
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    67
                let remaining = tail.len();
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    68
                self.buffer.advance(self.buffer.len() - remaining);
14816
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    69
                false
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    70
            }
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    71
            _ => {
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    72
                self.buffer.clear();
14816
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    73
                true
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    74
            }
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    75
        };
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    76
        !self.is_recovering
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    77
    }
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    78
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    79
    fn extract_message(&mut self) -> Option<HwProtocolMessage> {
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    80
        if !self.is_recovering || self.recover() {
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    81
            match message(&self.buffer[..]) {
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    82
                Ok((tail, message)) => {
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    83
                    let remaining = tail.len();
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    84
                    self.buffer.advance(self.buffer.len() - remaining);
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    85
                    return Some(message);
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    86
                }
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    87
                Err(nom::Err::Incomplete(_)) => {}
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    88
                Err(nom::Err::Failure(e) | nom::Err::Error(e)) => {
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    89
                    debug!("Invalid message: {:?}", e);
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    90
                    self.recover();
14816
add191d825f4 add parser error handling
alfadur
parents: 14796
diff changeset
    91
                }
14478
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14436
diff changeset
    92
            }
12136
e25a82ce2374 - Render messages to string
unc0rr
parents: 12133
diff changeset
    93
        }
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    94
        None
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    95
    }
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    96
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    97
    pub async fn read_from<R: AsyncReadExt + Unpin>(
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    98
        &mut self,
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
    99
        stream: &mut R,
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   100
    ) -> Result<HwProtocolMessage> {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   101
        use ProtocolError::*;
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   102
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   103
        loop {
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   104
            if !self.buffer.has_remaining() {
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   105
                match timeout(self.read_timeout, stream.read_buf(&mut self.buffer)).await {
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   106
                    Err(_) => return Err(Timeout),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   107
                    Ok(Err(e)) => return Err(Network(Box::new(e))),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   108
                    Ok(Ok(0)) => return Err(Eof),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   109
                    Ok(Ok(_)) => (),
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   110
                };
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   111
            }
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   112
            while !self.buffer.is_empty() {
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   113
                if let Some(result) = self.extract_message() {
15854
a4d505a32879 add back client timeouts
alfadur
parents: 15853
diff changeset
   114
                    return Ok(result);
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   115
                }
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   116
            }
7d0f747afcb8 move server network to tokio
alfadur
parents: 15826
diff changeset
   117
        }
12129
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
   118
    }
07972a8c2433 - Start protocol parser implementation
unc0rr
parents:
diff changeset
   119
}