onc_rpc/reply/
rejected_reply.rs1use std::{
2 convert::TryFrom,
3 io::{Cursor, Write},
4};
5
6use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
7
8use crate::Error;
9
10const REJECTED_RPC_MISMATCH: u32 = 0;
11const REJECTED_AUTH_ERROR: u32 = 1;
12
13const AUTH_ERROR_SUCCESS: u32 = 0;
14const AUTH_ERROR_BADCRED: u32 = 1;
15const AUTH_ERROR_REJECTEDCRED: u32 = 2;
16const AUTH_ERROR_BADVERF: u32 = 3;
17const AUTH_ERROR_REJECTEDVERF: u32 = 4;
18const AUTH_ERROR_TOOWEAK: u32 = 5;
19const AUTH_ERROR_INVALIDRESP: u32 = 6;
20const AUTH_ERROR_FAILED: u32 = 7;
21
22#[derive(Debug, PartialEq)]
24pub enum RejectedReply {
25 RpcVersionMismatch {
29 low: u32,
31 high: u32,
33 },
34
35 AuthError(AuthError),
38}
39
40impl RejectedReply {
41 pub(crate) fn from_cursor(r: &mut Cursor<&[u8]>) -> Result<Self, Error> {
47 let reply = match r.read_u32::<BigEndian>()? {
48 REJECTED_RPC_MISMATCH => Self::RpcVersionMismatch {
49 low: r.read_u32::<BigEndian>()?,
50 high: r.read_u32::<BigEndian>()?,
51 },
52 REJECTED_AUTH_ERROR => Self::AuthError(AuthError::from_cursor(r)?),
53 v => return Err(Error::InvalidRejectedReplyType(v)),
54 };
55
56 Ok(reply)
57 }
58
59 pub fn serialise_into<W: Write>(&self, mut buf: W) -> Result<(), std::io::Error> {
62 match self {
63 Self::RpcVersionMismatch { low: l, high: h } => {
64 buf.write_u32::<BigEndian>(REJECTED_RPC_MISMATCH)?;
65 buf.write_u32::<BigEndian>(*l)?;
66 buf.write_u32::<BigEndian>(*h)
67 }
68 Self::AuthError(err) => {
69 buf.write_u32::<BigEndian>(REJECTED_AUTH_ERROR)?;
70 err.serialise_into(buf)
71 }
72 }
73 }
74
75 pub fn serialised_len(&self) -> u32 {
77 let mut len = 0;
78
79 len += 4;
81
82 len += match self {
84 Self::RpcVersionMismatch {
85 low: _low,
86 high: _high,
87 } => {
88 4 + 4
90 }
91 Self::AuthError(e) => e.serialised_len(),
92 };
93
94 len
95 }
96}
97
98impl TryFrom<&[u8]> for RejectedReply {
99 type Error = Error;
100
101 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
102 let mut c = Cursor::new(v);
103 Self::from_cursor(&mut c)
104 }
105}
106
107#[cfg(feature = "bytes")]
108impl TryFrom<crate::Bytes> for RejectedReply {
109 type Error = Error;
110
111 fn try_from(mut v: crate::Bytes) -> Result<Self, Self::Error> {
112 use crate::bytes_ext::BytesReaderExt;
113
114 let reply = match v.try_u32()? {
115 REJECTED_RPC_MISMATCH => Self::RpcVersionMismatch {
116 low: v.try_u32()?,
117 high: v.try_u32()?,
118 },
119 REJECTED_AUTH_ERROR => Self::AuthError(AuthError::try_from(v)?),
120 v => return Err(Error::InvalidRejectedReplyType(v)),
121 };
122
123 Ok(reply)
124 }
125}
126
127#[derive(Debug, PartialEq, Clone)]
130pub enum AuthError {
131 Success,
133
134 BadCredentials,
138
139 RejectedCredentials,
148
149 BadVerifier,
153
154 RejectedVerifier,
158
159 TooWeak,
163
164 InvalidResponseVerifier,
168
169 Failed,
173}
174
175impl AuthError {
176 pub(crate) fn from_cursor(r: &mut Cursor<&[u8]>) -> Result<Self, Error> {
177 let reply = match r.read_u32::<BigEndian>()? {
178 AUTH_ERROR_SUCCESS => Self::Success,
179 AUTH_ERROR_BADCRED => Self::BadCredentials,
180 AUTH_ERROR_REJECTEDCRED => Self::RejectedCredentials,
181 AUTH_ERROR_BADVERF => Self::BadVerifier,
182 AUTH_ERROR_REJECTEDVERF => Self::RejectedVerifier,
183 AUTH_ERROR_TOOWEAK => Self::TooWeak,
184 AUTH_ERROR_INVALIDRESP => Self::InvalidResponseVerifier,
185 AUTH_ERROR_FAILED => Self::Failed,
186 v => return Err(Error::InvalidAuthError(v)),
187 };
188
189 Ok(reply)
190 }
191
192 pub fn serialise_into<W: Write>(&self, mut buf: W) -> Result<(), std::io::Error> {
195 let id = match self {
196 Self::Success => AUTH_ERROR_SUCCESS,
197 Self::BadCredentials => AUTH_ERROR_BADCRED,
198 Self::RejectedCredentials => AUTH_ERROR_REJECTEDCRED,
199 Self::BadVerifier => AUTH_ERROR_BADVERF,
200 Self::RejectedVerifier => AUTH_ERROR_REJECTEDVERF,
201 Self::TooWeak => AUTH_ERROR_TOOWEAK,
202 Self::InvalidResponseVerifier => AUTH_ERROR_INVALIDRESP,
203 Self::Failed => AUTH_ERROR_FAILED,
204 };
205
206 buf.write_u32::<BigEndian>(id)
207 }
208
209 pub fn serialised_len(&self) -> u32 {
211 4
212 }
213}
214
215#[cfg(feature = "bytes")]
216impl TryFrom<crate::Bytes> for AuthError {
217 type Error = Error;
218
219 fn try_from(mut v: crate::Bytes) -> Result<Self, Self::Error> {
220 use crate::bytes_ext::BytesReaderExt;
221
222 let reply = match v.try_u32()? {
223 AUTH_ERROR_SUCCESS => Self::Success,
224 AUTH_ERROR_BADCRED => Self::BadCredentials,
225 AUTH_ERROR_REJECTEDCRED => Self::RejectedCredentials,
226 AUTH_ERROR_BADVERF => Self::BadVerifier,
227 AUTH_ERROR_REJECTEDVERF => Self::RejectedVerifier,
228 AUTH_ERROR_TOOWEAK => Self::TooWeak,
229 AUTH_ERROR_INVALIDRESP => Self::InvalidResponseVerifier,
230 AUTH_ERROR_FAILED => Self::Failed,
231 v => return Err(Error::InvalidAuthError(v)),
232 };
233
234 Ok(reply)
235 }
236}