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