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 81 : CHIP_ERROR UDPEndPoint::Bind(IPAddressType addrType, const IPAddress & addr, uint16_t port, InterfaceId intfId) 47 : { 48 81 : if (mState != State::kReady && mState != State::kBound) 49 : { 50 1 : return CHIP_ERROR_INCORRECT_STATE; 51 : } 52 : 53 80 : if ((addr != IPAddress::Any) && (addr.Type() != IPAddressType::kAny) && (addr.Type() != addrType)) 54 : { 55 2 : return INET_ERROR_WRONG_ADDRESS_TYPE; 56 : } 57 : 58 78 : ReturnErrorOnFailure(BindImpl(addrType, addr, port, intfId)); 59 : 60 76 : mState = State::kBound; 61 : 62 76 : 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 78 : CHIP_ERROR UDPEndPoint::Listen(OnMessageReceivedFunct onMessageReceived, OnReceiveErrorFunct onReceiveError, void * appState) 80 : { 81 78 : if (mState == State::kListening) 82 : { 83 1 : return CHIP_NO_ERROR; 84 : } 85 : 86 77 : if (mState != State::kBound) 87 : { 88 1 : return CHIP_ERROR_INCORRECT_STATE; 89 : } 90 : 91 76 : OnMessageReceived = onMessageReceived; 92 76 : OnReceiveError = onReceiveError; 93 76 : mAppState = appState; 94 : 95 76 : ReturnErrorOnFailure(ListenImpl()); 96 : 97 76 : mState = State::kListening; 98 : 99 76 : return CHIP_NO_ERROR; 100 : } 101 : 102 49 : CHIP_ERROR UDPEndPoint::SendTo(const IPAddress & addr, uint16_t port, chip::System::PacketBufferHandle && msg, InterfaceId intfId) 103 : { 104 49 : IPPacketInfo pktInfo; 105 49 : pktInfo.Clear(); 106 49 : pktInfo.DestAddress = addr; 107 49 : pktInfo.DestPort = port; 108 49 : pktInfo.Interface = intfId; 109 49 : return SendMsg(&pktInfo, std::move(msg)); 110 : } 111 : 112 52 : CHIP_ERROR UDPEndPoint::SendMsg(const IPPacketInfo * pktInfo, System::PacketBufferHandle && msg) 113 : { 114 52 : INET_FAULT_INJECT(FaultInjection::kFault_Send, return INET_ERROR_UNKNOWN_INTERFACE;); 115 52 : INET_FAULT_INJECT(FaultInjection::kFault_SendNonCritical, return CHIP_ERROR_NO_MEMORY;); 116 : 117 52 : ReturnErrorOnFailure(SendMsgImpl(pktInfo, std::move(msg))); 118 : 119 52 : CHIP_SYSTEM_FAULT_INJECT_ASYNC_EVENT(); 120 : 121 52 : return CHIP_NO_ERROR; 122 : } 123 : 124 84 : void UDPEndPoint::Close() 125 : { 126 84 : if (mState != State::kClosed) 127 : { 128 77 : mState = State::kClosed; 129 77 : CloseImpl(); 130 : } 131 84 : } 132 : 133 34 : CHIP_ERROR UDPEndPoint::JoinMulticastGroup(InterfaceId aInterfaceId, const IPAddress & aAddress) 134 : { 135 34 : VerifyOrReturnError(aAddress.IsMulticast(), INET_ERROR_WRONG_ADDRESS_TYPE); 136 : 137 34 : switch (aAddress.Type()) 138 : { 139 : 140 : #if INET_CONFIG_ENABLE_IPV4 141 17 : case IPAddressType::kIPv4: 142 17 : return IPv4JoinLeaveMulticastGroupImpl(aInterfaceId, aAddress, true); 143 : #endif // INET_CONFIG_ENABLE_IPV4 144 : 145 17 : case IPAddressType::kIPv6: 146 17 : 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