Skip to content

Commit 7af817f

Browse files
committed
Merge branch 'relay-selector-api'
2 parents 3ce83ea + a84e839 commit 7af817f

File tree

3 files changed

+166
-3
lines changed

3 files changed

+166
-3
lines changed

mullvad-management-interface/build.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
fn main() {
2-
tonic_build::compile_protos("proto/management_interface.proto").unwrap();
2+
// Compile both proto files together so they can reference each other
3+
tonic_build::configure()
4+
.compile_protos(
5+
&[
6+
"proto/management_interface.proto",
7+
"proto/relay_selector.proto",
8+
],
9+
&["proto/"],
10+
)
11+
.unwrap();
312

413
// Enable DAITA by default on desktop and android
514
println!("cargo::rustc-check-cfg=cfg(daita)");
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Relay Selector service.
2+
//
3+
// This API is used to query which relays are selectable for a set of filters,
4+
// and to provide information about about how to unblock discarded relays.
5+
6+
syntax = "proto3";
7+
package mullvad_daemon.relay_selector;
8+
9+
import "management_interface.proto";
10+
11+
service RelaySelectorService {
12+
// Partition the available relays by a predicate. The predicate can be
13+
// derived from the current settings or a set of future settings changes
14+
// before they are applied.
15+
//
16+
// Returns a list of matching relays. For each connection using the given
17+
// constraints, one/a pair of these relays will be selected at random.
18+
//
19+
// Also returns a list of non-matching relays along with the set of
20+
// constraints/conditions that made them unavailable.
21+
rpc PartitionRelays(Predicate) returns (RelayPartitions);
22+
}
23+
24+
// Predicate for selecting relays.
25+
//
26+
// This message is used to specify the constraints that should be applied
27+
// when selecting relays, along with a context that may affect the selection
28+
// behavior.
29+
message Predicate {
30+
oneof context {
31+
// Get matching relays for singlehop configuration.
32+
EntryConstraints singlehop = 1;
33+
// Get matching relays with automatic multihop when necessary.
34+
//
35+
// If the entry-specific constraints are not met for a given relay but an alternative
36+
// entry node can be selected that matches the constraints, the relay will still be
37+
// returned as a viable exit node. Connecting to the relay will result in a implicit
38+
// multihop connection.
39+
EntryConstraints autohop = 2;
40+
// Get matching entry relays for multihop.
41+
MultiHopConstraints entry = 3;
42+
// Get matching exit relays for multihop.
43+
MultiHopConstraints exit = 4;
44+
}
45+
}
46+
47+
// Constraints that apply to relays for singlehop or the first hop
48+
// in a multihop configuration.
49+
//
50+
// These include all the of `ExitConstraints`, and a few entry
51+
// specific features.
52+
message EntryConstraints {
53+
ExitConstraints general_constraints = 1;
54+
// -- Entry specific constraints --
55+
management_interface.ObfuscationSettings obfuscation_settings = 2;
56+
management_interface.DaitaSettings daita_settings = 3;
57+
management_interface.IpVersion ip_version = 4;
58+
}
59+
60+
// Constraints that apply to the second hop in a multihop configuration.
61+
// This is a subset of `EntryConstraints`.
62+
message ExitConstraints {
63+
management_interface.LocationConstraint location = 1;
64+
repeated Provider providers = 2;
65+
management_interface.Ownership ownership = 3;
66+
}
67+
68+
// Constraints for both hops in a multihop configuration.
69+
message MultiHopConstraints {
70+
EntryConstraints entry = 1;
71+
ExitConstraints exit = 2;
72+
}
73+
74+
// The result of the relay selection algorithm.
75+
//
76+
// Contains the list of relays matching a predicate and the list of relays
77+
// that were discarded when evaluating a predicate.
78+
message RelayPartitions {
79+
// List of relays matching a predicate.
80+
repeated Relay matches = 1;
81+
// List of relays that were discarded when evaluating the same predicate.
82+
repeated DiscardedRelay discards = 2;
83+
}
84+
85+
// A relay from the relay list.
86+
message Relay {
87+
// A hostname that uniquely identifies a single VPN relay.
88+
//
89+
// It is the full hostname, e.g. `se-got-wg-101`.
90+
// This can *NOT* be a location, e.g. `se` or `se-got`.
91+
string hostname = 1;
92+
}
93+
94+
// A relay which was discarded when evaluating some predicate, and why.
95+
message DiscardedRelay {
96+
// Relay that was discarded.
97+
Relay relay = 1;
98+
// The list of constraints that did not match the relay.
99+
//
100+
// This can be interpreted as a list of criteria necessary
101+
// to unblock the relay from being selectable.
102+
IncompatibleConstraints why = 2;
103+
}
104+
105+
// Set of constraints that prevents the relay from being selected.
106+
message IncompatibleConstraints {
107+
// The relay is currently offline.
108+
bool inactive = 1;
109+
// The relay does not reside in the given location.
110+
bool location = 2;
111+
// The relay is not hosted by the given provider.
112+
// TODO: Return which provider it needs? Can be looked up in the full relay list
113+
bool providers = 3;
114+
// The relay ownership does not match.
115+
bool ownership = 4;
116+
117+
// -- Entry specific constraints --
118+
119+
// The relay cannot be connected to with the requested ip version.
120+
bool ip_version = 5;
121+
// The relay does not run DAITA.
122+
bool daita = 6;
123+
// The requested obfuscation method is not available.
124+
bool obfuscation = 7;
125+
// The relay cannot be connected to via the requested port.
126+
bool port = 8;
127+
// This relay is already used for the other hop (entry/exit).
128+
bool conflict_with_other_hop = 9;
129+
}
130+
131+
// A hosting provider.
132+
message Provider {
133+
// The name of the provider.
134+
string name = 1;
135+
}
Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
11
#[expect(clippy::allow_attributes)]
22
mod proto {
3-
tonic::include_proto!("mullvad_daemon.management_interface");
3+
// The management_interface and relay_selector modules need to be siblings
4+
// to reflect the file structure of the protos.
5+
pub mod management_interface {
6+
tonic::include_proto!("mullvad_daemon.management_interface");
7+
}
8+
pub use management_interface::*;
9+
10+
pub mod relay_selector {
11+
tonic::include_proto!("mullvad_daemon.relay_selector");
12+
}
413
}
14+
pub use proto::*;
15+
516
mod conversions;
617

718
pub use prost_types::{Duration, Timestamp};
819

920
pub use conversions::*;
10-
pub use proto::*;
21+
22+
// Re-export the relay selector service types
23+
pub use proto::relay_selector::relay_selector_service_client;
24+
pub use proto::relay_selector::relay_selector_service_server;
25+
26+
// Re-export the client and server types for convenience
27+
pub type RelaySelectorServiceClient =
28+
relay_selector_service_client::RelaySelectorServiceClient<crate::Channel>;
29+
pub use relay_selector_service_server::{RelaySelectorService, RelaySelectorServiceServer};

0 commit comments

Comments
 (0)