Line data Source code
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 : /**
19 : * @brief
20 : * File contains definitions on how a connection to a peer can be defined.
21 : *
22 : */
23 :
24 : #pragma once
25 :
26 : #include <inet/IPAddress.h>
27 : #include <inet/InetInterface.h>
28 : #include <lib/core/CHIPConfig.h>
29 : #include <lib/core/DataModelTypes.h>
30 : #include <lib/support/CHIPMemString.h>
31 :
32 : namespace chip {
33 : namespace Transport {
34 :
35 : /**
36 : * Communication path defines how two peers communicate.
37 : *
38 : * When a peer contacts another peer, it defines how the peers communicate.
39 : *
40 : * Once communication between two peers is established, the same transport
41 : * path should be used: a peer contacting another peer over UDP will receive
42 : * messages back over UDP. A communication channel established over TCP
43 : * will keep the same TCP channel.
44 : *
45 : */
46 :
47 : /**
48 : * Here we specified Type to be uint8_t, so the PeerAddress can be serialized easily.
49 : */
50 : enum class Type : uint8_t
51 : {
52 : kUndefined,
53 : kUdp,
54 : kBle,
55 : kTcp,
56 : };
57 :
58 : /**
59 : * Describes how a peer on a CHIP network can be addressed.
60 : */
61 : class PeerAddress
62 : {
63 : public:
64 149 : PeerAddress() : mIPAddress(Inet::IPAddress::Any), mTransportType(Type::kUndefined) {}
65 0 : PeerAddress(const Inet::IPAddress & addr, Type type) : mIPAddress(addr), mTransportType(type) {}
66 0 : PeerAddress(Type type) : mTransportType(type) {}
67 :
68 : PeerAddress(PeerAddress &&) = default;
69 0 : PeerAddress(const PeerAddress &) = default;
70 10732 : PeerAddress & operator=(const PeerAddress &) = default;
71 2 : PeerAddress & operator=(PeerAddress &&) = default;
72 :
73 6 : const Inet::IPAddress & GetIPAddress() const { return mIPAddress; }
74 0 : PeerAddress & SetIPAddress(const Inet::IPAddress & addr)
75 : {
76 0 : mIPAddress = addr;
77 0 : return *this;
78 : }
79 :
80 44953 : Type GetTransportType() const { return mTransportType; }
81 : PeerAddress & SetTransportType(Type type)
82 : {
83 : mTransportType = type;
84 : return *this;
85 : }
86 :
87 9 : uint16_t GetPort() const { return mPort; }
88 12 : PeerAddress & SetPort(uint16_t port)
89 : {
90 12 : mPort = port;
91 12 : return *this;
92 : }
93 :
94 104 : Inet::InterfaceId GetInterface() const { return mInterface; }
95 15 : PeerAddress & SetInterface(Inet::InterfaceId interface)
96 : {
97 15 : mInterface = interface;
98 15 : return *this;
99 : }
100 :
101 : bool IsInitialized() const { return mTransportType != Type::kUndefined; }
102 :
103 : bool IsMulticast() { return Type::kUdp == mTransportType && mIPAddress.IsIPv6Multicast(); }
104 :
105 9398 : bool operator==(const PeerAddress & other) const
106 : {
107 18568 : return (mTransportType == other.mTransportType) && (mIPAddress == other.mIPAddress) && (mPort == other.mPort) &&
108 18568 : (mInterface == other.mInterface);
109 : }
110 :
111 9389 : bool operator!=(const PeerAddress & other) const { return !(*this == other); }
112 :
113 : /// Maximum size of the string outputes by ToString. Format is of the form:
114 : /// "UDP:<ip>:<port>"
115 : static constexpr size_t kMaxToStringSize = 3 // type: UDP/TCP/BLE
116 : + 1 // splitter :
117 : + 2 // brackets around address
118 : + Inet::IPAddress::kMaxStringLength // address
119 : + 1 // splitter %
120 : + Inet::InterfaceId::kMaxIfNameLength // interface
121 : + 1 // splitter :
122 : + 5 // port: 16 bit interger
123 : + 1; // NullTerminator
124 :
125 : template <size_t N>
126 9614 : inline void ToString(char (&buf)[N]) const
127 : {
128 9614 : ToString(buf, N);
129 9614 : }
130 :
131 9614 : void ToString(char * buf, size_t bufSize) const
132 : {
133 : char ip_addr[Inet::IPAddress::kMaxStringLength];
134 :
135 9614 : char interface[Inet::InterfaceId::kMaxIfNameLength + 1] = {}; // +1 to prepend '%'
136 9614 : if (mInterface.IsPresent())
137 : {
138 0 : interface[0] = '%';
139 0 : interface[1] = 0;
140 0 : CHIP_ERROR err = mInterface.GetInterfaceName(interface + 1, sizeof(interface) - 1);
141 0 : if (err != CHIP_NO_ERROR)
142 : {
143 0 : Platform::CopyString(interface, sizeof(interface), "%(err)");
144 : }
145 : }
146 :
147 9614 : switch (mTransportType)
148 : {
149 47 : case Type::kUndefined:
150 47 : snprintf(buf, bufSize, "UNDEFINED");
151 47 : break;
152 9567 : case Type::kUdp:
153 9567 : mIPAddress.ToString(ip_addr);
154 : #if INET_CONFIG_ENABLE_IPV4
155 9567 : if (mIPAddress.IsIPv4())
156 0 : snprintf(buf, bufSize, "UDP:%s%s:%d", ip_addr, interface, mPort);
157 : else
158 : #endif
159 9567 : snprintf(buf, bufSize, "UDP:[%s%s]:%d", ip_addr, interface, mPort);
160 9567 : break;
161 0 : case Type::kTcp:
162 0 : mIPAddress.ToString(ip_addr);
163 : #if INET_CONFIG_ENABLE_IPV4
164 0 : if (mIPAddress.IsIPv4())
165 0 : snprintf(buf, bufSize, "TCP:%s%s:%d", ip_addr, interface, mPort);
166 : else
167 : #endif
168 0 : snprintf(buf, bufSize, "TCP:[%s%s]:%d", ip_addr, interface, mPort);
169 0 : break;
170 0 : case Type::kBle:
171 : // Note that BLE does not currently use any specific address.
172 0 : snprintf(buf, bufSize, "BLE");
173 0 : break;
174 0 : default:
175 0 : snprintf(buf, bufSize, "ERROR");
176 0 : break;
177 : }
178 9614 : }
179 :
180 : /****** Factory methods for convenience ******/
181 :
182 : static PeerAddress Uninitialized() { return PeerAddress(Inet::IPAddress::Any, Type::kUndefined); }
183 :
184 0 : static PeerAddress BLE() { return PeerAddress(Type::kBle); }
185 0 : static PeerAddress UDP(const Inet::IPAddress & addr) { return PeerAddress(addr, Type::kUdp); }
186 0 : static PeerAddress UDP(const Inet::IPAddress & addr, uint16_t port) { return UDP(addr).SetPort(port); }
187 :
188 : /**
189 : * Parses a PeerAddress from the given IP address string with UDP type. For example,
190 : * "192.168.1.4", "fe80::2", "fe80::1%wlan0". Notably this will also include the network scope
191 : * ID in either index or name form (e.g. %wlan0, %14).
192 : */
193 : static PeerAddress UDP(char * addrStr, uint16_t port) { return PeerAddress::FromString(addrStr, port, Type::kUdp); }
194 2 : static PeerAddress UDP(const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId interface)
195 : {
196 2 : return UDP(addr).SetPort(port).SetInterface(interface);
197 : }
198 0 : static PeerAddress TCP(const Inet::IPAddress & addr) { return PeerAddress(addr, Type::kTcp); }
199 : static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port) { return TCP(addr).SetPort(port); }
200 :
201 : /**
202 : * Parses a PeerAddress from the given IP address string with TCP type. For example,
203 : * "192.168.1.4", "fe80::2", "fe80::1%wlan0". Notably this will also include the network scope
204 : * ID in either index or name form (e.g. %wlan0, %14).
205 : */
206 : static PeerAddress TCP(char * addrStr, uint16_t port) { return PeerAddress::FromString(addrStr, port, Type::kTcp); }
207 12 : static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId interface)
208 : {
209 12 : return TCP(addr).SetPort(port).SetInterface(interface);
210 : }
211 :
212 2 : static PeerAddress Multicast(chip::FabricId fabric, chip::GroupId group)
213 : {
214 2 : constexpr uint8_t scope = 0x05; // Site-Local
215 2 : constexpr uint8_t prefixLength = 0x40; // 64-bit long network prefix field
216 : // The network prefix portion of the Multicast Address is the 64-bit bitstring formed by concatenating:
217 : // * 0xFD to designate a locally assigned ULA prefix
218 : // * The upper 56-bits of the Fabric ID for the network in big-endian order
219 2 : const uint64_t prefix = 0xfd00000000000000 | ((fabric >> 8) & 0x00ffffffffffffff);
220 : // The 32-bit group identifier portion of the Multicast Address is the 32-bits formed by:
221 : // * The lower 8-bits of the Fabric ID
222 : // * 0x00
223 : // * The 16-bits Group Identifier in big-endian order
224 2 : uint32_t groupId = static_cast<uint32_t>((fabric << 24) & 0xff000000) | group;
225 2 : return UDP(Inet::IPAddress::MakeIPv6PrefixMulticast(scope, prefixLength, prefix, groupId));
226 : }
227 :
228 : private:
229 : static PeerAddress FromString(char * addrStr, uint16_t port, Type type)
230 : {
231 : Inet::IPAddress addr;
232 : Inet::InterfaceId interfaceId;
233 : Inet::IPAddress::FromString(addrStr, addr, interfaceId);
234 : return PeerAddress(addr, type).SetPort(port).SetInterface(interfaceId);
235 : }
236 : Inet::IPAddress mIPAddress = {};
237 : Type mTransportType = Type::kUndefined;
238 : uint16_t mPort = CHIP_PORT; ///< Relevant for UDP data sending.
239 : Inet::InterfaceId mInterface = Inet::InterfaceId::Null();
240 : };
241 :
242 : } // namespace Transport
243 : } // namespace chip
|