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