1
// This file is part of hnefatafl-copenhagen.
2
//
3
// hnefatafl-copenhagen is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU Affero General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// hnefatafl-copenhagen is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU Affero General Public License for more details.
12
//
13
// You should have received a copy of the GNU Affero General Public License
14
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
15
//
16
// SPDX-License-Identifier: AGPL-3.0-or-later
17
// SPDX-FileCopyrightText: 2025 David Campbell <david@hnefatafl.org>
18

            
19
//! An AI, client, engine, and server for the game of Copenhagen Hnefatafl.
20
//!
21
//! ## Feature Flags
22
//!
23
//! By default the `client` and `server` feature flags are enabled.
24
//!
25
//! * client - enable the `hnefatafl-client` binary
26
//! * console - on Windows print output to the console
27
//! * debug - enable iced debug mode, also log on the debug level
28
//! * js - enable options for generating javascript code
29
//! * runic - enable the `icelandic-runic` binary for translating Icelandic to Icelandic Runic
30
//! * server - enable the `hnefatafl-server-full` binary
31
//!
32
//! ## Message Protocol
33
//!
34
//! Get more information about the [message protocol] used by the engine.
35
//!
36
//! [message protocol]: https://docs.rs/hnefatafl-copenhagen/latest/hnefatafl_copenhagen/message/enum.Message.html
37

            
38
#![deny(clippy::panic)]
39
#![deny(clippy::unwrap_used)]
40

            
41
use std::{
42
    io::{BufRead, BufReader, Write},
43
    net::TcpStream,
44
};
45

            
46
#[cfg(feature = "socket")]
47
use socket2::TcpKeepalive;
48

            
49
rust_i18n::i18n!();
50

            
51
pub mod accounts;
52
pub mod ai;
53
pub mod board;
54
pub mod characters;
55
pub mod draw;
56
pub mod email;
57
pub mod game;
58
mod game_tree;
59
pub mod glicko;
60
pub mod heat_map;
61
pub mod locale;
62
mod message;
63
pub mod play;
64
pub mod rating;
65
pub mod role;
66
pub mod server_game;
67
pub mod space;
68
pub mod status;
69
mod tests;
70
pub mod time;
71
pub mod tournament;
72
pub mod tree;
73
pub mod utils;
74

            
75
pub type Id = u128;
76
pub const HOME: &str = "hnefatafl-copenhagen";
77
pub const SERVER_PORT: &str = ":49152";
78
pub const SOCKET_PATH: &str = "/tmp/hnefatafl.sock";
79
pub const VERSION_ID: &str = "ad746a65";
80

            
81
pub const COPYRIGHT: &str = r".SH COPYRIGHT
82
Copyright (C) 2025-2026 Developers of the hnefatafl-copenhagen project
83

            
84
This program is free software: you can redistribute it and/or modify
85
it under the terms of the GNU Affero General Public License as published by
86
the Free Software Foundation, either version 3 of the License, or
87
(at your option) any later version.
88

            
89
This program is distributed in the hope that it will be useful,
90
but WITHOUT ANY WARRANTY; without even the implied warranty of
91
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
92
GNU Affero General Public License for more details.
93

            
94
You should have received a copy of the GNU Affero General Public License
95
along with this program.  If not, see <https://www.gnu.org/licenses/>.
96
";
97

            
98
pub const LONG_VERSION: &str = concat!(
99
    env!("CARGO_PKG_VERSION"),
100
    "
101
Copyright (c) 2025-2026 Developers of the hnefatafl-copenhagen project
102
Licensed under the AGPLv3"
103
);
104

            
105
/// # Errors
106
///
107
/// If read fails.
108
pub fn read_response(reader: &mut BufReader<TcpStream>) -> anyhow::Result<String> {
109
    let mut reply = String::new();
110
    reader.read_line(&mut reply)?;
111
    print!("<- {reply}");
112
    Ok(reply)
113
}
114

            
115
/// # Errors
116
///
117
/// If write fails.
118
pub fn write_command(command: &str, stream: &mut TcpStream) -> anyhow::Result<()> {
119
    print!("-> {command}");
120
    stream.write_all(command.as_bytes())?;
121
    Ok(())
122
}
123

            
124
#[must_use]
125
#[cfg(all(feature = "socket", not(target_os = "redox")))]
126
pub fn tcp_keep_alive() -> TcpKeepalive {
127
    use std::time::Duration;
128

            
129
    TcpKeepalive::new()
130
        .with_time(Duration::from_secs(30))
131
        .with_interval(Duration::from_secs(30))
132
        .with_retries(3)
133
}
134

            
135
#[must_use]
136
#[cfg(all(feature = "socket", target_os = "redox"))]
137
pub fn tcp_keep_alive() -> TcpKeepalive {
138
    use std::time::Duration;
139

            
140
    TcpKeepalive::new().with_time(Duration::from_secs(30))
141
}