瀏覽代碼

hw10 now has the same functionality as hw9.

Joshua Rutschmann 7 年之前
父節點
當前提交
455e64b271

+ 10
- 0
hw10/task1/Cargo.toml 查看文件

@@ -0,0 +1,10 @@
1
+[package]
2
+name = "task1"
3
+version = "0.2.0"
4
+authors = ["Joshua Rutschmann <joshua.rutschmann@gmx.de>", "Lorenz Bung <lorenz.bung@htwg-konstanz.de>"]
5
+
6
+[dependencies]
7
+srv-commands = { path = "srv-commands" }
8
+srv-config = { path = "srv-config" }
9
+
10
+[workspace]

+ 1
- 0
hw10/task1/DESIGN.md 查看文件

@@ -0,0 +1 @@
1
+# Design des MultiHashServer (hw10)

+ 121
- 0
hw10/task1/src/main.rs 查看文件

@@ -0,0 +1,121 @@
1
+extern crate srv_commands;
2
+extern crate srv_config;
3
+
4
+use std::io::{BufReader, BufRead, BufWriter, Write};
5
+use std::collections::VecDeque;
6
+use std::net::{TcpListener, TcpStream};
7
+use srv_commands::Command;
8
+use srv_config::Config;
9
+use HashServerError::Parse;
10
+
11
+#[derive(Debug)]
12
+pub enum HashServerError {
13
+    Parse(srv_commands::ParseError),
14
+    Io(std::io::Error),
15
+}
16
+
17
+impl From<std::io::Error> for HashServerError {
18
+    fn from(err: std::io::Error) -> HashServerError {
19
+        HashServerError::Io(err)
20
+    }
21
+}
22
+
23
+impl From<srv_commands::ParseError> for HashServerError {
24
+    fn from(err: srv_commands::ParseError) -> HashServerError {
25
+        HashServerError::Parse(err)
26
+    }
27
+}
28
+
29
+fn handle_client(stream: &TcpStream, orders: &mut VecDeque<String>, v: bool) {
30
+    let mut reader = BufReader::new(stream);
31
+    let mut writer = BufWriter::new(stream);
32
+
33
+    loop {
34
+        let mut line = String::new();
35
+        match reader.read_line(&mut line) {
36
+            Ok(n) => {
37
+                if n == 0 {
38
+                    break;
39
+                }
40
+
41
+                let cmd = srv_commands::parse(&line).map_err(HashServerError::Parse);
42
+
43
+                match cmd {
44
+                    Ok(Command::Stage(str)) => {
45
+                        orders.push_front(str);
46
+                    }
47
+                    Ok(Command::Retrieve) => {
48
+                        if orders.is_empty() {
49
+                            let _ = writer.write(b"No order on stage!\n");
50
+
51
+                        } else {
52
+                            if let Some(latest_order) = orders.pop_front() {
53
+                                let _ = writer.write(latest_order.as_bytes());
54
+                                let _ = writer.write(b"\n");
55
+                            }
56
+                        }
57
+                    }
58
+                    Ok(Command::Control(ref control_string)) => {
59
+                        if v {
60
+                            println!("Received Control: {}", control_string);
61
+                        }
62
+                    }
63
+                    Err(Parse(e)) => {
64
+                        println!("Error occurred: {:?}", e);
65
+                    }
66
+                    _ => {}
67
+                }
68
+
69
+                let _ = writer.flush();
70
+            }
71
+            _ => {
72
+                break;
73
+            }
74
+        }
75
+    }
76
+}
77
+
78
+pub fn main() {
79
+
80
+    let c = Config::load();
81
+
82
+    if c.verbosity > 0 {
83
+        println!("Starting Multi Hash Server 0.1:");
84
+        println!(
85
+            "verbosity: {} | address: {} | port: {} | test-mode: {}",
86
+            c.verbosity,
87
+            c.address,
88
+            c.port,
89
+            c.testing
90
+        );
91
+    }
92
+
93
+    let host = format!("{}:{}", c.address, c.port);
94
+
95
+    let mut orders: VecDeque<String> = VecDeque::new();
96
+
97
+    if c.testing {
98
+        orders.push_front(String::from("Test3"));
99
+        orders.push_front(String::from("Test2"));
100
+        orders.push_front(String::from("Test1"));
101
+    }
102
+
103
+    match TcpListener::bind(host).map_err(HashServerError::Io) {
104
+        Ok(listener) => {
105
+            for s in listener.incoming() {
106
+                if let Ok(stream) = s {
107
+                    if c.verbosity > 1 {
108
+                        println!("[DEBUG] New Client connected")
109
+                    }
110
+                    handle_client(&stream, &mut orders, c.verbosity > 0);
111
+                    if c.verbosity > 1 {
112
+                        println!("[DEBUG] Client diconnected")
113
+                    }
114
+                }
115
+            }
116
+        }
117
+        Err(e) => {
118
+            println!("Failed to start the MultiHashServer: {:?}", e);
119
+        }
120
+    }
121
+}

+ 8
- 0
hw10/task1/srv-commands/Cargo.toml 查看文件

@@ -0,0 +1,8 @@
1
+[package]
2
+name = "srv-commands"
3
+version = "0.1.0"
4
+authors = ["Joshua Rutschmann <joshua.rutschmann@gmx.de>"]
5
+
6
+[dependencies]
7
+sha2 = "0.7.0"
8
+time = "0.1"

+ 39
- 0
hw10/task1/srv-commands/src/lib.rs 查看文件

@@ -0,0 +1,39 @@
1
+pub fn parse(message: &str) -> Result<Command, ParseError> {
2
+    let m: String = String::from(message.trim_right());
3
+    let mut line = m.lines();
4
+    match line.next() {
5
+        Some(x) => {
6
+            let mut str = x.split_whitespace();
7
+            match str.next() {
8
+                Some("STAGE") => {
9
+                    let msg = m[6..].trim_left();
10
+                    Ok(Command::Stage(msg.to_string()))
11
+                }
12
+                Some("CONTROL") => {
13
+                    let cmd = m[8..].trim_left();
14
+                    Ok(Command::Control(cmd.to_string()))
15
+                }
16
+                Some("RETRIEVE") => Ok(Command::Retrieve),
17
+                Some(_) => Err(ParseError(ErrorType::UnknownCommand)),
18
+                None => Err(ParseError(ErrorType::EmptyString)),
19
+            }
20
+        }
21
+        None => Err(ParseError(ErrorType::EmptyString)),
22
+    }
23
+}
24
+
25
+#[derive(Debug, PartialEq)]
26
+pub enum Command {
27
+    Stage(String),
28
+    Control(String),
29
+    Retrieve,
30
+}
31
+
32
+#[derive(Debug, PartialEq)]
33
+pub struct ParseError(pub ErrorType);
34
+
35
+#[derive(Debug, PartialEq)]
36
+pub enum ErrorType {
37
+    UnknownCommand,
38
+    EmptyString,
39
+}

+ 43
- 0
hw10/task1/srv-commands/tests/srv-commands.rs 查看文件

@@ -0,0 +1,43 @@
1
+#[cfg(test)]
2
+
3
+mod tests {
4
+	extern crate srv_commands;
5
+    use self::srv_commands::*;
6
+
7
+    #[test]
8
+    fn empty_returns_correct_command() {
9
+        assert_eq!(parse("\n"), Err(ParseError(ErrorType::EmptyString)))
10
+    }
11
+
12
+    #[test]
13
+    fn not_known_command_returns_correct_command() {
14
+        assert_eq!(parse("Hello\n"), Err(ParseError(ErrorType::UnknownCommand)))
15
+    }
16
+
17
+    #[test]
18
+    fn stage_returns_correct_command() {
19
+        assert_eq!(
20
+            parse("STAGE Hello\n"),
21
+            Ok(Command::Stage("Hello".to_string()))
22
+        )
23
+    }
24
+
25
+    #[test]
26
+    fn control_returns_correct_command() {
27
+        assert_eq!(
28
+            parse("CONTROL Hello\n"),
29
+            Ok(Command::Control("Hello".to_string()))
30
+        )
31
+    }
32
+
33
+    #[test]
34
+    fn retrieve_returns_correct_command() {
35
+        assert_eq!(parse("RETRIEVE\n"), Ok(Command::Retrieve))
36
+    }
37
+
38
+    #[test]
39
+    fn retrieve_with_arguments_returns_correct_command() {
40
+        assert_eq!(parse("RETRIEVE Hello\n"), Ok(Command::Retrieve))
41
+    }
42
+
43
+}

+ 7
- 0
hw10/task1/srv-config/Cargo.toml 查看文件

@@ -0,0 +1,7 @@
1
+[package]
2
+name = "srv-config"
3
+version = "0.1.0"
4
+authors = ["Joshua Rutschmann <joshua.rutschmann@gmx.de>"]
5
+
6
+[dependencies]
7
+clap = {version = "~2.29.0", features = ["yaml"]}

+ 32
- 0
hw10/task1/srv-config/src/cli.yml 查看文件

@@ -0,0 +1,32 @@
1
+name: "Multi Hash Server 0.1"
2
+author: "Lorenz Bung & Joshua Rutschmann"
3
+about: "Does awesome things to find a hash with specific pattern"
4
+args:
5
+    - verbose:
6
+        short: "v"
7
+        help: "Prints help information"
8
+        multiple: true
9
+        required: false
10
+
11
+    - address:
12
+        short: "a"
13
+        long: "address"
14
+        value_name: "ADDRESS"
15
+        help: "the address, where the server can be reached (127.0.0.1 is default)"
16
+        takes_value: true
17
+        required: false
18
+
19
+    - port:
20
+        short: "p"
21
+        long: "port"
22
+        value_name: "PORT"
23
+        help: "the port, where the server can be reached (7878 is default)"
24
+        takes_value: true
25
+        required: true
26
+
27
+subcommands:
28
+    - test:
29
+        about: "controls testing features"
30
+        version: "1.0"
31
+        author: "Lorenz Bung & Joshua Rutschmann"
32
+

+ 36
- 0
hw10/task1/srv-config/src/lib.rs 查看文件

@@ -0,0 +1,36 @@
1
+#[macro_use]
2
+extern crate clap;
3
+
4
+use clap::App;
5
+
6
+pub struct Config {
7
+    pub address: String,
8
+    pub port: String,
9
+    pub verbosity: u64,
10
+    pub testing: bool,
11
+}
12
+
13
+impl Config {
14
+    pub fn load() -> Self {
15
+        let yaml = load_yaml!("cli.yml");
16
+        let matches = App::from_yaml(yaml).get_matches();
17
+        let address = matches.value_of("address").unwrap_or("127.0.0.1");
18
+        let port = matches.value_of("port").unwrap_or("7878");
19
+        let verbosity = matches.occurrences_of("verbose");
20
+        let mut testing = false;
21
+
22
+        // Falls das Unterkommando timings angegeben wurde aktiviere die Zeitmessung.
23
+        if let Some(ref sub_command) = matches.subcommand {
24
+            if sub_command.name.eq("test") {
25
+                testing = true;
26
+            }
27
+        }
28
+
29
+        Config {
30
+            address: address.to_string(),
31
+            port: port.to_string(),
32
+            verbosity: verbosity,
33
+            testing: testing,
34
+        }
35
+    }
36
+}

Loading…
取消
儲存