Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / mdns / minimal / Server.h
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
18 #pragma once
19
20 #include <core/CHIPError.h>
21 #include <inet/IPAddress.h>
22 #include <inet/InetInterface.h>
23 #include <inet/InetLayer.h>
24 #include <inet/UDPEndPoint.h>
25
26 #include <mdns/minimal/core/BytesRange.h>
27
28 namespace mdns {
29 namespace Minimal {
30
31 namespace BroadcastIpAddresses {
32
33 // Get standard mDNS Broadcast addresses
34
35 void GetIpv6Into(chip::Inet::IPAddress & dest);
36 void GetIpv4Into(chip::Inet::IPAddress & dest);
37
38 } // namespace BroadcastIpAddresses
39
40 /// Provides a list of intefaces to listen on.
41 ///
42 /// When listening on IP, both IP address type (IPv4 or IPv6) and interface id
43 /// are important. In particular, when using link-local IP addresses, the actual
44 /// interface matters (e.g. FF02::FB will care over which IPv6 interface it is sent)
45 ///
46 /// For MDNS in particular, you may want:
47 ///  - IPv4 listen on INET_NULL_INTERFACEID
48 ///  - IPv6 listen on every specific interface id available (except local loopback and other
49 ///    not usable interfaces like docker)
50 class ListenIterator
51 {
52 public:
53     virtual ~ListenIterator() {}
54
55     // Get the next interface/address type to listen on
56     virtual bool Next(chip::Inet::InterfaceId * id, chip::Inet::IPAddressType * type) = 0;
57 };
58
59 /// Handles mDNS Server Callbacks
60 class ServerDelegate
61 {
62 public:
63     virtual ~ServerDelegate() {}
64
65     // Callback of when a query is received
66     virtual void OnQuery(const BytesRange & data, const chip::Inet::IPPacketInfo * info) = 0;
67
68     // Callback of when a response is received
69     virtual void OnResponse(const BytesRange & data, const chip::Inet::IPPacketInfo * info) = 0;
70 };
71
72 // Defines an mDNS server that listens on one or more interfaces.
73 //
74 // I can send and receive mDNS packets (requests/replies)
75 class ServerBase
76 {
77 public:
78     struct EndpointInfo
79     {
80         chip::Inet::InterfaceId interfaceId = INET_NULL_INTERFACEID;
81         chip::Inet::IPAddressType addressType;
82         chip::Inet::UDPEndPoint * udp = nullptr;
83     };
84
85     ServerBase(EndpointInfo * endpointStorage, size_t kStorageSize) : mEndpoints(endpointStorage), mEndpointCount(kStorageSize)
86     {
87         for (size_t i = 0; i < mEndpointCount; i++)
88         {
89             mEndpoints[i].udp = nullptr;
90         }
91
92         BroadcastIpAddresses::GetIpv6Into(mIpv6BroadcastAddress);
93
94 #if INET_CONFIG_ENABLE_IPV4
95         BroadcastIpAddresses::GetIpv4Into(mIpv4BroadcastAddress);
96 #endif
97     }
98     ~ServerBase();
99
100     /// Closes all currently open endpoints
101     void Shutdown();
102
103     /// Listen on the given interfaces/address types.
104     ///
105     /// Since mDNS uses link-local addresses, one generally wants to listen on all
106     /// non-loopback interfaces.
107     CHIP_ERROR Listen(chip::Inet::InetLayer * inetLayer, ListenIterator * it, uint16_t port);
108
109     /// Send the specified packet to a destination IP address over the specified address
110     CHIP_ERROR DirectSend(chip::System::PacketBufferHandle && data, const chip::Inet::IPAddress & addr, uint16_t port,
111                           chip::Inet::InterfaceId interface);
112
113     /// Send a specific packet broadcast to all interfaces
114     CHIP_ERROR BroadcastSend(chip::System::PacketBufferHandle data, uint16_t port);
115
116     /// Send a specific packet broadcast to a specific interface
117     CHIP_ERROR BroadcastSend(chip::System::PacketBufferHandle data, uint16_t port, chip::Inet::InterfaceId interface);
118
119     ServerBase & SetDelegate(ServerDelegate * d)
120     {
121         mDelegate = d;
122         return *this;
123     }
124
125     /// How many endpoints are availabe to be used by the server.
126     size_t GetEndpointCount() const { return mEndpointCount; }
127
128     /// Get the endpoints that are used by this server
129     ///
130     /// Entries with non-null UDP are considered usable.
131     const EndpointInfo * GetEndpoints() const { return mEndpoints; }
132
133 private:
134     static void OnUdpPacketReceived(chip::Inet::IPEndPointBasis * endPoint, chip::System::PacketBufferHandle buffer,
135                                     const chip::Inet::IPPacketInfo * info);
136
137     EndpointInfo * mEndpoints;   // possible endpoints, to listen on multiple interfaces
138     const size_t mEndpointCount; // how many endpoints are allocated
139     ServerDelegate * mDelegate = nullptr;
140
141     // Broadcast IP addresses are cached to not require a string parse every time
142     // Ideally we should be able to constexpr these
143     chip::Inet::IPAddress mIpv6BroadcastAddress;
144 #if INET_CONFIG_ENABLE_IPV4
145     chip::Inet::IPAddress mIpv4BroadcastAddress;
146 #endif
147 };
148
149 template <size_t kCount>
150 class Server : public ServerBase
151 {
152 public:
153     Server() : ServerBase(mAllocatedStorage, kCount) {}
154     ~Server() {}
155
156 private:
157     EndpointInfo mAllocatedStorage[kCount];
158 };
159
160 } // namespace Minimal
161 } // namespace mdns