@desklink/host 0.5.3 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +33 -19
  2. package/dist/bridge.js +3 -3
  3. package/dist/bridge.js.map +1 -1
  4. package/dist/engineProcess.d.ts +5 -0
  5. package/dist/engineProcess.d.ts.map +1 -1
  6. package/dist/engineProcess.js +6 -3
  7. package/dist/engineProcess.js.map +1 -1
  8. package/dist/protocol.d.ts +39 -0
  9. package/dist/protocol.d.ts.map +1 -1
  10. package/dist/protocol.js.map +1 -1
  11. package/docs/BOUNDARY.md +4 -2
  12. package/docs/PROTOCOL.md +70 -7
  13. package/engine/Cargo.lock +6 -8
  14. package/engine/Cargo.toml +13 -1
  15. package/engine/src/audio.rs +398 -0
  16. package/engine/src/clipboard.rs +0 -34
  17. package/engine/src/convert.rs +0 -170
  18. package/engine/src/cursor.rs +0 -23
  19. package/engine/src/input.rs +0 -65
  20. package/engine/src/input_mac.rs +0 -11
  21. package/engine/src/keeper.rs +0 -137
  22. package/engine/src/keymap.rs +0 -107
  23. package/engine/src/keymap_mac.rs +0 -25
  24. package/engine/src/mac.rs +1 -28
  25. package/engine/src/main.rs +22 -0
  26. package/engine/src/peer.rs +297 -0
  27. package/engine/src/portal.rs +0 -18
  28. package/engine/src/protocol.rs +22 -162
  29. package/engine/src/session.rs +176 -3
  30. package/engine/src/win.rs +1 -0
  31. package/engine/src/x11.rs +0 -13
  32. package/engine/vendor/rtc-ice/Cargo.toml +137 -0
  33. package/engine/vendor/rtc-ice/DESKLINK-PATCH.md +111 -0
  34. package/engine/vendor/rtc-ice/LICENSE-APACHE +201 -0
  35. package/engine/vendor/rtc-ice/LICENSE-MIT +21 -0
  36. package/engine/vendor/rtc-ice/README.md +30 -0
  37. package/engine/vendor/rtc-ice/examples/ping_pong.rs +376 -0
  38. package/engine/vendor/rtc-ice/src/agent/agent_config.rs +126 -0
  39. package/engine/vendor/rtc-ice/src/agent/agent_proto.rs +172 -0
  40. package/engine/vendor/rtc-ice/src/agent/agent_selector.rs +647 -0
  41. package/engine/vendor/rtc-ice/src/agent/agent_stats.rs +292 -0
  42. package/engine/vendor/rtc-ice/src/agent/agent_test.rs +3594 -0
  43. package/engine/vendor/rtc-ice/src/agent/mod.rs +1753 -0
  44. package/engine/vendor/rtc-ice/src/attributes/control/control_test.rs +168 -0
  45. package/engine/vendor/rtc-ice/src/attributes/control/mod.rs +142 -0
  46. package/engine/vendor/rtc-ice/src/attributes/mod.rs +6 -0
  47. package/engine/vendor/rtc-ice/src/attributes/priority/mod.rs +37 -0
  48. package/engine/vendor/rtc-ice/src/attributes/priority/priority_test.rs +39 -0
  49. package/engine/vendor/rtc-ice/src/attributes/use_candidate/mod.rs +33 -0
  50. package/engine/vendor/rtc-ice/src/attributes/use_candidate/use_candidate_test.rs +19 -0
  51. package/engine/vendor/rtc-ice/src/candidate/candidate_host.rs +53 -0
  52. package/engine/vendor/rtc-ice/src/candidate/candidate_pair.rs +215 -0
  53. package/engine/vendor/rtc-ice/src/candidate/candidate_pair_test.rs +201 -0
  54. package/engine/vendor/rtc-ice/src/candidate/candidate_peer_reflexive.rs +49 -0
  55. package/engine/vendor/rtc-ice/src/candidate/candidate_relay.rs +53 -0
  56. package/engine/vendor/rtc-ice/src/candidate/candidate_relay_test.rs +114 -0
  57. package/engine/vendor/rtc-ice/src/candidate/candidate_server_reflexive.rs +53 -0
  58. package/engine/vendor/rtc-ice/src/candidate/candidate_server_reflexive_test.rs +91 -0
  59. package/engine/vendor/rtc-ice/src/candidate/candidate_test.rs +540 -0
  60. package/engine/vendor/rtc-ice/src/candidate/mod.rs +679 -0
  61. package/engine/vendor/rtc-ice/src/dl_trace.rs +49 -0
  62. package/engine/vendor/rtc-ice/src/lib.rs +88 -0
  63. package/engine/vendor/rtc-ice/src/mdns/mdns_test.rs +150 -0
  64. package/engine/vendor/rtc-ice/src/mdns/mod.rs +69 -0
  65. package/engine/vendor/rtc-ice/src/network_type/mod.rs +162 -0
  66. package/engine/vendor/rtc-ice/src/network_type/network_type_test.rs +95 -0
  67. package/engine/vendor/rtc-ice/src/rand/mod.rs +91 -0
  68. package/engine/vendor/rtc-ice/src/rand/rand_test.rs +115 -0
  69. package/engine/vendor/rtc-ice/src/state/mod.rs +106 -0
  70. package/engine/vendor/rtc-ice/src/state/state_test.rs +46 -0
  71. package/engine/vendor/rtc-ice/src/stats/mod.rs +166 -0
  72. package/engine/vendor/rtc-ice/src/tcp_type/mod.rs +47 -0
  73. package/engine/vendor/rtc-ice/src/tcp_type/tcp_type_test.rs +18 -0
  74. package/engine/vendor/rtc-ice/src/url/mod.rs +266 -0
  75. package/engine/vendor/rtc-ice/src/url/url_test.rs +142 -0
  76. package/package.json +8 -3
@@ -0,0 +1,168 @@
1
+ use super::*;
2
+ use shared::error::{Error, Result};
3
+
4
+ #[test]
5
+ fn test_controlled_get_from() -> Result<()> {
6
+ let mut m = Message::new();
7
+ let mut c = AttrControlled(4321);
8
+ let result = c.get_from(&m);
9
+ if let Err(err) = result {
10
+ assert_eq!(Error::ErrAttributeNotFound, err, "unexpected error");
11
+ } else {
12
+ panic!("expected error, but got ok");
13
+ }
14
+
15
+ m.build(&[Box::new(BINDING_REQUEST), Box::new(c)])?;
16
+
17
+ let mut m1 = Message::new();
18
+ m1.write(&m.raw)?;
19
+
20
+ let mut c1 = AttrControlled::default();
21
+ c1.get_from(&m1)?;
22
+
23
+ assert_eq!(c1, c, "not equal");
24
+
25
+ //"IncorrectSize"
26
+ {
27
+ let mut m3 = Message::new();
28
+ m3.add(ATTR_ICE_CONTROLLED, &[0; 100]);
29
+ let mut c2 = AttrControlled::default();
30
+ let result = c2.get_from(&m3);
31
+ if let Err(err) = result {
32
+ assert!(is_attr_size_invalid(&err), "should error");
33
+ } else {
34
+ panic!("expected error, but got ok");
35
+ }
36
+ }
37
+
38
+ Ok(())
39
+ }
40
+
41
+ #[test]
42
+ fn test_controlling_get_from() -> Result<()> {
43
+ let mut m = Message::new();
44
+ let mut c = AttrControlling(4321);
45
+ let result = c.get_from(&m);
46
+ if let Err(err) = result {
47
+ assert_eq!(Error::ErrAttributeNotFound, err, "unexpected error");
48
+ } else {
49
+ panic!("expected error, but got ok");
50
+ }
51
+
52
+ m.build(&[Box::new(BINDING_REQUEST), Box::new(c)])?;
53
+
54
+ let mut m1 = Message::new();
55
+ m1.write(&m.raw)?;
56
+
57
+ let mut c1 = AttrControlling::default();
58
+ c1.get_from(&m1)?;
59
+
60
+ assert_eq!(c1, c, "not equal");
61
+
62
+ //"IncorrectSize"
63
+ {
64
+ let mut m3 = Message::new();
65
+ m3.add(ATTR_ICE_CONTROLLING, &[0; 100]);
66
+ let mut c2 = AttrControlling::default();
67
+ let result = c2.get_from(&m3);
68
+ if let Err(err) = result {
69
+ assert!(is_attr_size_invalid(&err), "should error");
70
+ } else {
71
+ panic!("expected error, but got ok");
72
+ }
73
+ }
74
+
75
+ Ok(())
76
+ }
77
+
78
+ #[test]
79
+ fn test_control_get_from() -> Result<()> {
80
+ //"Blank"
81
+ {
82
+ let m = Message::new();
83
+ let mut c = AttrControl::default();
84
+ let result = c.get_from(&m);
85
+ if let Err(err) = result {
86
+ assert_eq!(Error::ErrAttributeNotFound, err, "unexpected error");
87
+ } else {
88
+ panic!("expected error, but got ok");
89
+ }
90
+ }
91
+ //"Controlling"
92
+ {
93
+ let mut m = Message::new();
94
+ let mut c = AttrControl::default();
95
+ let result = c.get_from(&m);
96
+ if let Err(err) = result {
97
+ assert_eq!(Error::ErrAttributeNotFound, err, "unexpected error");
98
+ } else {
99
+ panic!("expected error, but got ok");
100
+ }
101
+
102
+ c.role = Role::Controlling;
103
+ c.tie_breaker = TieBreaker(4321);
104
+
105
+ m.build(&[Box::new(BINDING_REQUEST), Box::new(c)])?;
106
+
107
+ let mut m1 = Message::new();
108
+ m1.write(&m.raw)?;
109
+
110
+ let mut c1 = AttrControl::default();
111
+ c1.get_from(&m1)?;
112
+
113
+ assert_eq!(c1, c, "not equal");
114
+
115
+ //"IncorrectSize"
116
+ {
117
+ let mut m3 = Message::new();
118
+ m3.add(ATTR_ICE_CONTROLLING, &[0; 100]);
119
+ let mut c2 = AttrControl::default();
120
+ let result = c2.get_from(&m3);
121
+ if let Err(err) = result {
122
+ assert!(is_attr_size_invalid(&err), "should error");
123
+ } else {
124
+ panic!("expected error, but got ok");
125
+ }
126
+ }
127
+ }
128
+
129
+ //"Controlled"
130
+ {
131
+ let mut m = Message::new();
132
+ let mut c = AttrControl::default();
133
+ let result = c.get_from(&m);
134
+ if let Err(err) = result {
135
+ assert_eq!(Error::ErrAttributeNotFound, err, "unexpected error");
136
+ } else {
137
+ panic!("expected error, but got ok");
138
+ }
139
+
140
+ c.role = Role::Controlled;
141
+ c.tie_breaker = TieBreaker(1234);
142
+
143
+ m.build(&[Box::new(BINDING_REQUEST), Box::new(c)])?;
144
+
145
+ let mut m1 = Message::new();
146
+ m1.write(&m.raw)?;
147
+
148
+ let mut c1 = AttrControl::default();
149
+ c1.get_from(&m1)?;
150
+
151
+ assert_eq!(c1, c, "not equal");
152
+
153
+ //"IncorrectSize"
154
+ {
155
+ let mut m3 = Message::new();
156
+ m3.add(ATTR_ICE_CONTROLLING, &[0; 100]);
157
+ let mut c2 = AttrControl::default();
158
+ let result = c2.get_from(&m3);
159
+ if let Err(err) = result {
160
+ assert!(is_attr_size_invalid(&err), "should error");
161
+ } else {
162
+ panic!("expected error, but got ok");
163
+ }
164
+ }
165
+ }
166
+
167
+ Ok(())
168
+ }
@@ -0,0 +1,142 @@
1
+ #[cfg(test)]
2
+ mod control_test;
3
+
4
+ use std::fmt;
5
+
6
+ use shared::error::*;
7
+ use stun::attributes::*;
8
+ use stun::checks::*;
9
+ use stun::message::*;
10
+
11
+ /// Common helper for ICE-{CONTROLLED,CONTROLLING} and represents the so-called Tiebreaker number.
12
+ #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
13
+ pub struct TieBreaker(pub u64);
14
+
15
+ pub(crate) const TIE_BREAKER_SIZE: usize = 8; // 64 bit
16
+
17
+ impl TieBreaker {
18
+ /// Adds Tiebreaker value to m as t attribute.
19
+ pub fn add_to_as(self, m: &mut Message, t: AttrType) -> Result<()> {
20
+ let mut v = vec![0; TIE_BREAKER_SIZE];
21
+ v.copy_from_slice(&self.0.to_be_bytes());
22
+ m.add(t, &v);
23
+ Ok(())
24
+ }
25
+
26
+ /// Decodes Tiebreaker value in message getting it as for t type.
27
+ pub fn get_from_as(&mut self, m: &Message, t: AttrType) -> Result<()> {
28
+ let v = m.get(t)?;
29
+ check_size(t, v.len(), TIE_BREAKER_SIZE)?;
30
+ self.0 = u64::from_be_bytes([v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]]);
31
+ Ok(())
32
+ }
33
+ }
34
+ /// Represents ICE-CONTROLLED attribute.
35
+ #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
36
+ pub struct AttrControlled(pub u64);
37
+
38
+ impl Setter for AttrControlled {
39
+ /// Adds ICE-CONTROLLED to message.
40
+ fn add_to(&self, m: &mut Message) -> Result<()> {
41
+ TieBreaker(self.0).add_to_as(m, ATTR_ICE_CONTROLLED)
42
+ }
43
+ }
44
+
45
+ impl Getter for AttrControlled {
46
+ /// Decodes ICE-CONTROLLED from message.
47
+ fn get_from(&mut self, m: &Message) -> Result<()> {
48
+ let mut t = TieBreaker::default();
49
+ t.get_from_as(m, ATTR_ICE_CONTROLLED)?;
50
+ self.0 = t.0;
51
+ Ok(())
52
+ }
53
+ }
54
+
55
+ /// Represents ICE-CONTROLLING attribute.
56
+ #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
57
+ pub struct AttrControlling(pub u64);
58
+
59
+ impl Setter for AttrControlling {
60
+ // add_to adds ICE-CONTROLLING to message.
61
+ fn add_to(&self, m: &mut Message) -> Result<()> {
62
+ TieBreaker(self.0).add_to_as(m, ATTR_ICE_CONTROLLING)
63
+ }
64
+ }
65
+
66
+ impl Getter for AttrControlling {
67
+ // get_from decodes ICE-CONTROLLING from message.
68
+ fn get_from(&mut self, m: &Message) -> Result<()> {
69
+ let mut t = TieBreaker::default();
70
+ t.get_from_as(m, ATTR_ICE_CONTROLLING)?;
71
+ self.0 = t.0;
72
+ Ok(())
73
+ }
74
+ }
75
+
76
+ /// Helper that wraps ICE-{CONTROLLED,CONTROLLING}.
77
+ #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
78
+ pub struct AttrControl {
79
+ role: Role,
80
+ tie_breaker: TieBreaker,
81
+ }
82
+
83
+ impl Setter for AttrControl {
84
+ // add_to adds ICE-CONTROLLED or ICE-CONTROLLING attribute depending on Role.
85
+ fn add_to(&self, m: &mut Message) -> Result<()> {
86
+ if self.role == Role::Controlling {
87
+ self.tie_breaker.add_to_as(m, ATTR_ICE_CONTROLLING)
88
+ } else {
89
+ self.tie_breaker.add_to_as(m, ATTR_ICE_CONTROLLED)
90
+ }
91
+ }
92
+ }
93
+
94
+ impl Getter for AttrControl {
95
+ // get_from decodes Role and Tiebreaker value from message.
96
+ fn get_from(&mut self, m: &Message) -> Result<()> {
97
+ if m.contains(ATTR_ICE_CONTROLLING) {
98
+ self.role = Role::Controlling;
99
+ return self.tie_breaker.get_from_as(m, ATTR_ICE_CONTROLLING);
100
+ }
101
+ if m.contains(ATTR_ICE_CONTROLLED) {
102
+ self.role = Role::Controlled;
103
+ return self.tie_breaker.get_from_as(m, ATTR_ICE_CONTROLLED);
104
+ }
105
+
106
+ Err(Error::ErrAttributeNotFound)
107
+ }
108
+ }
109
+
110
+ /// Represents ICE agent role, which can be controlling or controlled.
111
+ /// Possible ICE agent roles.
112
+ #[derive(Default, PartialEq, Eq, Copy, Clone, Debug)]
113
+ pub enum Role {
114
+ #[default]
115
+ /// This agent is controlling.
116
+ Controlling,
117
+ /// This agent is controlled.
118
+ Controlled,
119
+ /// No role attribute was present.
120
+ Unspecified,
121
+ }
122
+
123
+ impl From<&str> for Role {
124
+ fn from(raw: &str) -> Self {
125
+ match raw {
126
+ "controlling" => Self::Controlling,
127
+ "controlled" => Self::Controlled,
128
+ _ => Self::Unspecified,
129
+ }
130
+ }
131
+ }
132
+
133
+ impl fmt::Display for Role {
134
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135
+ let s = match *self {
136
+ Self::Controlling => "controlling",
137
+ Self::Controlled => "controlled",
138
+ Self::Unspecified => "unspecified",
139
+ };
140
+ write!(f, "{s}")
141
+ }
142
+ }
@@ -0,0 +1,6 @@
1
+ /// `ICE-CONTROLLING` and `ICE-CONTROLLED`, which resolve role conflicts.
2
+ pub mod control;
3
+ /// The `PRIORITY` attribute carried in connectivity checks.
4
+ pub mod priority;
5
+ /// The `USE-CANDIDATE` flag, by which the controlling agent nominates a pair.
6
+ pub mod use_candidate;
@@ -0,0 +1,37 @@
1
+ #[cfg(test)]
2
+ mod priority_test;
3
+
4
+ use shared::error::*;
5
+ use stun::attributes::ATTR_PRIORITY;
6
+ use stun::checks::*;
7
+ use stun::message::*;
8
+
9
+ /// Represents PRIORITY attribute.
10
+ #[derive(Default, PartialEq, Eq, Debug, Copy, Clone)]
11
+ pub struct PriorityAttr(pub u32);
12
+
13
+ const PRIORITY_SIZE: usize = 4; // 32 bit
14
+
15
+ impl Setter for PriorityAttr {
16
+ // add_to adds PRIORITY attribute to message.
17
+ fn add_to(&self, m: &mut Message) -> Result<()> {
18
+ let mut v = vec![0_u8; PRIORITY_SIZE];
19
+ v.copy_from_slice(&self.0.to_be_bytes());
20
+ m.add(ATTR_PRIORITY, &v);
21
+ Ok(())
22
+ }
23
+ }
24
+
25
+ impl PriorityAttr {
26
+ /// Decodes PRIORITY attribute from message.
27
+ pub fn get_from(&mut self, m: &Message) -> Result<()> {
28
+ let v = m.get(ATTR_PRIORITY)?;
29
+
30
+ check_size(ATTR_PRIORITY, v.len(), PRIORITY_SIZE)?;
31
+
32
+ let p = u32::from_be_bytes([v[0], v[1], v[2], v[3]]);
33
+ self.0 = p;
34
+
35
+ Ok(())
36
+ }
37
+ }
@@ -0,0 +1,39 @@
1
+ use super::*;
2
+ use shared::error::{Error, Result};
3
+
4
+ #[test]
5
+ fn test_priority_get_from() -> Result<()> {
6
+ let mut m = Message::new();
7
+ let mut p = PriorityAttr::default();
8
+ let result = p.get_from(&m);
9
+ if let Err(err) = result {
10
+ assert_eq!(err, Error::ErrAttributeNotFound, "unexpected error");
11
+ } else {
12
+ panic!("expected error, but got ok");
13
+ }
14
+
15
+ m.build(&[Box::new(BINDING_REQUEST), Box::new(p)])?;
16
+
17
+ let mut m1 = Message::new();
18
+ m1.write(&m.raw)?;
19
+
20
+ let mut p1 = PriorityAttr::default();
21
+ p1.get_from(&m1)?;
22
+
23
+ assert_eq!(p1, p, "not equal");
24
+
25
+ //"IncorrectSize"
26
+ {
27
+ let mut m3 = Message::new();
28
+ m3.add(ATTR_PRIORITY, &[0; 100]);
29
+ let mut p2 = PriorityAttr::default();
30
+ let result = p2.get_from(&m3);
31
+ if let Err(err) = result {
32
+ assert!(is_attr_size_invalid(&err), "should error");
33
+ } else {
34
+ panic!("expected error, but got ok");
35
+ }
36
+ }
37
+
38
+ Ok(())
39
+ }
@@ -0,0 +1,33 @@
1
+ #[cfg(test)]
2
+ mod use_candidate_test;
3
+
4
+ use shared::error::*;
5
+ use stun::attributes::ATTR_USE_CANDIDATE;
6
+ use stun::message::*;
7
+
8
+ /// Represents USE-CANDIDATE attribute.
9
+ #[derive(Default)]
10
+ pub struct UseCandidateAttr;
11
+
12
+ impl Setter for UseCandidateAttr {
13
+ /// Adds USE-CANDIDATE attribute to message.
14
+ fn add_to(&self, m: &mut Message) -> Result<()> {
15
+ m.add(ATTR_USE_CANDIDATE, &[]);
16
+ Ok(())
17
+ }
18
+ }
19
+
20
+ impl UseCandidateAttr {
21
+ #[must_use]
22
+ /// A `USE-CANDIDATE` attribute, which carries no value.
23
+ pub const fn new() -> Self {
24
+ Self
25
+ }
26
+
27
+ /// Returns true if USE-CANDIDATE attribute is set.
28
+ #[must_use]
29
+ pub fn is_set(m: &Message) -> bool {
30
+ let result = m.get(ATTR_USE_CANDIDATE);
31
+ result.is_ok()
32
+ }
33
+ }
@@ -0,0 +1,19 @@
1
+ use stun::message::BINDING_REQUEST;
2
+
3
+ use super::*;
4
+ use shared::error::Result;
5
+
6
+ #[test]
7
+ fn test_use_candidate_attr_add_to() -> Result<()> {
8
+ let mut m = Message::new();
9
+ assert!(!UseCandidateAttr::is_set(&m), "should not be set");
10
+
11
+ m.build(&[Box::new(BINDING_REQUEST), Box::new(UseCandidateAttr::new())])?;
12
+
13
+ let mut m1 = Message::new();
14
+ m1.write(&m.raw)?;
15
+
16
+ assert!(UseCandidateAttr::is_set(&m1), "should be set");
17
+
18
+ Ok(())
19
+ }
@@ -0,0 +1,53 @@
1
+ use super::*;
2
+ use crate::rand::generate_cand_id;
3
+
4
+ /// The config required to create a new `CandidateHost`.
5
+ #[derive(Default)]
6
+ pub struct CandidateHostConfig {
7
+ /// The fields shared by every candidate type.
8
+ pub base_config: CandidateConfig,
9
+
10
+ /// The TCP role, for ICE-TCP host candidates.
11
+ pub tcp_type: TcpType,
12
+ }
13
+
14
+ impl CandidateHostConfig {
15
+ /// Creates a new host candidate.
16
+ pub fn new_candidate_host(self) -> Result<Candidate> {
17
+ let mut candidate_id = self.base_config.candidate_id;
18
+ if candidate_id.is_empty() {
19
+ candidate_id = generate_cand_id();
20
+ }
21
+
22
+ let (resolved_addr, network_type) = if !self.base_config.address.ends_with(".local") {
23
+ let ip: IpAddr = match self.base_config.address.parse() {
24
+ Ok(ip) => ip,
25
+ Err(_) => return Err(Error::ErrAddressParseFailed),
26
+ };
27
+ (
28
+ SocketAddr::new(ip, self.base_config.port),
29
+ determine_network_type(&self.base_config.network, &ip)?,
30
+ )
31
+ } else {
32
+ (
33
+ SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 0),
34
+ NetworkType::Udp4,
35
+ )
36
+ };
37
+
38
+ Ok(Candidate {
39
+ id: candidate_id,
40
+ network_type,
41
+ candidate_type: CandidateType::Host,
42
+ address: self.base_config.address,
43
+ port: self.base_config.port,
44
+ resolved_addr,
45
+ component: self.base_config.component,
46
+ foundation_override: self.base_config.foundation,
47
+ priority_override: self.base_config.priority,
48
+ network: self.base_config.network,
49
+ tcp_type: self.tcp_type,
50
+ ..Candidate::default()
51
+ })
52
+ }
53
+ }