blob: 312136dbe9f8a3fbba01ebd793781b80e918603c [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <map>
#include <fbl/ref_ptr.h>
#include <lib/fit/function.h>
#include "garnet/drivers/bluetooth/lib/l2cap/scoped_channel.h"
#include "garnet/drivers/bluetooth/lib/l2cap/sdu.h"
#include "garnet/drivers/bluetooth/lib/sdp/sdp.h"
#include "garnet/drivers/bluetooth/lib/sdp/service_record.h"
#include "lib/fxl/memory/weak_ptr.h"
namespace btlib {
namespace sdp {
// The SDP server object owns the Service Database and all Service Records.
// Only one server is expected to exist per host.
// This object is not thread-safe.
// TODO(jamuraa): make calls thread-safe or ensure single-threadedness
class Server final {
public:
// A new SDP server, which starts with the ServiceDiscoveryService record.
Server();
~Server() = default;
// Initialize a new SDP profile connection with |peer_id| on |channel|.
// Returns false if the channel cannot be activated.
bool AddConnection(const std::string& peer_id,
fbl::RefPtr<l2cap::Channel> channel);
// Create a new ServiceRecord for a service, allocate a new handle for it, and
// call |callback| synchronously populate it. When |callback| returns, the
// record should have all attributes added.
// The record will have a valid handle when |callback| is called.
// The ServiceRecord passed to the callback is only guaranteed to be valid
// while |callback| is run.
// Returns |false| without calling |callback| if the record couldn't be
// created.
// Returns |true| if the record has been successfully added (if the record
// remains valid).
using ConstructCallback = fit::function<void(ServiceRecord*)>;
bool RegisterService(ConstructCallback callback);
// Unregister a service from the database. Idempotent.
// Returns |true| if a record was removed.
bool UnregisterService(ServiceHandle handle);
private:
// Inserts a new record in the database with handle |handle|, returning a
// pointer to the newly constructed record.
// Returns nullptr if the record already exists.
ServiceRecord* MakeNewRecord(ServiceHandle handle);
// Returns the next unused Service Handle, or 0 if none are available.
ServiceHandle GetNextHandle();
// l2cap::channel callbacks
void OnChannelClosed(const std::string& peer_id);
void OnRxBFrame(const std::string& peer_id, const l2cap::SDU& sdu);
std::unordered_map<std::string, l2cap::ScopedChannel> channels_;
std::unordered_map<ServiceHandle, ServiceRecord> records_;
// The next available ServiceHandle.
ServiceHandle next_handle_;
// The service database state tracker.
uint32_t db_state_ __UNUSED;
fxl::WeakPtrFactory<Server> weak_ptr_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(Server);
};
} // namespace sdp
} // namespace btlib