Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * Copyright (c) 2018 Google LLC.
5 : * Copyright (c) 2013-2018 Nest Labs, Inc.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * This file implements the <tt>Inet::UDPEndPoint</tt>
23 : * class, where the CHIP Inet Layer encapsulates methods for
24 : * interacting with UDP transport endpoints (SOCK_DGRAM sockets
25 : * on Linux and BSD-derived systems) or LwIP UDP protocol
26 : * control blocks, as the system is configured accordingly.
27 : *
28 : */
29 :
30 : #include <inet/UDPEndPoint.h>
31 :
32 : #include <inet/IPPacketInfo.h>
33 : #include <inet/InetFaultInjection.h>
34 : #include <inet/arpa-inet-compatibility.h>
35 : #include <lib/support/CodeUtils.h>
36 : #include <lib/support/SafeInt.h>
37 : #include <lib/support/logging/CHIPLogging.h>
38 : #include <system/SystemFaultInjection.h>
39 :
40 : #include <cstring>
41 : #include <utility>
42 :
43 : namespace chip {
44 : namespace Inet {
45 :
46 69 : CHIP_ERROR UDPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uint16_t port, InterfaceId intfId)
47 : {
48 69 : if (mState != State::kReady && mState != State::kBound)
49 : {
50 1 : return CHIP_ERROR_INCORRECT_STATE;
51 : }
52 :
53 68 : if ((addr != IPAddress::Any) && (addr.Type() != IPAddressType::kAny) && (addr.Type() != addrType))
54 : {
55 2 : return INET_ERROR_WRONG_ADDRESS_TYPE;
56 : }
57 :
58 66 : ReturnErrorOnFailure(BindImpl(addrType, addr, port, intfId));
59 :
60 64 : mState = State::kBound;
61 :
62 64 : return CHIP_NO_ERROR;
63 : }
64 :
65 2 : CHIP_ERROR UDPEndPoint::BindInterface(IPAddressType addrType, InterfaceId intfId)
66 : {
67 2 : if (mState != State::kReady && mState != State::kBound)
68 : {
69 1 : return CHIP_ERROR_INCORRECT_STATE;
70 : }
71 :
72 1 : ReturnErrorOnFailure(BindInterfaceImpl(addrType, intfId));
73 :
74 1 : mState = State::kBound;
75 :
76 1 : return CHIP_NO_ERROR;
77 : }
78 :
79 66 : CHIP_ERROR UDPEndPoint::Listen(OnMessageReceivedFunct onMessageReceived, OnReceiveErrorFunct onReceiveError, void * appState)
80 : {
81 66 : if (mState == State::kListening)
82 : {
83 1 : return CHIP_NO_ERROR;
84 : }
85 :
86 65 : if (mState != State::kBound)
87 : {
88 1 : return CHIP_ERROR_INCORRECT_STATE;
89 : }
90 :
91 64 : OnMessageReceived = onMessageReceived;
92 64 : OnReceiveError = onReceiveError;
93 64 : mAppState = appState;
94 :
95 64 : ReturnErrorOnFailure(ListenImpl());
96 :
97 64 : mState = State::kListening;
98 :
99 64 : return CHIP_NO_ERROR;
100 : }
101 :
102 43 : CHIP_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBufferHandle && msg, InterfaceId intfId)
103 : {
104 43 : IPPacketInfo pktInfo;
105 43 : pktInfo.Clear();
106 43 : pktInfo.DestAddress = addr;
107 43 : pktInfo.DestPort = port;
108 43 : pktInfo.Interface = intfId;
109 43 : return SendMsg(&pktInfo, std::move(msg));
110 : }
111 :
112 46 : CHIP_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, System::PacketBufferHandle && msg)
113 : {
114 46 : INET_FAULT_INJECT(FaultInjection::kFault_Send, return INET_ERROR_UNKNOWN_INTERFACE;);
115 46 : INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, return CHIP_ERROR_NO_MEMORY;);
116 :
117 46 : ReturnErrorOnFailure(SendMsgImpl(pktInfo, std::move(msg)));
118 :
119 46 : CHIP_SYSTEM_FAULT_INJECT_ASYNC_EVENT();
120 :
121 46 : return CHIP_NO_ERROR;
122 : }
123 :
124 72 : void UDPEndPoint::Close()
125 : {
126 72 : if (mState != State::kClosed)
127 : {
128 65 : mState = State::kClosed;
129 65 : CloseImpl();
130 : }
131 72 : }
132 :
133 28 : CHIP_ERROR UDPEndPoint::JoinMulticastGroup(InterfaceId aInterfaceId, const IPAddress & aAddress)
134 : {
135 28 : VerifyOrReturnError(aAddress.IsMulticast(), INET_ERROR_WRONG_ADDRESS_TYPE);
136 :
137 28 : switch (aAddress.Type())
138 : {
139 :
140 : #if INET_CONFIG_ENABLE_IPV4
141 14 : case IPAddressType::kIPv4:
142 14 : return IPv4JoinLeaveMulticastGroupImpl(aInterfaceId, aAddress, true);
143 : #endif // INET_CONFIG_ENABLE_IPV4
144 :
145 14 : case IPAddressType::kIPv6:
146 14 : return IPv6JoinLeaveMulticastGroupImpl(aInterfaceId, aAddress, true);
147 :
148 0 : default:
149 0 : return INET_ERROR_WRONG_ADDRESS_TYPE;
150 : }
151 : }
152 :
153 0 : CHIP_ERROR UDPEndPoint::LeaveMulticastGroup(InterfaceId aInterfaceId, const IPAddress & aAddress)
154 : {
155 0 : VerifyOrReturnError(aAddress.IsMulticast(), INET_ERROR_WRONG_ADDRESS_TYPE);
156 :
157 0 : switch (aAddress.Type())
158 : {
159 :
160 : #if INET_CONFIG_ENABLE_IPV4
161 0 : case IPAddressType::kIPv4:
162 0 : return IPv4JoinLeaveMulticastGroupImpl(aInterfaceId, aAddress, false);
163 : #endif // INET_CONFIG_ENABLE_IPV4
164 :
165 0 : case IPAddressType::kIPv6:
166 0 : return IPv6JoinLeaveMulticastGroupImpl(aInterfaceId, aAddress, false);
167 :
168 0 : default:
169 0 : return INET_ERROR_WRONG_ADDRESS_TYPE;
170 : }
171 : }
172 :
173 : } // namespace Inet
174 : } // namespace chip
|