Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
dbt_endpoint.hpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2022 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#ifndef DBT_ENDPOINT_HPP_
26#define DBT_ENDPOINT_HPP_
27
28#include <iostream>
29#include <cassert>
30#include <cinttypes>
31#include <cstring>
32
33#include <catch2/catch_amalgamated.hpp>
35
37
38using namespace direct_bt;
39
40class DBTEndpoint;
41typedef std::shared_ptr<DBTEndpoint> DBTEndpointRef;
42
44
45 public:
46 virtual ~DBTEndpoint() = default;
47
48 /**
49 * Return name of this endpoint,
50 * which becomes the adapter's name.
51 */
52 virtual std::string getName() = 0;
53
54 /**
55 * Set the server adapter for this endpoint.
56 *
57 * This is done in {@link ChangedAdapterSetListener#adapterAdded(BTAdapter)}
58 * if {@link #initAdapter(BTAdapter)} returned true.
59 *
60 * @param a the associate adapter for this endpoint.
61 */
62 virtual void setAdapter(BTAdapterRef a) = 0;
63
64 /**
65 * Return the adapter for this endpoint.
66 */
67 virtual BTAdapterRef getAdapter() = 0;
68
69 virtual void close(const std::string& msg) = 0;
70
71 virtual void setProtocolSessionsLeft(const int v) = 0;
72 virtual int getProtocolSessionsLeft() = 0;
75 virtual int getDisconnectCount() = 0;
76
77 /**
78 * Initialize the given adapter for this endpoint.
79 *
80 * The matching and successfully initialized adapter
81 * will become this endpoint's associated adapter via {@link #setAdapter(BTAdapter)},
82 * as performed in in {@link ChangedAdapterSetListener#adapterAdded(BTAdapter)}.
83 *
84 * @param adapter the potential associated adapter for this endpoint.
85 * @return true if successful and associated
86 */
87 virtual bool initAdapter(BTAdapterRef adapter) = 0;
88
89 static void checkInitializedState(const DBTEndpointRef& endp) {
90 BTAdapterRef adapter = endp->getAdapter();
91 REQUIRE( true == adapter->isInitialized() );
92 REQUIRE( true == adapter->isPowered() );
93 REQUIRE( BTRole::Master == adapter->getRole() );
94 REQUIRE( 4 <= adapter->getBTMajorVersion() );
95 }
96
97 static std::mutex mtx_cas_endpts;
98 static std::vector<DBTEndpointRef> cas_endpts;
99
100 static void myChangedAdapterSetFunc(const bool added, BTAdapterRef& adapter) {
101 if( added ) {
102 for(const DBTEndpointRef& endpt : cas_endpts ) {
103 if( nullptr == endpt->getAdapter() ) {
104 if( endpt->initAdapter( adapter ) ) {
105 endpt->setAdapter(adapter);
106 jau::fprintf_td(stderr, "****** Adapter ADDED__: InitOK: %s\n", adapter->toString().c_str());
107 return;
108 }
109 }
110 }
111 jau::fprintf_td(stderr, "****** Adapter ADDED__: Ignored: %s\n", adapter->toString().c_str());
112 } else {
113 for(const DBTEndpointRef& endpt : cas_endpts ) {
114 if( nullptr != endpt->getAdapter() && *adapter == *endpt->getAdapter() ) {
115 endpt->setAdapter(nullptr);
116 jau::fprintf_td(stderr, "****** Adapter REMOVED: %s\n", adapter->toString().c_str());
117 return;
118 }
119 }
120 jau::fprintf_td(stderr, "****** Adapter REMOVED: Ignored: %s\n", adapter->toString().c_str());
121 }
122 }
123
124 static ChangedAdapterSetCallback initChangedAdapterSetListener(const BTManagerRef& manager, std::vector<DBTEndpointRef> endpts) {
125 const std::lock_guard<std::mutex> lock(mtx_cas_endpts); // RAII-style acquire and relinquish via destructor
126 cas_endpts = std::move( endpts );
128 manager->addChangedAdapterSetCallback(casc);
129 for(const DBTEndpointRef& endpt : cas_endpts ) {
130 REQUIRE( nullptr != endpt->getAdapter() );
131 }
132 return casc;
133 }
134
135 static void startDiscovery(const BTAdapterRef& adapter, const bool current_exp_discovering_state) {
136 REQUIRE( false == adapter->isAdvertising() );
137 REQUIRE( current_exp_discovering_state == adapter->isDiscovering());
138
139 REQUIRE( HCIStatusCode::SUCCESS == adapter->startDiscovery() );
140 while( !adapter->isDiscovering() ) { // pending action
141 jau::sleep_for( 100_ms );
142 }
143 REQUIRE( false == adapter->isAdvertising() );
144 REQUIRE( true == adapter->isDiscovering() );
145 REQUIRE( BTRole::Master == adapter->getRole() );
146 }
147
148 static void stopDiscovery(const BTAdapterRef& adapter, const bool current_exp_discovering_state) {
149 REQUIRE( false == adapter->isAdvertising() );
150 REQUIRE( current_exp_discovering_state == adapter->isDiscovering() );
151 REQUIRE( BTRole::Master == adapter->getRole() );
152
153 REQUIRE( HCIStatusCode::SUCCESS == adapter->stopDiscovery() ); // pending action
154 while( adapter->isDiscovering() ) { // pending action
155 jau::sleep_for( 100_ms );
156 }
157 REQUIRE( false == adapter->isAdvertising() );
158 REQUIRE( false == adapter->isDiscovering() );
159 REQUIRE( BTRole::Master == adapter->getRole() );
160 }
161};
162
164std::vector<DBTEndpointRef> DBTEndpoint::cas_endpts;
165
166#endif /* DBT_ENDPOINT_HPP_ */
virtual std::string getName()=0
Return name of this endpoint, which becomes the adapter's name.
static void checkInitializedState(const DBTEndpointRef &endp)
virtual ~DBTEndpoint()=default
static void myChangedAdapterSetFunc(const bool added, BTAdapterRef &adapter)
virtual void setAdapter(BTAdapterRef a)=0
Set the server adapter for this endpoint.
static void stopDiscovery(const BTAdapterRef &adapter, const bool current_exp_discovering_state)
virtual int getDisconnectCount()=0
virtual void close(const std::string &msg)=0
virtual int getProtocolSessionsLeft()=0
static std::mutex mtx_cas_endpts
virtual int getProtocolSessionsDoneTotal()=0
static ChangedAdapterSetCallback initChangedAdapterSetListener(const BTManagerRef &manager, std::vector< DBTEndpointRef > endpts)
virtual void setProtocolSessionsLeft(const int v)=0
virtual int getProtocolSessionsDoneSuccess()=0
static void startDiscovery(const BTAdapterRef &adapter, const bool current_exp_discovering_state)
static std::vector< DBTEndpointRef > cas_endpts
virtual bool initAdapter(BTAdapterRef adapter)=0
Initialize the given adapter for this endpoint.
virtual BTAdapterRef getAdapter()=0
Return the adapter for this endpoint.
Class template jau::function is a general-purpose static-polymorphic function wrapper.
std::shared_ptr< DBTEndpoint > DBTEndpointRef
std::shared_ptr< BTManager > BTManagerRef
Definition: BTAdapter.hpp:61
std::shared_ptr< BTAdapter > BTAdapterRef
Definition: BTAdapter.hpp:1354
jau::function< R(A...)> bind_free(R(*func)(A...)) noexcept
Bind given non-void free-function to an anonymous function using func::free_target_t.
int fprintf_td(const uint64_t elapsed_ms, FILE *stream, const char *format,...) noexcept
Convenient fprintf() invocation, prepending the given elapsed_ms timestamp.
Definition: debug.cpp:270
bool sleep_for(const fraction_timespec &relative_time, const bool monotonic=true, const bool ignore_irq=true) noexcept
sleep_for causes the current thread to block until a specific amount of time has passed.