Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <app/icd/server/ICDServerConfig.h>
21 : #if CHIP_CONFIG_ENABLE_ICD_SERVER
22 : #include <app/icd/server/ICDManager.h> // nogncheck
23 : #endif
24 : #include <app/icd/server/ICDStateObserver.h>
25 : #include <app/server/CommissioningModeProvider.h>
26 : #include <credentials/FabricTable.h>
27 : #include <inet/InetConfig.h>
28 : #include <lib/core/CHIPError.h>
29 : #include <lib/core/Optional.h>
30 : #include <lib/dnssd/Advertiser.h>
31 : #include <platform/CHIPDeviceLayer.h>
32 : #include <stddef.h>
33 : #include <system/TimeSource.h>
34 :
35 : namespace chip {
36 : namespace app {
37 :
38 : class DLL_EXPORT DnssdServer : public ICDStateObserver
39 : {
40 : public:
41 : static constexpr System::Clock::Timestamp kTimeoutCleared = System::Clock::kZero;
42 :
43 : /// Provides the system-wide implementation of the service advertiser
44 31 : static DnssdServer & Instance()
45 : {
46 31 : static DnssdServer instance;
47 31 : return instance;
48 : }
49 :
50 : /// Sets the secure Matter IPv6 port
51 1 : void SetSecuredIPv6Port(uint16_t port) { mSecuredIPv6Port = port; }
52 :
53 : #if INET_CONFIG_ENABLE_IPV4
54 : /// Sets the secure Matter IPv4 port.
55 1 : void SetSecuredIPv4Port(uint16_t port) { mSecuredIPv4Port = port; }
56 : #endif // INET_CONFIG_ENABLE_IPV4
57 :
58 : /// Gets the secure Matter port
59 7 : uint16_t GetSecuredPort() const { return mSecuredIPv6Port; }
60 :
61 : /// Sets the unsecure Matter port
62 1 : void SetUnsecuredPort(uint16_t port) { mUnsecuredPort = port; }
63 :
64 : /// Gets the unsecure Matter port
65 0 : uint16_t GetUnsecuredPort() const { return mUnsecuredPort; }
66 :
67 : /// Sets the interface id used for advertising
68 1 : void SetInterfaceId(Inet::InterfaceId interfaceId) { mInterfaceId = interfaceId; }
69 :
70 : /// Gets the interface id used for advertising
71 7 : Inet::InterfaceId GetInterfaceId() { return mInterfaceId; }
72 :
73 : //
74 : // Set the fabric table the DnssdServer should use for operational
75 : // advertising. This must be set before StartServer() is called for the
76 : // first time.
77 : //
78 1 : void SetFabricTable(FabricTable * table)
79 : {
80 1 : VerifyOrDie(table != nullptr);
81 1 : mFabricTable = table;
82 1 : }
83 :
84 : // Set the commissioning mode provider to use. Null provider will mean we
85 : // assume the commissioning mode is kDisabled.
86 2 : void SetCommissioningModeProvider(CommissioningModeProvider * provider) { mCommissioningModeProvider = provider; }
87 :
88 : #if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
89 : /// Sets the extended discovery timeout. Value will be persisted across reboots
90 : void SetExtendedDiscoveryTimeoutSecs(int32_t secs);
91 :
92 : /// Callback from Extended Discovery Expiration timer
93 : /// Checks if extended discovery has expired and if so,
94 : /// stops commissionable node advertising
95 : /// Extended Discovery Expiration refers here to commissionable node advertising when NOT in commissioning mode
96 : void OnExtendedDiscoveryExpiration(System::Layer * aSystemLayer, void * aAppState);
97 : #endif // CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
98 :
99 : #if CHIP_CONFIG_ENABLE_ICD_SERVER
100 : template <class AdvertisingParams>
101 : void AddICDKeyToAdvertisement(AdvertisingParams & advParams);
102 :
103 : void SetICDManager(ICDManager * manager) { mICDManager = manager; };
104 : #endif
105 :
106 : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
107 1 : void SetTCPServerEnabled(bool serverEnabled) { mTCPServerEnabled = serverEnabled; };
108 : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
109 :
110 : /// Start operational advertising
111 : CHIP_ERROR AdvertiseOperational();
112 :
113 : /// (Re-)starts the Dnssd server, using the commissioning mode from our
114 : /// commissioning mode provider.
115 : void StartServer();
116 :
117 : /// (Re-)starts the Dnssd server, using the provided commissioning mode.
118 : void StartServer(Dnssd::CommissioningMode mode);
119 :
120 : //// Stop the Dnssd server. After this call, SetFabricTable must be called
121 : //// again before calling StartServer().
122 : void StopServer();
123 :
124 : CHIP_ERROR GenerateRotatingDeviceId(char rotatingDeviceIdHexBuffer[], size_t rotatingDeviceIdHexBufferSize);
125 :
126 : /// Generates the (random) instance name that a CHIP device is to use for pre-commissioning DNS-SD
127 : CHIP_ERROR GetCommissionableInstanceName(char * buffer, size_t bufferLen);
128 :
129 : /**
130 : * @brief Overrides configuration so that commissionable advertisement will use an
131 : * ephemeral discriminator such as one set for ECM. If the Optional has no
132 : * value, the default basic discriminator is used as usual.
133 : *
134 : * @param[in] discriminator Ephemeral discriminator to override if it HasValue(), otherwise reverts
135 : * to default.
136 : * @return CHIP_NO_ERROR on success or CHIP_ERROR_INVALID_ARGUMENT on invalid value
137 : */
138 : CHIP_ERROR SetEphemeralDiscriminator(Optional<uint16_t> discriminator);
139 :
140 : /**
141 : * @brief When the ICD changes operating mode, the dnssd server needs to restart its DNS-SD advertising to update the TXT keys.
142 : */
143 : void OnICDModeChange() override;
144 :
145 : /**
146 : * @brief dnssd server has no action to do on this ICD event. Do nothing.
147 : */
148 0 : void OnEnterActiveMode() override{};
149 :
150 : /**
151 : * @brief dnssd server has no action to do on this ICD event. Do nothing.
152 : */
153 0 : void OnTransitionToIdle() override{};
154 :
155 : /**
156 : * @brief dnssd server has no action to do on this ICD event. Do nothing.
157 : */
158 0 : void OnEnterIdleMode() override{};
159 :
160 : private:
161 : /// Overloaded utility method for commissioner and commissionable advertisement
162 : /// This method is used for both commissioner discovery and commissionable node discovery since
163 : /// they share many fields.
164 : /// commissionableNode = true : advertise commissionable node
165 : /// commissionableNode = false : advertise commissioner
166 : CHIP_ERROR Advertise(bool commissionableNode, chip::Dnssd::CommissioningMode mode);
167 :
168 : /// Set MDNS commissioner advertisement
169 : CHIP_ERROR AdvertiseCommissioner();
170 :
171 : /// Set MDNS commissionable node advertisement
172 : CHIP_ERROR AdvertiseCommissionableNode(chip::Dnssd::CommissioningMode mode);
173 :
174 : // Our randomly-generated fallback "MAC address", in case we don't have a real one.
175 : uint8_t mFallbackMAC[chip::DeviceLayer::ConfigurationManager::kPrimaryMACAddressLength] = { 0 };
176 :
177 : void GetPrimaryOrFallbackMACAddress(MutableByteSpan & mac);
178 :
179 : //
180 : // Check if we have any valid operational credentials present in the fabric table and return true
181 : // if we do.
182 : //
183 : bool HaveOperationalCredentials();
184 :
185 : // Check whether the secured IPv4 port matches the secured IPv6 port. If it
186 : // does not, we should not advertise our IPv4 bits, because we can only
187 : // advertise one port number.
188 7 : bool SecuredIPv4PortMatchesIPv6Port() const
189 : {
190 : #if INET_CONFIG_ENABLE_IPV4
191 7 : return mSecuredIPv4Port == mSecuredIPv6Port;
192 : #else
193 : return false;
194 : #endif // INET_CONFIG_ENABLE_IPV4
195 : }
196 :
197 : FabricTable * mFabricTable = nullptr;
198 : CommissioningModeProvider * mCommissioningModeProvider = nullptr;
199 :
200 : #if CHIP_CONFIG_ENABLE_ICD_SERVER
201 : ICDManager * mICDManager = nullptr;
202 : #endif // CHIP_CONFIG_ENABLE_ICD_SERVER
203 :
204 : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
205 : bool mTCPServerEnabled = true;
206 : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
207 :
208 : uint16_t mSecuredIPv6Port = CHIP_PORT;
209 : #if INET_CONFIG_ENABLE_IPV4
210 : uint16_t mSecuredIPv4Port = CHIP_PORT;
211 : #endif // INET_CONFIG_ENABLE_IPV4
212 : uint16_t mUnsecuredPort = CHIP_UDC_PORT;
213 : Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null();
214 :
215 : // Ephemeral discriminator to use instead of the default if set
216 : Optional<uint16_t> mEphemeralDiscriminator;
217 :
218 : #if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
219 : Time::TimeSource<Time::Source::kSystem> mTimeSource;
220 :
221 : /// Get the current extended discovery timeout (set by
222 : /// SetExtendedDiscoveryTimeoutSecs, or the configuration default if not set).
223 : int32_t GetExtendedDiscoveryTimeoutSecs();
224 :
225 : /// schedule next extended discovery expiration
226 : CHIP_ERROR ScheduleExtendedDiscoveryExpiration();
227 :
228 : // mExtendedDiscoveryExpiration, if not set to kTimeoutCleared, is used to
229 : // indicate that we should be advertising extended discovery right now.
230 : System::Clock::Timestamp mExtendedDiscoveryExpiration = kTimeoutCleared;
231 : Optional<int32_t> mExtendedDiscoveryTimeoutSecs = NullOptional;
232 :
233 : // The commissioning mode we are advertising right now. Used to detect when
234 : // we need to start extended discovery advertisement. We start this off as
235 : // kEnabledBasic, so that when we first start up we do extended discovery
236 : // advertisement if we don't enter commissioning mode.
237 : Dnssd::CommissioningMode mCurrentCommissioningMode = Dnssd::CommissioningMode::kEnabledBasic;
238 : #endif // CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
239 : };
240 :
241 : } // namespace app
242 : } // namespace chip
|