1611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//
2611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  Copyright (C) 2015 Google, Inc.
3611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//
4611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  Licensed under the Apache License, Version 2.0 (the "License");
5611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  you may not use this file except in compliance with the License.
6611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  You may obtain a copy of the License at:
7611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//
8611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  http://www.apache.org/licenses/LICENSE-2.0
9611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//
10611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  Unless required by applicable law or agreed to in writing, software
11611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  distributed under the License is distributed on an "AS IS" BASIS,
12611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  See the License for the specific language governing permissions and
14611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//  limitations under the License.
15611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge//
16fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray
1749a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#define LOG_TAG "bt_bluetooth_host"
1849a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen
19e415c050edbb2710e8807dd2602c851412953268Scott James Remnant#include "service/ipc/linux_ipc_host.h"
20611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
21611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <errno.h>
22611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <stdio.h>
23611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <stdlib.h>
24611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/ioctl.h>
25611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/socket.h>
26611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/types.h>
27611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <sys/un.h>
28611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <unistd.h>
29611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
30611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include <algorithm>
31611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
32f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <base/base64.h>
33f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <base/strings/string_number_conversions.h>
34f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray#include <base/strings/string_split.h>
35f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray
36611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge#include "osi/include/log.h"
37911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "osi/include/osi.h"
38d6a4b0c950f44d3eab34825880d26c19e362d22bArman Uguray#include "service/adapter.h"
39fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray
40d6a4b0c950f44d3eab34825880d26c19e362d22bArman Ugurayusing bluetooth::Adapter;
41fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Ugurayusing bluetooth::UUID;
42fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray
43fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Ugurayusing namespace bluetooth::gatt;
44611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
45611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgenamespace {
46611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
47611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// IPC API is according to:
48611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// https://docs.google.com/document/d/1eRnku-jAyVU1wGJsLT2CzWi0-8bs2g49s1b3FR_GApM
49611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetAdapterNameCommand[] = "set-device-name";
50611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kCreateServiceCommand[] = "create-service";
51611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kDestroyServiceCommand[] = "destroy-service";
52611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kAddCharacteristicCommand[] = "add-characteristic";
53611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetCharacteristicValueCommand[] = "set-characteristic-value";
54611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetAdvertisementCommand[] = "set-advertisement";
55611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kSetScanResponseCommand[] = "set-scan-response";
56611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kStartServiceCommand[] = "start-service";
57611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kStopServiceCommand[] = "stop-service";
58611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeconst char kWriteCharacteristicCommand[] = "write-characteristic";
59611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
60e415c050edbb2710e8807dd2602c851412953268Scott James Remnant// Useful values for indexing LinuxIPCHost::pfds_
61611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge// Not super general considering that we should be able to support
62e415c050edbb2710e8807dd2602c851412953268Scott James Remnant// many GATT FDs owned by one LinuxIPCHost.
63611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidgeenum {
64611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  kFdIpc = 0,
65611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  kFdGatt = 1,
66611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  kPossibleFds = 2,
67611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge};
68611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool TokenBool(const std::string& text) { return text == "true"; }
70611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
71611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}  // namespace
72611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
73fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguraynamespace ipc {
74611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
75e415c050edbb2710e8807dd2602c851412953268Scott James RemnantLinuxIPCHost::LinuxIPCHost(int sockfd, Adapter* adapter)
76d6a4b0c950f44d3eab34825880d26c19e362d22bArman Uguray    : adapter_(adapter), pfds_(1, {sockfd, POLLIN, 0}) {}
77611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
78911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonLinuxIPCHost::~LinuxIPCHost() { close(pfds_[0].fd); }
79611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
80e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::EventLoop() {
81611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  while (true) {
82611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    int status =
83611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge        TEMP_FAILURE_RETRY(ppoll(pfds_.data(), pfds_.size(), nullptr, nullptr));
84611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    if (status < 1) {
85db554581079863974af8e1289646f5deea6fc044Marie Janssen      LOG_ERROR(LOG_TAG, "ppoll error");
86611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      return false;
87611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    }
88611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
89611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    if (pfds_[kFdIpc].revents && !OnMessage()) {
90611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      return false;
91611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    }
92611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (pfds_.size() == kPossibleFds && pfds_[kFdGatt].revents &&
94611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge        !OnGattWrite()) {
95611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      return false;
96611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    }
97611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
98611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
99611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
100611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
101e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnSetAdapterName(const std::string& name) {
102611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::string decoded_data;
103611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  base::Base64Decode(name, &decoded_data);
104d6a4b0c950f44d3eab34825880d26c19e362d22bArman Uguray  return adapter_->SetName(decoded_data);
105611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
106611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
107e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnCreateService(const std::string& service_uuid) {
108fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray  gatt_servers_[service_uuid] = std::unique_ptr<Server>(new Server);
109611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
110611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  int gattfd;
111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool status =
112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      gatt_servers_[service_uuid]->Initialize(UUID(service_uuid), &gattfd);
113611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (!status) {
114db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "Failed to initialize bluetooth");
115611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    return false;
116611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
117611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  pfds_.resize(kPossibleFds);
118611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  pfds_[kFdGatt] = {gattfd, POLLIN, 0};
119611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
120611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
121611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
122e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnDestroyService(const std::string& service_uuid) {
123611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  gatt_servers_.erase(service_uuid);
124611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  close(pfds_[1].fd);
125611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  pfds_.resize(1);
126611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
127611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
128611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
129e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnAddCharacteristic(const std::string& service_uuid,
130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                       const std::string& characteristic_uuid,
131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                       const std::string& control_uuid,
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                       const std::string& options) {
13357d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko  std::vector<std::string> option_tokens = base::SplitString(
13457d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko      options, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
135611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
136611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  int properties_mask = 0;
137611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  int permissions_mask = 0;
138611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
139611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (std::find(option_tokens.begin(), option_tokens.end(), "notify") !=
140611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      option_tokens.end()) {
141fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray    permissions_mask |= kPermissionRead;
142fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray    properties_mask |= kPropertyRead;
143fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray    properties_mask |= kPropertyNotify;
144611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
145611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (std::find(option_tokens.begin(), option_tokens.end(), "read") !=
146611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      option_tokens.end()) {
147fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray    permissions_mask |= kPermissionRead;
148fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray    properties_mask |= kPropertyRead;
149611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
150611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (std::find(option_tokens.begin(), option_tokens.end(), "write") !=
151611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      option_tokens.end()) {
152fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray    permissions_mask |= kPermissionWrite;
153fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray    properties_mask |= kPropertyWrite;
154611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
155611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
156611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (control_uuid.empty()) {
157611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    gatt_servers_[service_uuid]->AddCharacteristic(
158fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray        UUID(characteristic_uuid), properties_mask, permissions_mask);
159611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  } else {
160fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray    gatt_servers_[service_uuid]->AddBlob(UUID(characteristic_uuid),
161fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray                                         UUID(control_uuid), properties_mask,
162611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge                                         permissions_mask);
163611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
164611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
165611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
166611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool LinuxIPCHost::OnSetCharacteristicValue(
168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    const std::string& service_uuid, const std::string& characteristic_uuid,
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    const std::string& value) {
170611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::string decoded_data;
171611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  base::Base64Decode(value, &decoded_data);
172611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
173fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray  gatt_servers_[service_uuid]->SetCharacteristicValue(UUID(characteristic_uuid),
174611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge                                                      blob_data);
175611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
176611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
177611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
178e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnSetAdvertisement(const std::string& service_uuid,
179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                      const std::string& advertise_uuids,
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                      const std::string& advertise_data,
181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                      const std::string& manufacturer_data,
182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                      const std::string& transmit_name) {
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  LOG_INFO(LOG_TAG, "%s: service:%s uuids:%s data:%s", __func__,
184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           service_uuid.c_str(), advertise_uuids.c_str(),
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           advertise_data.c_str());
186611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
18757d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko  std::vector<std::string> advertise_uuid_tokens = base::SplitString(
18857d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko      advertise_uuids, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
189611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
190fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray  // string -> vector<UUID>
191fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray  std::vector<UUID> ids;
192611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  for (const auto& uuid_token : advertise_uuid_tokens)
193611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    ids.emplace_back(uuid_token);
194611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
195611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::string decoded_data;
196611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  base::Base64Decode(advertise_data, &decoded_data);
197aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  std::vector<uint8_t> decoded_advertise_data(decoded_data.begin(),
198aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge                                              decoded_data.end());
199aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge
200aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  base::Base64Decode(manufacturer_data, &decoded_data);
201aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  std::vector<uint8_t> decoded_manufacturer_data(decoded_data.begin(),
202aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge                                                 decoded_data.end());
203aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge
204aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  gatt_servers_[service_uuid]->SetAdvertisement(ids, decoded_advertise_data,
205aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge                                                decoded_manufacturer_data,
206611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge                                                TokenBool(transmit_name));
207611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
208611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
209611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
210e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnSetScanResponse(const std::string& service_uuid,
211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                     const std::string& scan_response_uuids,
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                     const std::string& scan_response_data,
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                     const std::string& manufacturer_data,
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                     const std::string& transmit_name) {
21557d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko  std::vector<std::string> scan_response_uuid_tokens = base::SplitString(
21657d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko      scan_response_uuids, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
217611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
218fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray  // string -> vector<UUID>
219fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray  std::vector<UUID> ids;
220611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  for (const auto& uuid_token : scan_response_uuid_tokens)
221611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    ids.emplace_back(uuid_token);
222611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
223611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::string decoded_data;
224611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  base::Base64Decode(scan_response_data, &decoded_data);
225aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  std::vector<uint8_t> decoded_advertise_data(decoded_data.begin(),
226aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge                                              decoded_data.end());
227aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge
228aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  base::Base64Decode(manufacturer_data, &decoded_data);
229aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  std::vector<uint8_t> decoded_manufacturer_data(decoded_data.begin(),
230aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge                                                 decoded_data.end());
231aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge
232aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge  gatt_servers_[service_uuid]->SetScanResponse(ids, decoded_advertise_data,
233aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge                                               decoded_manufacturer_data,
234611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge                                               TokenBool(transmit_name));
235611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
236611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
237611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
238e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnStartService(const std::string& service_uuid) {
239611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return gatt_servers_[service_uuid]->Start();
240611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
241611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
242e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnStopService(const std::string& service_uuid) {
243611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return gatt_servers_[service_uuid]->Stop();
244611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
245611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
246e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnMessage() {
247611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::string ipc_msg;
248d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov  ssize_t size;
249d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov
250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  OSI_NO_INTR(size =
251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  recv(pfds_[kFdIpc].fd, &ipc_msg[0], 0, MSG_PEEK | MSG_TRUNC));
252611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (-1 == size) {
253db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "Error reading datagram size: %s", strerror(errno));
254611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    return false;
255611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  } else if (0 == size) {
256f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    LOG_INFO(LOG_TAG, "%s:%d: Connection closed", __func__, __LINE__);
257611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    return false;
258611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
259611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
260611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  ipc_msg.resize(size);
261d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov  OSI_NO_INTR(size = read(pfds_[kFdIpc].fd, &ipc_msg[0], ipc_msg.size()));
262611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (-1 == size) {
263db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "Error reading IPC: %s", strerror(errno));
264611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    return false;
265611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  } else if (0 == size) {
266f2d6434a6b7ad98e20c7a601d2a0950237514837Arman Uguray    LOG_INFO(LOG_TAG, "%s:%d: Connection closed", __func__, __LINE__);
267611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    return false;
268611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
269611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
27057d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko  std::vector<std::string> tokens = base::SplitString(
27157d7bf98ea5f7a08c93c30f5d8a0e303d78ea432Alex Vakulenko      ipc_msg, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
272611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  switch (tokens.size()) {
273611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    case 2:
274611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      if (tokens[0] == kSetAdapterNameCommand)
275611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge        return OnSetAdapterName(tokens[1]);
276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (tokens[0] == kCreateServiceCommand) return OnCreateService(tokens[1]);
277611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      if (tokens[0] == kDestroyServiceCommand)
278611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge        return OnDestroyService(tokens[1]);
279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (tokens[0] == kStartServiceCommand) return OnStartService(tokens[1]);
280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (tokens[0] == kStopServiceCommand) return OnStopService(tokens[1]);
281611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      break;
282611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    case 4:
283611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      if (tokens[0] == kSetCharacteristicValueCommand)
284611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge        return OnSetCharacteristicValue(tokens[1], tokens[2], tokens[3]);
285611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      break;
286611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    case 5:
287611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      if (tokens[0] == kAddCharacteristicCommand)
288611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge        return OnAddCharacteristic(tokens[1], tokens[2], tokens[3], tokens[4]);
289611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      break;
290aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge    case 6:
291aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge      if (tokens[0] == kSetAdvertisementCommand)
292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return OnSetAdvertisement(tokens[1], tokens[2], tokens[3], tokens[4],
293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  tokens[5]);
294aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge      if (tokens[0] == kSetScanResponseCommand)
295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return OnSetScanResponse(tokens[1], tokens[2], tokens[3], tokens[4],
296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                 tokens[5]);
297aa9e17bc61324446b9e0199630fb772b9afb1109Ian Coolidge      break;
298611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    default:
299611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge      break;
300611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
301611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
302db554581079863974af8e1289646f5deea6fc044Marie Janssen  LOG_ERROR(LOG_TAG, "Malformed IPC message: %s", ipc_msg.c_str());
303611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return false;
304611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
305611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
306e415c050edbb2710e8807dd2602c851412953268Scott James Remnantbool LinuxIPCHost::OnGattWrite() {
307fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray  UUID::UUID128Bit id;
308d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov  ssize_t r;
309d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov
310d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov  OSI_NO_INTR(r = read(pfds_[kFdGatt].fd, id.data(), id.size()));
311611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (r != id.size()) {
312db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "Error reading GATT attribute ID");
313611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    return false;
314611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
315611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
316611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::vector<uint8_t> value;
317611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  // TODO(icoolidge): Generalize this for multiple clients.
318611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  auto server = gatt_servers_.begin();
319fe6dd2a72b0f6d761821e75b048c13eb9ecd19acArman Uguray  server->second->GetCharacteristicValue(UUID(id), &value);
320611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  const std::string value_string(value.begin(), value.end());
321611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::string encoded_value;
322611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  base::Base64Encode(value_string, &encoded_value);
323611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
324611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  std::string transmit(kWriteCharacteristicCommand);
325611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  transmit += "|" + server->first;
326611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  transmit += "|" + base::HexEncode(id.data(), id.size());
327611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  transmit += "|" + encoded_value;
328611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
329d6121a37c579731b89348e618a823c53b938449aPavlin Radoslavov  OSI_NO_INTR(r = write(pfds_[kFdIpc].fd, transmit.data(), transmit.size()));
330611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  if (-1 == r) {
331db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "Error replying to IPC: %s", strerror(errno));
332611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge    return false;
333611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  }
334611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
335611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge  return true;
336611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge}
337611fcf98316e28425abe28dbcc07b8d037653ceeIan Coolidge
338fe65fb7978bc9257a36d1e5eae59c5f412dbdb49Arman Uguray}  // namespace ipc
339