Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / examples / minimal-mdns / advertiser.cpp
1 /*
2  *
3  *    Copyright (c) 2020 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 #include <cstdio>
18 #include <memory>
19
20 #include <arpa/inet.h>
21 #include <strings.h>
22
23 #include <mdns/Advertiser.h>
24 #include <platform/CHIPDeviceLayer.h>
25 #include <support/CHIPArgParser.hpp>
26 #include <support/CHIPMem.h>
27
28 using namespace chip;
29
30 namespace {
31
32 enum class AdvertisingMode
33 {
34     kCommisioning,
35     kOperational,
36     kCommisionable,
37 };
38
39 struct Options
40 {
41     bool enableIpV4                 = false;
42     AdvertisingMode advertisingMode = AdvertisingMode::kCommisioning;
43
44     // commisioning/commisionable params
45     uint8_t shortDiscriminator = 52;
46     uint16_t longDiscriminator = 840;
47     Optional<uint16_t> vendorId;
48     Optional<uint16_t> productId;
49
50     // commisionable params
51     Optional<const char *> pairingInstr;
52     Optional<uint8_t> pairingHint;
53
54     // operational params
55     uint64_t fabricId = 12345;
56     uint64_t nodeId   = 6789;
57
58 } gOptions;
59
60 using namespace chip::ArgParser;
61
62 constexpr uint16_t kOptionEnableIpV4      = '4';
63 constexpr uint16_t kOptionAdvertisingMode = 'm';
64
65 constexpr uint16_t kOptionCommisioningShordDiscriminator = 's';
66 constexpr uint16_t kOptionCommisioningLongDiscriminaotr  = 'l';
67 constexpr uint16_t kOptionCommisioningVendorId           = 0x100; // v is used by 'version'
68 constexpr uint16_t kOptionCommisioningProductId          = 'p';
69 constexpr uint16_t kOptionCommisioningPairingInstr       = 0x200; // Just use the long format
70 constexpr uint16_t kOptionCommisioningPairingHint        = 0x300;
71
72 constexpr uint16_t kOptionOperationalFabricId = 'f';
73 constexpr uint16_t kOptionOperationalNodeId   = 'n';
74
75 bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue)
76 {
77     switch (aIdentifier)
78     {
79     case kOptionEnableIpV4:
80         gOptions.enableIpV4 = true;
81         return true;
82     case kOptionAdvertisingMode:
83         if (strcmp(aValue, "operational") == 0)
84         {
85             gOptions.advertisingMode = AdvertisingMode::kOperational;
86         }
87         else if (strcmp(aValue, "commisioning") == 0)
88         {
89             gOptions.advertisingMode = AdvertisingMode::kCommisioning;
90         }
91         else if (strcmp(aValue, "commisionable") == 0)
92         {
93             gOptions.advertisingMode = AdvertisingMode::kCommisionable;
94         }
95         else
96         {
97             PrintArgError("%s: Invalid advertising mode %s\n", aProgram, aValue);
98
99             return false;
100         }
101         return true;
102     case kOptionCommisioningShordDiscriminator:
103         gOptions.shortDiscriminator = static_cast<uint8_t>(atoi(aValue));
104         return true;
105     case kOptionCommisioningLongDiscriminaotr:
106         gOptions.longDiscriminator = static_cast<uint16_t>(atoi(aValue));
107         return true;
108     case kOptionCommisioningVendorId:
109         gOptions.vendorId = Optional<uint16_t>::Value(static_cast<uint16_t>(atoi(aValue)));
110         return true;
111     case kOptionCommisioningProductId:
112         gOptions.productId = Optional<uint16_t>::Value(static_cast<uint16_t>(atoi(aValue)));
113         return true;
114     case kOptionCommisioningPairingInstr:
115         gOptions.pairingInstr = Optional<const char *>::Value(static_cast<const char *>(aValue));
116         return true;
117     case kOptionCommisioningPairingHint:
118         gOptions.pairingHint = Optional<uint8_t>::Value(static_cast<uint8_t>(atoi(aValue)));
119         return true;
120     case kOptionOperationalFabricId:
121         gOptions.fabricId = atoll(aValue);
122         return true;
123     case kOptionOperationalNodeId:
124         gOptions.nodeId = atoll(aValue);
125         return true;
126     default:
127         PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName);
128         return false;
129     }
130 }
131
132 OptionDef cmdLineOptionsDef[] = {
133 #if INET_CONFIG_ENABLE_IPV4
134     { "enable-ip-v4", kNoArgument, kOptionEnableIpV4 },
135 #endif
136     { "advertising-mode", kArgumentRequired, kOptionAdvertisingMode },
137
138     { "short-discriminator", kArgumentRequired, kOptionCommisioningShordDiscriminator },
139     { "long-discriminator", kArgumentRequired, kOptionCommisioningLongDiscriminaotr },
140     { "vendor-id", kArgumentRequired, kOptionCommisioningVendorId },
141     { "product-id", kArgumentRequired, kOptionCommisioningProductId },
142     { "pairing-instruction", kArgumentRequired, kOptionCommisioningPairingInstr },
143     { "pairing-hint", kArgumentRequired, kOptionCommisioningPairingHint },
144
145     { "fabrid-id", kArgumentRequired, kOptionOperationalFabricId },
146     { "node-id", kArgumentRequired, kOptionOperationalNodeId },
147     nullptr,
148 };
149
150 OptionSet cmdLineOptions = { HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS",
151 #if INET_CONFIG_ENABLE_IPV4
152                              "  -4\n"
153                              "  --enable-ip-v4\n"
154                              "        enable listening on IPv4\n"
155 #endif
156                              "  -m <mode>\n"
157                              "  --advertising-mode <mode>\n"
158                              "        Advertise in this mode (operational or commisioning or commisionable).\n"
159                              "  --short-discriminator <value>\n"
160                              "  -s <value>\n"
161                              "        Commisioning/commisionable short discriminator.\n"
162                              "  --long-discriminator <value>\n"
163                              "  -l <value>\n"
164                              "        Commisioning/commisionable long discriminator.\n"
165                              "  --vendor-id <value>\n"
166                              "        Commisioning/commisionable vendor id.\n"
167                              "  --product-id <value>\n"
168                              "  -p <value>\n"
169                              "        Commisioning/commisionable product id.\n"
170                              "  --pairing-instruction <value>\n"
171                              "        Commisionable pairing instruction.\n"
172                              "  --pairing-hint <value>\n"
173                              "        Commisionable pairing hint.\n"
174                              "  --fabrid-id <value>\n"
175                              "  -f <value>\n"
176                              "        Operational fabric id.\n"
177                              "  --node-id <value>\n"
178                              "  -n <value>\n"
179                              "        Operational node id.\n"
180                              "\n" };
181
182 HelpOptions helpOptions("advertiser", "Usage: advertiser [options]", "1.0");
183
184 OptionSet * allOptions[] = { &cmdLineOptions, &helpOptions, nullptr };
185
186 } // namespace
187
188 int main(int argc, char ** args)
189 {
190     if (Platform::MemoryInit() != CHIP_NO_ERROR)
191     {
192         fprintf(stderr, "FAILED to initialize memory\n");
193         return 1;
194     }
195
196     if (DeviceLayer::PlatformMgr().InitChipStack() != CHIP_NO_ERROR)
197     {
198         fprintf(stderr, "FAILED to initialize chip stack\n");
199         return 1;
200     }
201
202     if (!chip::ArgParser::ParseArgs(args[0], argc, args, allOptions))
203     {
204         return 1;
205     }
206
207     if (chip::Mdns::ServiceAdvertiser::Instance().Start(&DeviceLayer::InetLayer, Mdns::kMdnsPort) != CHIP_NO_ERROR)
208     {
209         fprintf(stderr, "FAILED to start MDNS advertisement\n");
210         return 1;
211     }
212
213     CHIP_ERROR err;
214
215     if (gOptions.advertisingMode == AdvertisingMode::kCommisioning)
216     {
217         err = chip::Mdns::ServiceAdvertiser::Instance().Advertise(chip::Mdns::CommissionAdvertisingParameters()
218                                                                       .EnableIpV4(gOptions.enableIpV4)
219                                                                       .SetPort(CHIP_PORT)
220                                                                       .SetShortDiscriminator(gOptions.shortDiscriminator)
221                                                                       .SetLongDiscrimininator(gOptions.longDiscriminator)
222                                                                       .SetVendorId(gOptions.vendorId)
223                                                                       .SetProductId(gOptions.productId));
224     }
225     else if (gOptions.advertisingMode == AdvertisingMode::kOperational)
226     {
227         err = chip::Mdns::ServiceAdvertiser::Instance().Advertise(chip::Mdns::OperationalAdvertisingParameters()
228                                                                       .EnableIpV4(gOptions.enableIpV4)
229                                                                       .SetPort(CHIP_PORT)
230                                                                       .SetFabricId(gOptions.fabricId)
231                                                                       .SetNodeId(gOptions.nodeId));
232     }
233     else if (gOptions.advertisingMode == AdvertisingMode::kCommisionable)
234     {
235         err = chip::Mdns::ServiceAdvertiser::Instance().Advertise(
236             chip::Mdns::CommissionAdvertisingParameters()
237                 .EnableIpV4(gOptions.enableIpV4)
238                 .SetPort(CHIP_PORT)
239                 .SetShortDiscriminator(gOptions.shortDiscriminator)
240                 .SetLongDiscrimininator(gOptions.longDiscriminator)
241                 .SetVendorId(gOptions.vendorId)
242                 .SetProductId(gOptions.productId)
243                 .SetPairingInstr(gOptions.pairingInstr)
244                 .SetPairingHint(gOptions.pairingHint)
245                 .SetCommissionAdvertiseMode(chip::Mdns::CommssionAdvertiseMode::kCommissionable));
246     }
247     else
248     {
249         fprintf(stderr, "FAILED to determine advertising type.\n");
250         return 1;
251     }
252
253     if (err != CHIP_NO_ERROR)
254     {
255         fprintf(stderr, "FAILED to setup advertisement parameters\n");
256         return 1;
257     }
258
259     DeviceLayer::PlatformMgr().RunEventLoop();
260
261     printf("Done...\n");
262     return 0;
263 }