Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qbluetoothserver_winrt.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qbluetoothserver.h"
6#include "qbluetoothsocket.h"
10
11#include <QtCore/QLoggingCategory>
12#include <QtCore/private/qfunctions_winrt_p.h>
13
14#include <windows.networking.h>
15#include <windows.networking.connectivity.h>
16#include <windows.networking.sockets.h>
17
18using namespace Microsoft::WRL;
19using namespace Microsoft::WRL::Wrappers;
20using namespace ABI::Windows::Devices;
21using namespace ABI::Windows::Devices::Enumeration;
22using namespace ABI::Windows::Foundation;
23using namespace ABI::Windows::Networking;
24using namespace ABI::Windows::Networking::Sockets;
25using namespace ABI::Windows::Networking::Connectivity;
26
27typedef ITypedEventHandler<StreamSocketListener *, StreamSocketListenerConnectionReceivedEventArgs *> ClientConnectedHandler;
28
30
31Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS)
32
34
36 QBluetoothServer *parent)
37 : serverType(sType), q_ptr(parent)
38{
39 mainThreadCoInit(this);
40}
41
43{
44 deactivateActiveListening();
45 __fakeServerPorts.remove(this);
46 // If we do not reset that pointer, socketListener will go out of scope after CoUninitialize was
47 // called, which will lead to a crash.
48 socketListener = nullptr;
50}
51
52bool QBluetoothServerPrivate::isListening() const
53{
54 return __fakeServerPorts.contains(const_cast<QBluetoothServerPrivate *>(this));
55}
56
57bool QBluetoothServerPrivate::initiateActiveListening(const QString &serviceName)
58{
59 HStringReference serviceNameRef(reinterpret_cast<LPCWSTR>(serviceName.utf16()));
60
61 ComPtr<IAsyncAction> bindAction;
62 HRESULT hr = socketListener->BindServiceNameAsync(serviceNameRef.Get(), &bindAction);
63 Q_ASSERT_SUCCEEDED(hr);
64 hr = QWinRTFunctions::await(bindAction);
65 Q_ASSERT_SUCCEEDED(hr);
66 return true;
67}
68
69bool QBluetoothServerPrivate::deactivateActiveListening()
70{
71 if (!isListening())
72 return true;
73
74 HRESULT hr;
75 hr = socketListener->remove_ConnectionReceived(connectionToken);
76 Q_ASSERT_SUCCEEDED(hr);
77 return true;
78}
79
80HRESULT QBluetoothServerPrivate::handleClientConnection(IStreamSocketListener *listener,
81 IStreamSocketListenerConnectionReceivedEventArgs *args)
82{
84 if (!socketListener || socketListener.Get() != listener) {
85 qCDebug(QT_BT_WINDOWS) << "Accepting connection from wrong listener. We should not be here.";
86 Q_UNREACHABLE();
87 return S_OK;
88 }
89
90 HRESULT hr;
91 ComPtr<IStreamSocket> socket;
92 hr = args->get_Socket(&socket);
93 Q_ASSERT_SUCCEEDED(hr);
94 QMutexLocker locker(&pendingConnectionsMutex);
95 if (pendingConnections.size() < maxPendingConnections) {
96 qCDebug(QT_BT_WINDOWS) << "Accepting connection";
97 pendingConnections.append(socket);
98 locker.unlock();
99 q->newConnection();
100 } else {
101 qCDebug(QT_BT_WINDOWS) << "Refusing connection";
102 }
103
104 return S_OK;
105}
106
108{
109 Q_D(QBluetoothServer);
110
111 d->deactivateActiveListening();
112 __fakeServerPorts.remove(d);
113}
114
116{
118 Q_D(QBluetoothServer);
120 d->m_lastError = UnsupportedProtocolError;
121 emit errorOccurred(d->m_lastError);
122 return false;
123 }
124
125 if (isListening())
126 return false;
127
128 HRESULT hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(),
129 &d->socketListener);
130 Q_ASSERT_SUCCEEDED(hr);
131 hr = d->socketListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QBluetoothServerPrivate::handleClientConnection).Get(),
132 &d->connectionToken);
133 Q_ASSERT_SUCCEEDED(hr);
134
135 //We can not register an actual Rfcomm port, because the platform does not allow it
136 //but we need a way to associate a server with a service
137 if (port == 0) { //Try to assign a non taken port id
138 for (int i = 1; ; i++){
139 if (__fakeServerPorts.key(i) == 0) {
140 port = i;
141 break;
142 }
143 }
144 }
145
146 if (__fakeServerPorts.key(port) == 0) {
148
149 qCDebug(QT_BT_WINDOWS) << "Port" << port << "registered";
150 } else {
151 qCWarning(QT_BT_WINDOWS) << "server with port" << port << "already registered or port invalid";
152 d->m_lastError = ServiceAlreadyRegisteredError;
153 emit errorOccurred(d->m_lastError);
154 return false;
155 }
156
157 return true;
158}
159
160void QBluetoothServer::setMaxPendingConnections(int numConnections)
161{
162 Q_D(QBluetoothServer);
163 QMutexLocker locker(&d->pendingConnectionsMutex);
164 if (d->pendingConnections.size() > numConnections) {
165 qCWarning(QT_BT_WINDOWS) << "There are currently more than" << numConnections << "connections"
166 << "pending. Number of maximum pending connections was not changed.";
167 return;
168 }
169
170 d->maxPendingConnections = numConnections;
171}
172
174{
175 Q_D(const QBluetoothServer);
176 QMutexLocker locker(&d->pendingConnectionsMutex);
177 return !d->pendingConnections.isEmpty();
178}
179
181{
182 Q_D(QBluetoothServer);
183 if (d->pendingConnections.isEmpty())
184 return nullptr;
185
186 ComPtr<IStreamSocket> socket = d->pendingConnections.takeFirst();
187
188 QBluetoothSocket *newSocket = new QBluetoothSocket();
189 bool success = newSocket->d_ptr->setSocketDescriptor(socket, d->serverType);
190 if (!success) {
191 delete newSocket;
192 newSocket = nullptr;
193 }
194
195 return newSocket;
196}
197
199{
200 QList<QBluetoothHostInfo> hosts = QBluetoothLocalDevice::allDevices();
201
202 if (hosts.isEmpty())
203 return QBluetoothAddress();
204 else
205 return hosts.at(0).address();
206}
207
209{
210 //We return the fake port
211 Q_D(const QBluetoothServer);
213}
214
215void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security)
216{
217 Q_UNUSED(security);
218}
219
220QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const
221{
223}
224
\inmodule QtBluetooth
static QList< QBluetoothHostInfo > allDevices()
Returns a list of all available local Bluetooth devices.
QBluetoothSocket * socket
\inmodule QtBluetooth
bool hasPendingConnections() const
Returns true if a connection is pending, otherwise false.
void setSecurityFlags(QBluetooth::SecurityFlags security)
Sets the Bluetooth security flags to security.
bool isListening() const
Returns true if the server is listening for incoming connections, otherwise false.
QBluetoothSocket * nextPendingConnection()
Returns a pointer to the QBluetoothSocket for the next pending connection.
bool listen(const QBluetoothAddress &address=QBluetoothAddress(), quint16 port=0)
Start listening for incoming connections to address on port.
void close()
Closes and resets the listening socket.
void errorOccurred(QBluetoothServer::Error error)
This signal is emitted when an error occurs.
quint16 serverPort() const
Returns the server port number.
QBluetoothAddress serverAddress() const
Returns the server address.
QBluetooth::SecurityFlags securityFlags() const
Returns the Bluetooth security flags.
void setMaxPendingConnections(int numConnections)
Sets the maximum number of pending connections to numConnections.
QBluetoothServiceInfo::Protocol serverType() const
Returns the type of the QBluetoothServer.
\inmodule QtBluetooth
virtual bool setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType, QBluetoothSocket::SocketState socketState=QBluetoothSocket::SocketState::ConnectedState, QBluetoothSocket::OpenMode openMode=QBluetoothSocket::ReadWrite)=0
\inmodule QtBluetooth
QBluetoothSocketBasePrivate * d_ptr
\inmodule QtCore
Definition qhash.h:820
\inmodule QtCore
Definition qmutex.h:313
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6995
Combined button and popup list for selecting options.
QT_BEGIN_NAMESPACE QHash< QBluetoothServerPrivate *, int > __fakeServerPorts
ITypedEventHandler< StreamSocketListener *, StreamSocketListenerConnectionReceivedEventArgs * > ClientConnectedHandler
QT_BEGIN_NAMESPACE QHash< QBluetoothServerPrivate *, int > __fakeServerPorts
void mainThreadCoInit(void *caller)
void mainThreadCoUninit(void *caller)
EGLOutputPortEXT port
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define emit
#define Q_UNUSED(x)
unsigned short quint16
Definition qtypes.h:48
long HRESULT
QTcpSocket * socket
[1]
QJSValueList args