nntp_proxy/protocol/
responses.rs1pub const CRLF: &[u8] = b"\r\n";
8
9pub const MIN_RESPONSE_LENGTH: usize = 5;
11
12pub const AUTH_REQUIRED: &[u8] = b"381 Password required\r\n";
16
17pub const AUTH_ACCEPTED: &[u8] = b"281 Authentication accepted\r\n";
19
20pub const AUTH_FAILED: &[u8] = b"481 Authentication failed\r\n";
22
23pub const AUTH_REQUIRED_FOR_COMMAND: &[u8] = b"480 Authentication required\r\n";
25
26pub const AUTH_OUT_OF_SEQUENCE: &[u8] = b"482 Authentication commands issued out of sequence\r\n";
31
32pub const AUTH_ALREADY_AUTHENTICATED: &[u8] = b"502 Already authenticated\r\n";
37
38pub const AUTH_UNKNOWN_SUBCOMMAND: &[u8] = b"501 Syntax error in command\r\n";
43
44pub const PROXY_GREETING_PCR: &[u8] = b"201 NNTP Proxy Ready (Per-Command Routing)\r\n";
48
49pub const CONNECTION_CLOSING: &[u8] = b"205 Connection closing\r\n";
51
52pub const GOODBYE: &[u8] = b"205 Goodbye\r\n";
54
55pub const POSTING_NOT_PERMITTED: &[u8] = b"440 Posting not permitted\r\n";
62
63pub const BACKEND_ERROR: &[u8] = b"503 Backend error\r\n";
65
66pub const BACKEND_UNAVAILABLE: &[u8] = b"400 Backend server unavailable\r\n";
68
69pub const COMMAND_TOO_LONG: &[u8] = b"501 Command too long\r\n";
71
72pub const COMMAND_SYNTAX_ERROR_RESPONSE: &[u8] = b"501 Syntax error in command\r\n";
74
75pub const NO_SUCH_ARTICLE: &[u8] = b"430 No such article\r\n";
77
78#[inline]
92#[must_use]
93pub fn greeting(message: &str) -> String {
94 format!("200 {message}\r\n")
95}
96
97#[inline]
99#[must_use]
100pub fn greeting_readonly(message: &str) -> String {
101 format!("201 {message}\r\n")
102}
103
104#[inline]
106#[must_use]
107pub fn ok_response(message: &str) -> String {
108 format!("200 {message}\r\n")
109}
110
111#[inline]
121#[must_use]
122pub fn error_response(code: u16, message: &str) -> String {
123 format!("{code} {message}\r\n")
124}
125
126#[inline]
128#[must_use]
129pub fn response(code: u16, message: &str) -> String {
130 format!("{code} {message}\r\n")
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_constants() {
139 assert_eq!(CRLF, b"\r\n");
140 }
141
142 #[test]
143 fn test_greeting() {
144 assert_eq!(greeting("Ready"), "200 Ready\r\n");
145 assert_eq!(
146 greeting("news.example.com ready"),
147 "200 news.example.com ready\r\n"
148 );
149 assert_eq!(greeting_readonly("Read only"), "201 Read only\r\n");
150 }
151
152 #[test]
153 fn test_ok_response() {
154 assert_eq!(ok_response("OK"), "200 OK\r\n");
155 assert_eq!(ok_response("Command accepted"), "200 Command accepted\r\n");
156 }
157
158 #[test]
159 fn test_error_response() {
160 assert_eq!(
161 error_response(430, "No such article"),
162 "430 No such article\r\n"
163 );
164 assert_eq!(
165 error_response(500, "Command not recognized"),
166 "500 Command not recognized\r\n"
167 );
168 }
169
170 #[test]
171 fn test_response() {
172 assert_eq!(
173 response(215, "Newsgroups follow"),
174 "215 Newsgroups follow\r\n"
175 );
176 assert_eq!(
177 response(381, "Password required"),
178 "381 Password required\r\n"
179 );
180 }
181
182 #[test]
183 fn test_auth_constants() {
184 assert_eq!(AUTH_REQUIRED, b"381 Password required\r\n");
185 assert_eq!(AUTH_ACCEPTED, b"281 Authentication accepted\r\n");
186 assert_eq!(AUTH_FAILED, b"481 Authentication failed\r\n");
187 assert_eq!(
188 AUTH_REQUIRED_FOR_COMMAND,
189 b"480 Authentication required\r\n"
190 );
191 }
192
193 #[test]
194 fn test_standard_responses() {
195 assert!(PROXY_GREETING_PCR.starts_with(b"201"));
196 assert!(CONNECTION_CLOSING.starts_with(b"205"));
197 assert!(GOODBYE.starts_with(b"205"));
198 }
199
200 #[test]
201 fn test_error_constants() {
202 assert!(POSTING_NOT_PERMITTED.starts_with(b"440"));
203 assert!(BACKEND_ERROR.starts_with(b"503"));
204 assert!(BACKEND_UNAVAILABLE.starts_with(b"400"));
205 }
206
207 #[test]
208 fn test_all_responses_end_with_crlf() {
209 assert!(AUTH_REQUIRED.ends_with(CRLF));
210 assert!(AUTH_ACCEPTED.ends_with(CRLF));
211 assert!(AUTH_FAILED.ends_with(CRLF));
212 assert!(AUTH_REQUIRED_FOR_COMMAND.ends_with(CRLF));
213 assert!(PROXY_GREETING_PCR.ends_with(CRLF));
214 assert!(CONNECTION_CLOSING.ends_with(CRLF));
215 assert!(GOODBYE.ends_with(CRLF));
216 assert!(POSTING_NOT_PERMITTED.ends_with(CRLF));
217 assert!(BACKEND_ERROR.ends_with(CRLF));
218 assert!(BACKEND_UNAVAILABLE.ends_with(CRLF));
219 }
220}