1use std::{collections::BTreeMap, fmt::Display, net::SocketAddr};
2
3use async_trait::async_trait;
4use bytes::Bytes;
5use mizaru2::{
6 BlindedClientToken, BlindedSignature, ClientToken, SingleBlindedSignature,
7 SingleUnblindedSignature, UnblindedSignature,
8};
9use nanorpc::{nanorpc_derive, JrpcRequest, JrpcResponse};
10mod route;
11pub use route::*;
12mod exit;
13pub use exit::*;
14mod signed;
15use serde::{Deserialize, Serialize};
16pub use signed::*;
17mod mac;
18pub mod puzzle;
19pub use mac::*;
20mod bridge;
21pub use bridge::*;
22use thiserror::Error;
23
24#[nanorpc_derive]
25#[async_trait]
26pub trait BrokerProtocol {
27 async fn opaque_abtest(&self, test: String, id: u64) -> bool;
28
29 async fn call_geph_payments(&self, jrpc_req: JrpcRequest)
30 -> Result<JrpcResponse, GenericError>;
31
32 async fn get_mizaru_subkey(&self, level: AccountLevel, epoch: u16) -> Bytes;
33
34 async fn get_auth_token(&self, credential: Credential) -> Result<String, AuthError>;
35 async fn get_user_info(&self, auth_token: String) -> Result<Option<UserInfo>, AuthError>;
36 async fn get_user_info_by_cred(
37 &self,
38 credential: Credential,
39 ) -> Result<Option<UserInfo>, AuthError>;
40
41 async fn get_connect_token(
42 &self,
43 auth_token: String,
44 level: AccountLevel,
45 epoch: u16,
46 blind_token: BlindedClientToken,
47 ) -> Result<BlindedSignature, AuthError>;
48
49 async fn get_bw_token(
50 &self,
51 auth_token: String,
52 blind_token: BlindedClientToken,
53 ) -> Result<SingleBlindedSignature, AuthError>;
54
55 async fn consume_bw_token(
56 &self,
57 token: ClientToken,
58 sig: SingleUnblindedSignature,
59 ) -> Result<(), AuthError>;
60
61 async fn get_exits(&self) -> Result<StdcodeSigned<ExitList>, GenericError>;
62 async fn get_free_exits(&self) -> Result<StdcodeSigned<ExitList>, GenericError>;
63
64 async fn get_net_status(&self) -> Result<JsonSigned<NetStatus>, GenericError>;
66
67 async fn get_routes(
68 &self,
69 token: ClientToken,
70 sig: UnblindedSignature,
71 exit_b2e: SocketAddr,
72 ) -> Result<RouteDescriptor, GenericError>;
73 async fn get_routes_v2(&self, args: GetRoutesArgs) -> Result<RouteDescriptor, GenericError>;
74
75 async fn insert_exit(
76 &self,
77 descriptor: Mac<StdcodeSigned<ExitDescriptor>>,
78 ) -> Result<(), GenericError>;
79
80 async fn insert_exit_v2(
81 &self,
82 descriptor: Mac<JsonSigned<(ExitDescriptor, ExitMetadata)>>,
83 ) -> Result<(), GenericError>;
84
85 async fn insert_bridge(&self, descriptor: Mac<BridgeDescriptor>) -> Result<(), GenericError>;
86
87 async fn incr_stat(&self, stat: String, value: i32);
88
89 async fn set_stat(&self, stat: String, value: f64);
90
91 async fn upload_available(&self, data: AvailabilityData);
92
93 async fn get_puzzle(&self) -> (String, u16);
94
95 async fn register_user_secret(
96 &self,
97 puzzle: String,
98 solution: String,
99 ) -> Result<String, GenericError>;
100
101 async fn upgrade_to_secret(&self, cred: Credential) -> Result<String, AuthError>;
102
103 async fn delete_account(&self, secret: String) -> Result<(), GenericError>;
104
105 async fn get_news(&self, lang: String) -> Result<Vec<LegacyNewsItem>, GenericError>;
106
107 async fn raw_price_points(&self) -> Result<Vec<(u32, u32)>, GenericError>;
108 async fn basic_price_points(&self) -> Result<Vec<(u32, u32)>, GenericError>;
109 async fn basic_mb_limit(&self) -> u32;
110
111 async fn payment_methods(&self) -> Result<Vec<String>, GenericError>;
112
113 async fn create_payment(
114 &self,
115 auth_token: String,
116 days: u32,
117 method: String,
118 ) -> Result<String, GenericError>;
119
120 async fn create_basic_payment(
121 &self,
122 auth_token: String,
123 days: u32,
124 method: String,
125 ) -> Result<String, GenericError>;
126
127 async fn get_free_voucher(&self, secret: String) -> Result<Option<VoucherInfo>, GenericError>;
128
129 async fn redeem_voucher(&self, secret: String, code: String) -> Result<i32, GenericError>;
131
132 async fn upload_debug_pack(
134 &self,
135 email: Option<String>,
136 logs: String,
137 ) -> Result<(), GenericError>;
138}
139
140#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
141pub struct VoucherInfo {
142 pub code: String,
143 pub explanation: BTreeMap<String, String>,
144}
145
146#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
147pub struct GetRoutesArgs {
148 pub token: ClientToken,
149 pub sig: UnblindedSignature,
150 pub exit_b2e: SocketAddr,
151 pub client_metadata: serde_json::Value,
152}
153
154#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
155pub struct AvailabilityData {
156 pub listen: String,
157 pub country: String,
158 pub asn: String,
159 pub success: bool,
160}
161
162#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
163pub struct UserInfo {
164 pub user_id: u64,
165 pub plus_expires_unix: Option<u64>,
166 #[serde(default)]
167 pub recurring: bool,
168 #[serde(default)]
169 pub bw_consumption: Option<BwConsumptionInfo>,
170}
171
172#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
173pub struct BwConsumptionInfo {
174 pub mb_used: u32,
175 pub mb_limit: u32,
176 pub renew_unix: u64,
177}
178
179#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)]
180pub enum AccountLevel {
181 Free,
182 Plus,
183}
184
185#[derive(Clone, Debug, Error, Serialize, Deserialize)]
186#[serde(rename_all = "snake_case")]
187pub enum AuthError {
188 #[error("rate limited")]
189 RateLimited,
190 #[error("incorrect credentials")]
191 Forbidden,
192 #[error("wrong level")]
193 WrongLevel,
194}
195
196#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
197#[serde(rename_all = "snake_case")]
198#[derive(Default)]
199pub enum Credential {
200 #[default]
201 TestDummy,
202 LegacyUsernamePassword {
203 username: String,
204 password: String,
205 },
206 Secret(String),
207}
208
209pub const DOMAIN_EXIT_DESCRIPTOR: &str = "exit-descriptor";
210
211pub const DOMAIN_NET_STATUS: &str = "net-status";
212
213#[derive(Serialize, Deserialize, Clone, Debug)]
214#[serde(transparent)]
215pub struct GenericError(pub String);
216
217impl Display for GenericError {
218 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
219 self.0.fmt(f)
220 }
221}
222
223impl<T: Into<anyhow::Error>> From<T> for GenericError {
224 fn from(value: T) -> Self {
225 Self(value.into().to_string())
226 }
227}
228
229#[derive(Serialize, Deserialize, Clone, Debug)]
230pub struct LegacyNewsItem {
231 pub title: String,
232 pub date_unix: u64,
233 pub contents: String,
234}