19dd9f0513072fe515152fdf352ef868e79144aa
[platform/upstream/connectedhomeip.git] / src / app / server / Mdns.cpp
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 #include "Mdns.h"
19
20 #include <inttypes.h>
21
22 #include <core/Optional.h>
23 #include <mdns/Advertiser.h>
24 #include <platform/CHIPDeviceLayer.h>
25 #include <platform/ConfigurationManager.h>
26 #include <support/ReturnMacros.h>
27 #include <support/logging/CHIPLogging.h>
28 #include <transport/AdminPairingTable.h>
29 #include <transport/PASESession.h>
30
31 #include "Server.h"
32
33 namespace chip {
34 namespace app {
35 namespace Mdns {
36
37 namespace {
38
39 NodeId GetCurrentNodeId()
40 {
41     // TODO: once operational credentials are implemented, node ID should be read from them
42     if (!DeviceLayer::ConfigurationMgr().IsFullyProvisioned())
43     {
44         ChipLogError(Discovery, "Device not fully provisioned. Node ID unknown.");
45         return chip::kTestDeviceNodeId;
46     }
47
48     // Admin pairings should have been persisted and should be loadable
49
50     // TODO: once multi-admin is decided, figure out if a single node id
51     // is sufficient or if we need multi-node-id advertisement. Existing
52     // mdns advertises a single node id as parameter.
53
54     // Search for one admin pairing and use its node id.
55     auto pairing = GetGlobalAdminPairingTable().cbegin();
56     if (pairing != GetGlobalAdminPairingTable().cend())
57     {
58         ChipLogProgress(Discovery, "Found admin paring for admin %" PRIX64 ", node %" PRIX64, pairing->GetAdminId(),
59                         pairing->GetNodeId());
60         return pairing->GetNodeId();
61     }
62
63     ChipLogError(Discovery, "Failed to find a valid admin pairing. Node ID unknown");
64     return chip::kTestDeviceNodeId;
65 }
66
67 } // namespace
68
69 /// Set MDNS operational advertisement
70 CHIP_ERROR AdvertiseOperational()
71 {
72     uint64_t fabricId;
73
74     if (DeviceLayer::ConfigurationMgr().GetFabricId(fabricId) != CHIP_NO_ERROR)
75     {
76         ChipLogError(Discovery, "Fabric ID not known. Using a default");
77         fabricId = 5544332211;
78     }
79
80     const auto advertiseParameters = chip::Mdns::OperationalAdvertisingParameters()
81                                          .SetFabricId(fabricId)
82                                          .SetNodeId(GetCurrentNodeId())
83                                          .SetPort(CHIP_PORT)
84                                          .EnableIpV4(true);
85
86     auto & mdnsAdvertiser = chip::Mdns::ServiceAdvertiser::Instance();
87
88     ReturnErrorOnFailure(mdnsAdvertiser.Advertise(advertiseParameters));
89
90     return mdnsAdvertiser.Start(&chip::DeviceLayer::InetLayer, chip::Mdns::kMdnsPort);
91 }
92
93 /// Set MDNS commisioning advertisement
94 CHIP_ERROR AdvertiseCommisioning()
95 {
96
97     auto advertiseParameters = chip::Mdns::CommissionAdvertisingParameters().SetPort(CHIP_PORT).EnableIpV4(true);
98
99     uint16_t value;
100     if (DeviceLayer::ConfigurationMgr().GetVendorId(value) != CHIP_NO_ERROR)
101     {
102         ChipLogProgress(Discovery, "Vendor ID not known");
103     }
104     else
105     {
106         advertiseParameters.SetVendorId(chip::Optional<uint16_t>::Value(value));
107     }
108
109     if (DeviceLayer::ConfigurationMgr().GetProductId(value) != CHIP_NO_ERROR)
110     {
111         ChipLogProgress(Discovery, "Product ID not known");
112     }
113     else
114     {
115         advertiseParameters.SetProductId(chip::Optional<uint16_t>::Value(value));
116     }
117
118     if (DeviceLayer::ConfigurationMgr().GetSetupDiscriminator(value) != CHIP_NO_ERROR)
119     {
120         ChipLogError(Discovery, "Setup discriminator not known. Using a default.");
121         value = 840;
122     }
123     advertiseParameters.SetShortDiscriminator(static_cast<uint8_t>(value & 0xFF)).SetLongDiscrimininator(value);
124
125     auto & mdnsAdvertiser = chip::Mdns::ServiceAdvertiser::Instance();
126
127     ReturnErrorOnFailure(mdnsAdvertiser.Advertise(advertiseParameters));
128
129     return mdnsAdvertiser.Start(&chip::DeviceLayer::InetLayer, chip::Mdns::kMdnsPort);
130 }
131
132 /// (Re-)starts the minmdns server
133 void StartServer()
134 {
135     CHIP_ERROR err = chip::Mdns::ServiceAdvertiser::Instance().Start(&chip::DeviceLayer::InetLayer, chip::Mdns::kMdnsPort);
136
137     // TODO: advertise this only when really operational once we support both
138     // operational and commisioning advertising is supported.
139     if (DeviceLayer::ConfigurationMgr().IsFullyProvisioned())
140     {
141         err = app::Mdns::AdvertiseOperational();
142     }
143     else
144     {
145         err = app::Mdns::AdvertiseCommisioning();
146     }
147
148     if (err != CHIP_NO_ERROR)
149     {
150         ChipLogError(Discovery, "Failed to start mDNS server: %s", chip::ErrorStr(err));
151     }
152 }
153
154 } // namespace Mdns
155 } // namespace app
156 } // namespace chip