Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / BLE.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    All rights reserved.
5  *
6  *    Licensed under the Apache License, Version 2.0 (the "License");
7  *    you may not use this file except in compliance with the License.
8  *    You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *    Unless required by applicable law or agreed to in writing, software
13  *    distributed under the License is distributed on an "AS IS" BASIS,
14  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *    See the License for the specific language governing permissions and
16  *    limitations under the License.
17  */
18
19 /**
20  *    @file
21  *      This file implements the CHIP Connection object that maintains a BLE connection.
22  *
23  */
24
25 #include <transport/BLE.h>
26
27 #include <support/CodeUtils.h>
28 #include <support/logging/CHIPLogging.h>
29 #include <transport/raw/MessageHeader.h>
30
31 #include <inttypes.h>
32
33 using namespace chip::Ble;
34 using namespace chip::System;
35
36 namespace chip {
37 namespace Transport {
38
39 BLE::~BLE()
40 {
41     ClearState();
42 }
43
44 void BLE::ClearState()
45 {
46     if (mBleLayer)
47     {
48         mBleLayer->CancelBleIncompleteConnection();
49         mBleLayer->OnChipBleConnectReceived = nullptr;
50         mBleLayer                           = nullptr;
51     }
52
53     if (mBleEndPoint)
54     {
55         mBleEndPoint->Close();
56         mBleEndPoint = nullptr;
57     }
58 }
59
60 CHIP_ERROR BLE::Init(RendezvousSessionDelegate * delegate, const RendezvousParameters & params)
61 {
62     CHIP_ERROR err      = CHIP_NO_ERROR;
63     BleLayer * bleLayer = params.GetBleLayer();
64
65     VerifyOrExit(mState == State::kNotReady, err = CHIP_ERROR_INCORRECT_STATE);
66     VerifyOrExit(bleLayer, err = CHIP_ERROR_INCORRECT_STATE);
67
68     mDelegate = delegate;
69
70     mBleLayer                           = bleLayer;
71     mBleLayer->mAppState                = reinterpret_cast<void *>(this);
72     mBleLayer->OnChipBleConnectReceived = OnNewConnection;
73
74     if (params.HasDiscriminator())
75     {
76         err = mBleLayer->NewBleConnection(reinterpret_cast<void *>(this), params.GetDiscriminator(), OnBleConnectionComplete,
77                                           OnBleConnectionError);
78     }
79     else if (params.HasConnectionObject())
80     {
81         err = InitInternal(params.GetConnectionObject());
82     }
83     SuccessOrExit(err);
84
85 exit:
86     return err;
87 }
88
89 CHIP_ERROR BLE::InitInternal(BLE_CONNECTION_OBJECT connObj)
90 {
91     CHIP_ERROR err = CHIP_NO_ERROR;
92
93     err = mBleLayer->NewBleEndPoint(&mBleEndPoint, connObj, kBleRole_Central, true);
94     SuccessOrExit(err);
95
96     // Initiate CHIP over BLE protocol connection.
97     SetupEvents(mBleEndPoint);
98     err = mBleEndPoint->StartConnect();
99     SuccessOrExit(err);
100
101 exit:
102     if (err != CHIP_NO_ERROR)
103     {
104         ClearState();
105     }
106     return err;
107 }
108
109 CHIP_ERROR BLE::SetEndPoint(Ble::BLEEndPoint * endPoint)
110 {
111     CHIP_ERROR err = CHIP_NO_ERROR;
112
113     VerifyOrExit(endPoint->mState == BLEEndPoint::kState_Connected, err = CHIP_ERROR_INVALID_ARGUMENT);
114
115     mBleEndPoint = endPoint;
116     SetupEvents(mBleEndPoint);
117
118     // Manually trigger the OnConnectComplete callback.
119     OnBleEndPointConnectionComplete(endPoint, err);
120
121 exit:
122     return err;
123 }
124
125 void BLE::SetupEvents(Ble::BLEEndPoint * endPoint)
126 {
127     endPoint->mAppState          = reinterpret_cast<void *>(this);
128     endPoint->OnMessageReceived  = OnBleEndPointReceive;
129     endPoint->OnConnectComplete  = OnBleEndPointConnectionComplete;
130     endPoint->OnConnectionClosed = OnBleEndPointConnectionClosed;
131 }
132
133 CHIP_ERROR BLE::SendMessage(const PacketHeader & header, const Transport::PeerAddress & address, System::PacketBufferHandle msgBuf)
134 {
135     CHIP_ERROR err = CHIP_NO_ERROR;
136
137     VerifyOrExit(address.GetTransportType() == Type::kBle, err = CHIP_ERROR_INVALID_ARGUMENT);
138     VerifyOrExit(mState == State::kInitialized, err = CHIP_ERROR_INCORRECT_STATE);
139     VerifyOrExit(mBleEndPoint != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
140
141     err = header.EncodeBeforeData(msgBuf);
142     SuccessOrExit(err);
143
144     err = mBleEndPoint->Send(std::move(msgBuf));
145     SuccessOrExit(err);
146
147 exit:
148     return err;
149 }
150
151 void BLE::OnBleConnectionComplete(void * appState, BLE_CONNECTION_OBJECT connObj)
152 {
153     CHIP_ERROR err = CHIP_NO_ERROR;
154     BLE * ble      = reinterpret_cast<BLE *>(appState);
155
156     // TODO(#4547): On darwin, OnBleConnectionComplete is called multiple times for the same peripheral, this should become an error
157     // in the future.
158     VerifyOrExit(ble->mBleEndPoint == nullptr || !ble->mBleEndPoint->ConnectionObjectIs(connObj),
159                  ChipLogError(Ble, "Warning: OnBleConnectionComplete is called multiple times for the same peripheral."));
160
161     err = ble->InitInternal(connObj);
162     SuccessOrExit(err);
163
164 exit:
165     if (err != CHIP_NO_ERROR)
166     {
167         ble->OnBleConnectionError(appState, err);
168     }
169 }
170
171 void BLE::OnBleConnectionError(void * appState, BLE_ERROR err)
172 {
173     BLE * ble = reinterpret_cast<BLE *>(appState);
174
175     if (ble->mDelegate)
176     {
177         ble->mDelegate->OnRendezvousError(err);
178     }
179 }
180
181 void BLE::OnBleEndPointReceive(BLEEndPoint * endPoint, PacketBufferHandle buffer)
182 {
183     BLE * ble      = reinterpret_cast<BLE *>(endPoint->mAppState);
184     CHIP_ERROR err = CHIP_NO_ERROR;
185
186     if (ble->mDelegate)
187     {
188         PacketHeader header;
189         err = header.DecodeAndConsume(buffer);
190         SuccessOrExit(err);
191
192         ble->mDelegate->OnRendezvousMessageReceived(header, Transport::PeerAddress(Transport::Type::kBle), std::move(buffer));
193     }
194 exit:
195     if (err != CHIP_NO_ERROR)
196     {
197         ChipLogError(Inet, "Failed to receive BLE message: %s", ErrorStr(err));
198     }
199 }
200
201 void BLE::OnBleEndPointConnectionComplete(BLEEndPoint * endPoint, BLE_ERROR err)
202 {
203     BLE * ble   = reinterpret_cast<BLE *>(endPoint->mAppState);
204     ble->mState = State::kInitialized;
205
206     if (ble->mDelegate)
207     {
208         if (err != BLE_NO_ERROR)
209         {
210             ble->mDelegate->OnRendezvousError(err);
211         }
212         else
213         {
214             ble->mDelegate->OnRendezvousConnectionOpened();
215         }
216     }
217 }
218
219 void BLE::OnBleEndPointConnectionClosed(BLEEndPoint * endPoint, BLE_ERROR err)
220 {
221     BLE * ble   = reinterpret_cast<BLE *>(endPoint->mAppState);
222     ble->mState = State::kNotReady;
223
224     // Already closed, avoid closing again in our destructor.
225     ble->mBleEndPoint = nullptr;
226
227     if (ble->mDelegate)
228     {
229         if (err != BLE_NO_ERROR)
230         {
231             ble->mDelegate->OnRendezvousError(err);
232         }
233         else
234         {
235             // OnRendezvousError may delete |ble|; don't call both callbacks.
236             ble->mDelegate->OnRendezvousConnectionClosed();
237         }
238     }
239 }
240
241 void BLE::OnNewConnection(BLEEndPoint * endPoint)
242 {
243     BLE * ble      = reinterpret_cast<BLE *>(endPoint->mAppState);
244     CHIP_ERROR err = ble->SetEndPoint(endPoint);
245     if (err != CHIP_NO_ERROR)
246     {
247         ChipLogError(Ble, "Transport::BLE Init failure: %s", ErrorStr(err));
248     }
249 }
250
251 } // namespace Transport
252 } // namespace chip