Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : * All rights reserved.
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 CHIP Connection object that maintains a UDP connection.
23 : */
24 : #include <transport/raw/UDP.h>
25 :
26 : #include <lib/support/CHIPFaultInjection.h>
27 : #include <lib/support/CodeUtils.h>
28 : #include <lib/support/logging/CHIPLogging.h>
29 : #include <transport/raw/GroupcastTesting.h>
30 : #include <transport/raw/MessageHeader.h>
31 :
32 : #include <inttypes.h>
33 :
34 : namespace chip {
35 : namespace Transport {
36 :
37 7 : CHIP_ERROR UDP::Init(UdpListenParameters & params)
38 : {
39 7 : CHIP_ERROR err = CHIP_NO_ERROR;
40 :
41 7 : if (mState != State::kNotReady)
42 : {
43 0 : Close();
44 : }
45 :
46 7 : err = params.GetEndPointManager()->NewEndPoint(mUDPEndPoint);
47 7 : SuccessOrExit(err);
48 :
49 7 : mUDPEndPoint->SetNativeParams(params.GetNativeParams());
50 :
51 7 : ChipLogDetail(Inet, "UDP::Init bind&listen port=%d", params.GetListenPort());
52 :
53 7 : err = mUDPEndPoint->Bind(params.GetAddressType(), Inet::IPAddress::Any, params.GetListenPort(), params.GetInterfaceId());
54 7 : SuccessOrExit(err);
55 :
56 7 : err = mUDPEndPoint->Listen(OnUdpReceive, OnUdpError, this);
57 7 : SuccessOrExit(err);
58 :
59 7 : mUDPEndpointType = params.GetAddressType();
60 :
61 7 : mState = State::kInitialized;
62 :
63 7 : ChipLogDetail(Inet, "UDP::Init bound to port=%d", mUDPEndPoint->GetBoundPort());
64 :
65 7 : exit:
66 14 : if (err != CHIP_NO_ERROR)
67 : {
68 0 : ChipLogProgress(Inet, "Failed to initialize Udp transport: %" CHIP_ERROR_FORMAT, err.Format());
69 0 : mUDPEndPoint.Release();
70 : }
71 :
72 7 : return err;
73 : }
74 :
75 4 : uint16_t UDP::GetBoundPort()
76 : {
77 4 : VerifyOrDie(mUDPEndPoint);
78 4 : return mUDPEndPoint->GetBoundPort();
79 : }
80 :
81 3 : void UDP::Close()
82 : {
83 3 : mUDPEndPoint.Release();
84 3 : mState = State::kNotReady;
85 3 : }
86 :
87 4 : CHIP_ERROR UDP::SendMessage(const Transport::PeerAddress & address, System::PacketBufferHandle && msgBuf)
88 : {
89 4 : VerifyOrReturnError(address.GetTransportType() == Type::kUdp, CHIP_ERROR_INVALID_ARGUMENT);
90 4 : VerifyOrReturnError(mState == State::kInitialized, CHIP_ERROR_INCORRECT_STATE);
91 4 : VerifyOrReturnError(mUDPEndPoint, CHIP_ERROR_INCORRECT_STATE);
92 :
93 4 : Inet::IPPacketInfo addrInfo;
94 4 : addrInfo.Clear();
95 :
96 4 : addrInfo.DestAddress = address.GetIPAddress();
97 4 : addrInfo.DestPort = address.GetPort();
98 4 : addrInfo.Interface = address.GetInterface();
99 :
100 : // Drop the message and return. Free the buffer.
101 4 : CHIP_FAULT_INJECT(FaultInjection::kFault_DropOutgoingUDPMsg, msgBuf = nullptr; return CHIP_ERROR_CONNECTION_ABORTED;);
102 :
103 3 : return mUDPEndPoint->SendMsg(&addrInfo, std::move(msgBuf));
104 : }
105 :
106 2 : void UDP::OnUdpReceive(Inet::UDPEndPoint * endPoint, System::PacketBufferHandle && buffer, const Inet::IPPacketInfo * pktInfo)
107 : {
108 2 : CHIP_ERROR err = CHIP_NO_ERROR;
109 2 : UDP * udp = reinterpret_cast<UDP *>(endPoint->mAppState);
110 2 : PeerAddress peerAddress = PeerAddress::UDP(pktInfo->SrcAddress, pktInfo->SrcPort, pktInfo->Interface);
111 :
112 2 : auto & testing = Groupcast::GetTesting();
113 2 : if (testing.IsEnabled())
114 : {
115 0 : PeerAddress destAddress = PeerAddress::UDP(pktInfo->DestAddress, pktInfo->DestPort, pktInfo->Interface);
116 0 : testing.SetSourceIpAddress(peerAddress.GetIPAddress());
117 0 : testing.SetDestinationIpAddress(destAddress.GetIPAddress());
118 : }
119 :
120 2 : CHIP_FAULT_INJECT(FaultInjection::kFault_DropIncomingUDPMsg, buffer = nullptr; return;);
121 :
122 2 : udp->HandleMessageReceived(peerAddress, std::move(buffer));
123 :
124 4 : if (err != CHIP_NO_ERROR)
125 : {
126 0 : ChipLogError(Inet, "Failed to receive UDP message: %" CHIP_ERROR_FORMAT, err.Format());
127 : }
128 : }
129 :
130 0 : void UDP::OnUdpError(Inet::UDPEndPoint * endPoint, CHIP_ERROR err, const Inet::IPPacketInfo * pktInfo)
131 : {
132 0 : ChipLogError(Inet, "Failed to receive UDP message: %" CHIP_ERROR_FORMAT, err.Format());
133 0 : }
134 :
135 0 : CHIP_ERROR UDP::MulticastGroupJoinLeave(const Transport::PeerAddress & address, bool join)
136 : {
137 : char addressStr[Transport::PeerAddress::kMaxToStringSize];
138 0 : address.ToString(addressStr, Transport::PeerAddress::kMaxToStringSize);
139 :
140 0 : if (join)
141 : {
142 0 : ChipLogProgress(Inet, "Joining Multicast Group with address %s", addressStr);
143 0 : return mUDPEndPoint->JoinMulticastGroup(mUDPEndPoint->GetBoundInterface(), address.GetIPAddress());
144 : }
145 :
146 0 : ChipLogProgress(Inet, "Leaving Multicast Group with address %s", addressStr);
147 0 : return mUDPEndPoint->LeaveMulticastGroup(mUDPEndPoint->GetBoundInterface(), address.GetIPAddress());
148 : }
149 :
150 : } // namespace Transport
151 : } // namespace chip
|