07aeb5822c63dfb55e27116084048f6f9eb8b2d5
[platform/core/api/webapi-plugins.git] / src / bluetooth / bluetooth_gatt_server_service.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include <string>
18
19 #include "bluetooth/bluetooth_gatt_server.h"
20 #include "bluetooth/bluetooth_gatt_server_service.h"
21 #include "bluetooth/bluetooth_instance.h"
22 #include "bluetooth/bluetooth_util.h"
23 #include "bluetooth/uuid.h"
24
25 #include "common/logger.h"
26 #include "common/platform_result.h"
27 #include "common/tools.h"
28
29 using namespace extension::bluetooth::util;
30 using common::PlatformResult;
31 using common::ErrorCode;
32
33 namespace extension {
34 namespace bluetooth {
35
36 namespace {
37 const std::string kUuid = "uuid";
38 const std::string kServiceUuid = "serviceUuid";
39 const std::string kIsPrimary = "isPrimary";
40 const std::string kCharacteristics = "characteristics";
41
42 const std::string kServices = "services";
43 const std::string kDescriptors = "descriptors";
44 const std::string kIsBroadcast = "isBroadcast";
45 const std::string kHasExtendedProperties = "hasExtendedProperties";
46 const std::string kIsNotify = "isNotify";
47 const std::string kIsIndication = "isIndication";
48 const std::string kIsReadable = "isReadable";
49 const std::string kIsSignedWrite = "isSignedWrite";
50 const std::string kIsWritable = "isWritable";
51 const std::string kIsWriteNoResponse = "isWriteNoResponse";
52 const std::string kReadPermission = "readPermission";
53 const std::string kWritePermission = "writePermission";
54 const std::string kEncryptedReadPermission = "encryptedReadPermission";
55 const std::string kEncryptedWritePermission = "encryptedWritePermission";
56 const std::string kEncryptedSignedReadPermission = "encryptedSignedReadPermission";
57 const std::string kEncryptedSignedWritePermission = "encryptedSignedWritePermission";
58
59 const std::string kId = "_id";
60 const std::string kIdsToRemoveFromNativeLayer = "idsToRemoveFromNativeLayer";
61 const std::string kClientAddress = "clientAddress";
62 const std::string kRequestId = "requestId";
63 const std::string kValue = "value";
64 const std::string kOffset = "offset";
65 const std::string kReplyRequired = "replyRequired";
66 const std::string kRequestType = "requestType";
67 const std::string kReadRequestType = "readRequestType";
68 const std::string kWriteRequestType = "writeRequestType";
69 const std::string kStatusCode = "statusCode";
70 const std::string kData = "data";
71 const std::string kReadCallback = "readCallback";
72 const std::string kWriteCallback = "writeCallback";
73
74 int GetPermissionsInt(const picojson::value& permissions) {
75   ScopeLogger("permissions: %s", permissions.serialize().c_str());
76
77   int ret = 0;
78   if (permissions.get(kReadPermission).get<bool>()) {
79     ret |= BT_GATT_PERMISSION_READ;
80   }
81   if (permissions.get(kWritePermission).get<bool>()) {
82     ret |= BT_GATT_PERMISSION_WRITE;
83   }
84   if (permissions.get(kEncryptedReadPermission).get<bool>()) {
85     ret |= BT_GATT_PERMISSION_ENCRYPT_READ;
86   }
87   if (permissions.get(kEncryptedWritePermission).get<bool>()) {
88     ret |= BT_GATT_PERMISSION_ENCRYPT_WRITE;
89   }
90   if (permissions.get(kEncryptedSignedReadPermission).get<bool>()) {
91     ret |= BT_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_READ;
92   }
93   if (permissions.get(kEncryptedSignedWritePermission).get<bool>()) {
94     ret |= BT_GATT_PERMISSION_ENCRYPT_AUTHENTICATED_WRITE;
95   }
96
97   LoggerD("Permissions: %x", static_cast<unsigned int>(ret));
98   return ret;
99 }
100
101 int GetPropertiesInt(const picojson::value& properties) {
102   ScopeLogger("properties: %s", properties.serialize().c_str());
103
104   int ret = 0;
105   if (properties.get(kIsBroadcast).get<bool>()) {
106     ret |= BT_GATT_PROPERTY_BROADCAST;
107   }
108   if (properties.get(kIsReadable).get<bool>()) {
109     ret |= BT_GATT_PROPERTY_READ;
110   }
111   if (properties.get(kIsWriteNoResponse).get<bool>()) {
112     ret |= BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE;
113   }
114   if (properties.get(kIsWritable).get<bool>()) {
115     ret |= BT_GATT_PROPERTY_WRITE;
116   }
117   if (properties.get(kIsNotify).get<bool>()) {
118     ret |= BT_GATT_PROPERTY_NOTIFY;
119   }
120   if (properties.get(kIsIndication).get<bool>()) {
121     ret |= BT_GATT_PROPERTY_INDICATE;
122   }
123   if (properties.get(kIsSignedWrite).get<bool>()) {
124     ret |= BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES;
125   }
126   if (properties.get(kHasExtendedProperties).get<bool>()) {
127     ret |= BT_GATT_PROPERTY_EXTENDED_PROPERTIES;
128   }
129
130   LoggerD("Properties: %x", static_cast<unsigned int>(ret));
131   return ret;
132 }
133
134 }  // namespace
135
136 bool BluetoothGATTServerService::DestroyService(int total, int index, bt_gatt_h handle,
137                                                 void* user_data) {
138   ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
139
140   /*
141    * Undocumented behavior of native Bluetooth API:
142    * bt_gatt_service_destroy() destroys not only the service, but also all
143    * its components (included services, characteristics, descriptors)
144    * recursively.
145    */
146   auto ret = bt_gatt_service_destroy(handle);
147   if (BT_ERROR_NONE != ret) {
148     LoggerE("bt_gatt_service_destroy(): %d (%s)", ret, get_error_message(ret));
149   }
150   LoggerD("bt_gatt_service_destroy(): success");
151
152   return true;
153 }
154
155 bool BluetoothGATTServerService::DestroyCharacteristic(int total, int index, bt_gatt_h handle,
156                                                        void* user_data) {
157   ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
158
159   auto ret = bt_gatt_characteristic_destroy(handle);
160   if (BT_ERROR_NONE != ret) {
161     LoggerE("bt_gatt_characteristic_destroy(): %d (%s)", ret, get_error_message(ret));
162   }
163   LoggerD("bt_gatt_characteristic_destroy(): success");
164
165   return true;
166 }
167
168 bool BluetoothGATTServerService::DestroyDescriptor(int total, int index, bt_gatt_h handle,
169                                                    void* user_data) {
170   ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
171
172   auto ret = bt_gatt_descriptor_destroy(handle);
173   if (BT_ERROR_NONE != ret) {
174     LoggerE("bt_gatt_descriptor_destroy(): %d (%s)", ret, get_error_message(ret));
175   }
176   LoggerD("bt_gatt_descriptor_destroy(): success");
177
178   return true;
179 }
180
181 BluetoothGATTServerService::BluetoothGATTServerService(BluetoothInstance& instance)
182     : instance_{instance}, rw_request_callback_data_{instance, callback_names_} {
183   ScopeLogger();
184 }
185
186 BluetoothGATTServerService::~BluetoothGATTServerService() {
187   ScopeLogger();
188 }
189
190 common::PlatformResult BluetoothGATTServerService::AddDescriptors(
191     const picojson::array& descriptors_init, bt_gatt_h characteristic_handle,
192     std::vector<std::pair<int, bt_gatt_h>>& new_gatt_objects) {
193   ScopeLogger("descriptors_init length: %zu", descriptors_init.size());
194
195   /*
196    * This function expects valid input.
197    * If it gets descriptors missing any: uuid, permission,
198    * or with one of these with a wrong type, the application will crash.
199    */
200
201   for (const auto& descriptor_init_data : descriptors_init) {
202     const auto& uuid_str = descriptor_init_data.get(kUuid).get<std::string>();
203     /*
204      * Native APIs don't support 32-bit UUIDs. We convert any UUID to its 128-bit
205      * form to assure, it will be accepted by the native API.
206      *
207      * We assume, UUID::create() returns a valid object, because the input is valid.
208      */
209     auto uuid = UUID::create(uuid_str);
210     int permissions = GetPermissionsInt(descriptor_init_data);
211     bt_gatt_h descriptor_handle = nullptr;
212
213     int ret = bt_gatt_descriptor_create(uuid->uuid_128_bit.c_str(), permissions, nullptr, 0,
214                                         &descriptor_handle);
215     if (BT_ERROR_NONE != ret) {
216       LoggerE("bt_gatt_descriptor_create() failed: %d (%s)", ret, get_error_message(ret));
217       return BluetoothErrorToPlatformResult(ret, "Failed to create a descriptor");
218     }
219     LoggerD("bt_gatt_descriptor_create(): success");
220
221     ret = bt_gatt_characteristic_add_descriptor(characteristic_handle, descriptor_handle);
222     if (BT_ERROR_NONE != ret) {
223       LoggerE("bt_gatt_characteristic_add_descriptor() failed: %d (%s)", ret,
224               get_error_message(ret));
225       DestroyDescriptor(0, 0, descriptor_handle, nullptr);
226       return BluetoothErrorToPlatformResult(ret, "Failed to add descriptor to characteristic");
227     }
228     LoggerD("bt_gatt_characteristic_add_descriptor(): success");
229
230     const auto _id = static_cast<int>(descriptor_init_data.get(kId).get<double>());
231     new_gatt_objects.push_back({_id, descriptor_handle});
232   }
233
234   return common::PlatformResult();
235 }
236
237 common::PlatformResult BluetoothGATTServerService::AddCharacteristics(
238     const picojson::array& characteristics_init, bt_gatt_h service_handle,
239     std::vector<std::pair<int, bt_gatt_h>>& new_gatt_objects) {
240   ScopeLogger("characteristics_init length: %zu", characteristics_init.size());
241
242   /*
243    * This function expects valid input.
244    * If it gets characteristics missing any: uuid, permission, property,
245    * or with any of these with a wrong type, the application will crash.
246    */
247
248   for (const auto& characteristic_init_data : characteristics_init) {
249     const auto& uuid_str = characteristic_init_data.get(kUuid).get<std::string>();
250     /*
251      * Native APIs don't support 32-bit UUIDs. We convert any UUID to its 128-bit
252      * form to assure, it will be accepted by the native API.
253      *
254      * We assume, UUID::create() returns a valid object, because the input is valid.
255      */
256     auto uuid = UUID::create(uuid_str);
257
258     int permissions = GetPermissionsInt(characteristic_init_data);
259     int properties = GetPropertiesInt(characteristic_init_data);
260     bt_gatt_h characteristic_handle = nullptr;
261
262     int ret = bt_gatt_characteristic_create(uuid->uuid_128_bit.c_str(), permissions, properties,
263                                             nullptr, 0, &characteristic_handle);
264     if (BT_ERROR_NONE != ret) {
265       LoggerE("bt_gatt_characteristic_create() failed: %d (%s)", ret, get_error_message(ret));
266       return BluetoothErrorToPlatformResult(ret, "Failed to create a characteristic");
267     }
268     LoggerD("bt_gatt_characteristic_create(): success");
269
270     if (characteristic_init_data.get(kDescriptors).is<picojson::array>()) {
271       const auto& descriptors = characteristic_init_data.get(kDescriptors).get<picojson::array>();
272       auto result = AddDescriptors(descriptors, characteristic_handle, new_gatt_objects);
273       if (!result) {
274         DestroyCharacteristic(0, 0, characteristic_handle, nullptr);
275         return result;
276       }
277     }
278
279     ret = bt_gatt_service_add_characteristic(service_handle, characteristic_handle);
280     if (BT_ERROR_NONE != ret) {
281       LoggerE("bt_gatt_service_add_characteristic() failed: %d (%s)", ret, get_error_message(ret));
282       DestroyCharacteristic(0, 0, characteristic_handle, nullptr);
283       return BluetoothErrorToPlatformResult(ret, "Failed to add a characteristic to a service");
284     }
285     LoggerD("bt_gatt_service_add_characteristic(): success");
286
287     const auto _id = static_cast<int>(characteristic_init_data.get(kId).get<double>());
288     new_gatt_objects.push_back({_id, characteristic_handle});
289   }
290
291   return common::PlatformResult();
292 }
293
294 common::PlatformResult BluetoothGATTServerService::AddIncludedServices(
295     const picojson::array& included_services_init, bt_gatt_h parent_service_handle,
296     std::vector<std::pair<int, bt_gatt_h>>& new_gatt_objects) {
297   ScopeLogger("included_services_init length: %zu", included_services_init.size());
298
299   /*
300    * This function expects valid input.
301    * If it gets included_services missing a uuid
302    * or with any of these with a wrong type, the application will crash.
303    */
304
305   for (const auto& service_init_data : included_services_init) {
306     bt_gatt_h included_service_handle = nullptr;
307     auto result = CreateService(service_init_data, &included_service_handle, new_gatt_objects);
308     if (!result) {
309       LoggerE("Failed to create included service");
310       return result;
311     }
312
313     int ret = bt_gatt_service_add_included_service(parent_service_handle, included_service_handle);
314     if (BT_ERROR_NONE != ret) {
315       LoggerE("bt_gatt_service_add_included_service() failed: %d (%s)", ret,
316               get_error_message(ret));
317       DestroyService(0, 0, included_service_handle, nullptr);
318       return BluetoothErrorToPlatformResult(ret, "Failed to add included service");
319     }
320     LoggerD("bt_gatt_service_add_included_service(): success");
321
322     const auto _id = static_cast<int>(service_init_data.get(kId).get<double>());
323     new_gatt_objects.push_back({_id, parent_service_handle});
324   }
325
326   return common::PlatformResult();
327 }
328
329 common::PlatformResult BluetoothGATTServerService::CreateService(
330     const picojson::value& service_init, bt_gatt_h* new_service_handle,
331     std::vector<std::pair<int, bt_gatt_h>>& new_gatt_objects) {
332   ScopeLogger("service_init: %s", service_init.serialize().c_str());
333   /*
334    * This function expects valid input.
335    * If it gets service_init without any of the expected members or with a member of
336    * a wrong type, the application will crash.
337    */
338
339   const auto& uuid_str = service_init.get(kServiceUuid).get<std::string>();
340   /*
341    * Native APIs don't support 32-bit UUIDs. We convert any UUID to its 128-bit
342    * form to assure, it will be accepted by the native API.
343    *
344    * We assume, UUID::create() returns a valid object, because the input is valid.
345    */
346   auto uuid = UUID::create(uuid_str);
347   bool primary = service_init.get(kIsPrimary).get<bool>();
348   bt_gatt_service_type_e type =
349       primary ? BT_GATT_SERVICE_TYPE_PRIMARY : BT_GATT_SERVICE_TYPE_SECONDARY;
350   bt_gatt_h service_handle = nullptr;
351
352   int err = bt_gatt_service_create(uuid->uuid_128_bit.c_str(), type, &service_handle);
353   if (BT_ERROR_NONE != err) {
354     LoggerE("bt_gatt_service_create error: %d (%s)", err, get_error_message(err));
355     return BluetoothErrorToPlatformResult(err, "Failed to create GATT service");
356   }
357   LoggerD("bt_gatt_service_create(): success");
358
359   if (service_init.get(kServices).is<picojson::array>()) {
360     const auto& services = service_init.get(kServices).get<picojson::array>();
361     auto result = AddIncludedServices(services, service_handle, new_gatt_objects);
362     if (!result) {
363       DestroyService(0, 0, service_handle, nullptr);
364       return result;
365     }
366   }
367
368   if (service_init.get(kCharacteristics).is<picojson::array>()) {
369     const auto& characteristics = service_init.get(kCharacteristics).get<picojson::array>();
370     auto result = AddCharacteristics(characteristics, service_handle, new_gatt_objects);
371     if (!result) {
372       DestroyService(0, 0, service_handle, nullptr);
373       return result;
374     }
375   }
376
377   const auto _id = static_cast<int>(service_init.get(kId).get<double>());
378   new_gatt_objects.push_back({_id, service_handle});
379
380   *new_service_handle = service_handle;
381
382   return common::PlatformResult();
383 }
384
385 common::PlatformResult BluetoothGATTServerService::RegisterService(
386     bt_gatt_h service_handle, bt_gatt_server_h server,
387     const std::vector<std::pair<int, bt_gatt_h>>& new_gatt_objects) {
388   ScopeLogger();
389
390   int ret = bt_gatt_server_register_service(server, service_handle);
391   if (BT_ERROR_NONE != ret) {
392     LoggerE("bt_gatt_server_register_service() failed: %d (%s)", ret, get_error_message(ret));
393     return BluetoothErrorToPlatformResult(ret, "Failed to register GATT service");
394   }
395
396   gatt_objects_.insert(new_gatt_objects.begin(), new_gatt_objects.end());
397
398   return common::PlatformResult();
399 }
400
401 common::PlatformResult BluetoothGATTServerService::UnregisterService(const picojson::value& args,
402                                                                      bt_gatt_server_h server) {
403   ScopeLogger();
404
405   auto _id = static_cast<int>(args.get(kId).get<double>());
406   LoggerD("Unregistering service with _id: %d", _id);
407
408   auto service_handle = gatt_objects_[_id];
409
410   /*
411    * Undocumented behavior of native Bluetooth API:
412    * bt_gatt_server_unregister_service() not only unregisters the service,
413    * but also calls bt_gatt_destroy_service() on its handle, destroying
414    * the corresponding service object and all its components (included services,
415    * characteristics, descriptors).
416    */
417   auto ret = bt_gatt_server_unregister_service(server, service_handle);
418   if (BT_ERROR_NONE != ret) {
419     LoggerE("bt_gatt_server_unregister_service() failed: %d (%s)", ret, get_error_message(ret));
420     return BluetoothErrorToPlatformResult(ret, "Failed to unregister GATT service");
421   }
422   LoggerD("bt_gatt_server_unregister_service(): SUCCESS");
423
424   gatt_objects_.erase(_id);
425
426   auto ids_to_remove = args.get(kIdsToRemoveFromNativeLayer).get<picojson::array>();
427   for (const auto& to_remove : ids_to_remove) {
428     const auto id_to_remove = static_cast<int>(to_remove.get<double>());
429
430     auto handle_to_remove = gatt_objects_[id_to_remove];
431     LoggerD("Erasing gatt object with _id: %d", id_to_remove);
432     callback_names_.erase(std::make_pair(handle_to_remove, kReadCallback));
433     callback_names_.erase(std::make_pair(handle_to_remove, kWriteCallback));
434     gatt_objects_.erase(id_to_remove);
435   }
436
437   return common::PlatformResult{};
438 }
439
440 PlatformResult BluetoothGATTServerService::SetReadValueRequestCallback(
441     const picojson::value& args) {
442   ScopeLogger();
443
444   auto _id = static_cast<int>(args.get(kId).get<double>());
445   LoggerD("Setting read value request callback for a GATT entity with _id: %d", _id);
446
447   auto gatt_handle = gatt_objects_[_id];
448   callback_names_[std::make_pair(gatt_handle, kReadCallback)] =
449       "ReadValueRequestCallback_" + std::to_string(_id);
450
451   auto read_value_request_callback = [](const char* remote_address, int request_id,
452                                         bt_gatt_server_h server, bt_gatt_h gatt_handle, int offset,
453                                         void* user_data) -> void {
454     ScopeLogger("ReadValueRequestCallback called. remote_address: %s, request_id: %d, offset: %d",
455                 remote_address, request_id, offset);
456     auto rw_callback_data = static_cast<ReadWriteRequestCallbackData*>(user_data);
457
458     // We create a copy of this value, because remote_address pointer will be invalid
459     // when the job will be executed in the worker
460     auto remote_address_copy = std::string{remote_address};
461
462     rw_callback_data->instance_.GetWorker().add_job(
463         [remote_address_copy, request_id, server, gatt_handle, offset, rw_callback_data] {
464           ScopeLogger("Async call: SetReadValueRequestCallback");
465
466           auto read_value_request = picojson::value{picojson::object{}};
467           auto& read_value_request_obj = read_value_request.get<picojson::object>();
468           read_value_request_obj[kClientAddress] = picojson::value{remote_address_copy};
469           read_value_request_obj[kRequestId] = picojson::value{static_cast<double>(request_id)};
470           read_value_request_obj[kRequestType] = picojson::value{kReadRequestType};
471           read_value_request_obj[kOffset] = picojson::value{static_cast<double>(offset)};
472           const auto callback_name =
473               rw_callback_data->callback_names_map_[std::make_pair(gatt_handle, kReadCallback)];
474           LoggerD("Firing read value request event: %s: %s", callback_name.c_str(),
475                   read_value_request.serialize().c_str());
476           rw_callback_data->instance_.FireEvent(callback_name, read_value_request);
477         });
478   };
479
480   auto ret = bt_gatt_server_set_read_value_requested_cb(gatt_handle, read_value_request_callback,
481                                                         &rw_request_callback_data_);
482   if (BT_ERROR_NONE != ret) {
483     LoggerE("bt_gatt_server_set_read_value_requested_cb() failed: %d (%s)", ret,
484             get_error_message(ret));
485     return BluetoothErrorToPlatformResult(ret, "Failed to set read value request callback");
486   }
487
488   LoggerD("bt_gatt_server_set_read_value_requested_cb(): SUCCESS");
489   return common::PlatformResult{};
490 }
491
492 PlatformResult BluetoothGATTServerService::SetWriteValueRequestCallback(
493     const picojson::value& args) {
494   ScopeLogger();
495
496   auto _id = static_cast<int>(args.get(kId).get<double>());
497   LoggerD("Setting write value request callback for a GATT entity with _id: %d", _id);
498
499   auto gatt_handle = gatt_objects_[_id];
500   callback_names_[std::make_pair(gatt_handle, kWriteCallback)] =
501       "WriteValueRequestCallback_" + std::to_string(_id);
502
503   auto write_value_request_callback = [](
504       const char* remote_address, int request_id, bt_gatt_server_h server, bt_gatt_h gatt_handle,
505       bool response_needed, int offset, const char* value, int len, void* user_data) -> void {
506     ScopeLogger(
507         "WriteValueRequestCallback called. remote_address: %s, request_id: %d, response_needed: "
508         "%d, offset: %d, value: %s, len: %d",
509         remote_address, request_id, response_needed, offset, value, len);
510     auto rw_callback_data = static_cast<ReadWriteRequestCallbackData*>(user_data);
511
512     // We create a copy of value and remote_address
513     auto remote_address_copy = std::string{remote_address};
514     auto value_copy = std::string{value};
515     rw_callback_data->instance_.GetWorker().add_job([remote_address_copy, request_id, server,
516                                                      gatt_handle, response_needed, offset, value_copy,
517                                                      rw_callback_data] {
518       ScopeLogger("Async call: SetWriteValueRequestCallback");
519
520       auto write_value_request = picojson::value{picojson::object{}};
521       auto& write_value_request_obj = write_value_request.get<picojson::object>();
522       write_value_request_obj[kClientAddress] = picojson::value{remote_address_copy};
523       write_value_request_obj[kRequestId] = picojson::value{static_cast<double>(request_id)};
524       write_value_request_obj[kRequestType] = picojson::value{kWriteRequestType};
525       write_value_request_obj[kReplyRequired] = picojson::value{response_needed};
526       write_value_request_obj[kOffset] = picojson::value{static_cast<double>(offset)};
527
528       write_value_request_obj[kValue] = picojson::value{picojson::array{}};
529       auto& value_byte_array = write_value_request_obj[kValue].get<picojson::array>();
530       for (auto c: value_copy) {
531         value_byte_array.push_back(picojson::value{static_cast<double>(c)});
532       }
533       const auto callback_name =
534           rw_callback_data->callback_names_map_[std::make_pair(gatt_handle, kWriteCallback)];
535       LoggerD("Firing write value request event: %s: %s", callback_name.c_str(),
536               write_value_request.serialize().c_str());
537       rw_callback_data->instance_.FireEvent(callback_name, write_value_request);
538     });
539   };
540
541   auto ret = bt_gatt_server_set_write_value_requested_cb(gatt_handle, write_value_request_callback,
542                                                          &rw_request_callback_data_);
543   if (BT_ERROR_NONE != ret) {
544     LoggerE("bt_gatt_server_set_write_value_requested_cb() failed: %d (%s)", ret,
545             get_error_message(ret));
546     return BluetoothErrorToPlatformResult(ret, "Failed to set write value request callback");
547   }
548
549   LoggerD("bt_gatt_server_set_write_value_requested_cb(): SUCCESS");
550   return common::PlatformResult{};
551 }
552
553 PlatformResult BluetoothGATTServerService::SendResponse(const picojson::value& args) {
554   ScopeLogger("Response: %s", args.serialize().c_str());
555
556   auto _id = static_cast<int>(args.get(kId).get<double>());
557   auto request_id = static_cast<int>(args.get(kRequestId).get<double>());
558   auto request_type_str = args.get(kRequestType).get<std::string>();
559   auto request_type = (request_type_str == kReadRequestType) ? BT_GATT_REQUEST_TYPE_READ
560                                                              : BT_GATT_REQUEST_TYPE_WRITE;
561   auto offset = static_cast<int>(args.get(kOffset).get<double>());
562   auto status_code = static_cast<int>(args.get(kStatusCode).get<double>());
563
564   std::unique_ptr<char[]> value{nullptr};
565   int value_size = 0;
566   if (args.get(kData).is<picojson::array>()) {
567     auto value_octets = args.get(kData).get<picojson::array>();
568     value_size = value_octets.size();
569     value = std::make_unique<char[]>(value_size);
570     for (int i = 0; i < value_size; ++i) {
571       value[i] += static_cast<int>(value_octets[i].get<double>());
572     }
573   } else {
574     LoggerD("No data!");
575   }
576
577   LoggerD(
578       "Sending response: _id: %d, requestId: %d, requestType: %s, offset: %d, statusCode: %d, "
579       "value: [%p], value size: %d",
580       _id, request_id, request_type_str.c_str(), offset, status_code, value.get(), value_size);
581
582   auto ret = bt_gatt_server_send_response(request_id, request_type, offset, status_code,
583                                           value.get(), value_size);
584   if (BT_ERROR_NONE != ret) {
585     LoggerE("bt_gatt_server_send_response() failed: %d (%s)", ret, get_error_message(ret));
586     return BluetoothErrorToPlatformResult(ret, "Failed to send response");
587   }
588   LoggerD("bt_gatt_server_send_response(): SUCCESS");
589
590   return common::PlatformResult{};
591 }
592
593 }  // namespace bluetooth
594 }  // namespace extension