1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtBluetooth module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include "chatserver.h"
52
53#include <QtBluetooth/qbluetoothserver.h>
54#include <QtBluetooth/qbluetoothsocket.h>
55
56//! [Service UUID]
57static const QLatin1String serviceUuid("e8e10f95-1a70-4b27-9ccf-02010264e9c8");
58//! [Service UUID]
59
60ChatServer::ChatServer(QObject *parent)
61 : QObject(parent)
62{
63}
64
65ChatServer::~ChatServer()
66{
67 stopServer();
68}
69
70void ChatServer::startServer(const QBluetoothAddress& localAdapter)
71{
72 if (rfcommServer)
73 return;
74
75 //! [Create the server]
76 rfcommServer = new QBluetoothServer(QBluetoothServiceInfo::RfcommProtocol, this);
77 connect(sender: rfcommServer, signal: &QBluetoothServer::newConnection,
78 receiver: this, slot: QOverload<>::of(ptr: &ChatServer::clientConnected));
79 bool result = rfcommServer->listen(address: localAdapter);
80 if (!result) {
81 qWarning() << "Cannot bind chat server to" << localAdapter.toString();
82 return;
83 }
84 //! [Create the server]
85
86 //serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceRecordHandle, (uint)0x00010010);
87
88 QBluetoothServiceInfo::Sequence profileSequence;
89 QBluetoothServiceInfo::Sequence classId;
90 classId << QVariant::fromValue(value: QBluetoothUuid(QBluetoothUuid::SerialPort));
91 classId << QVariant::fromValue(value: quint16(0x100));
92 profileSequence.append(t: QVariant::fromValue(value: classId));
93 serviceInfo.setAttribute(attributeId: QBluetoothServiceInfo::BluetoothProfileDescriptorList,
94 value: profileSequence);
95
96 classId.clear();
97 classId << QVariant::fromValue(value: QBluetoothUuid(serviceUuid));
98 classId << QVariant::fromValue(value: QBluetoothUuid(QBluetoothUuid::SerialPort));
99
100 serviceInfo.setAttribute(attributeId: QBluetoothServiceInfo::ServiceClassIds, value: classId);
101
102 //! [Service name, description and provider]
103 serviceInfo.setAttribute(attributeId: QBluetoothServiceInfo::ServiceName, value: tr(s: "Bt Chat Server"));
104 serviceInfo.setAttribute(attributeId: QBluetoothServiceInfo::ServiceDescription,
105 value: tr(s: "Example bluetooth chat server"));
106 serviceInfo.setAttribute(attributeId: QBluetoothServiceInfo::ServiceProvider, value: tr(s: "qt-project.org"));
107 //! [Service name, description and provider]
108
109 //! [Service UUID set]
110 serviceInfo.setServiceUuid(QBluetoothUuid(serviceUuid));
111 //! [Service UUID set]
112
113 //! [Service Discoverability]
114 QBluetoothServiceInfo::Sequence publicBrowse;
115 publicBrowse << QVariant::fromValue(value: QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
116 serviceInfo.setAttribute(attributeId: QBluetoothServiceInfo::BrowseGroupList,
117 value: publicBrowse);
118 //! [Service Discoverability]
119
120 //! [Protocol descriptor list]
121 QBluetoothServiceInfo::Sequence protocolDescriptorList;
122 QBluetoothServiceInfo::Sequence protocol;
123 protocol << QVariant::fromValue(value: QBluetoothUuid(QBluetoothUuid::L2cap));
124 protocolDescriptorList.append(t: QVariant::fromValue(value: protocol));
125 protocol.clear();
126 protocol << QVariant::fromValue(value: QBluetoothUuid(QBluetoothUuid::Rfcomm))
127 << QVariant::fromValue(value: quint8(rfcommServer->serverPort()));
128 protocolDescriptorList.append(t: QVariant::fromValue(value: protocol));
129 serviceInfo.setAttribute(attributeId: QBluetoothServiceInfo::ProtocolDescriptorList,
130 value: protocolDescriptorList);
131 //! [Protocol descriptor list]
132
133 //! [Register service]
134 serviceInfo.registerService(localAdapter);
135 //! [Register service]
136}
137
138//! [stopServer]
139void ChatServer::stopServer()
140{
141 // Unregister service
142 serviceInfo.unregisterService();
143
144 // Close sockets
145 qDeleteAll(c: clientSockets);
146
147 // Close server
148 delete rfcommServer;
149 rfcommServer = nullptr;
150}
151//! [stopServer]
152
153//! [sendMessage]
154void ChatServer::sendMessage(const QString &message)
155{
156 QByteArray text = message.toUtf8() + '\n';
157
158 for (QBluetoothSocket *socket : qAsConst(t&: clientSockets))
159 socket->write(data: text);
160}
161//! [sendMessage]
162
163//! [clientConnected]
164void ChatServer::clientConnected()
165{
166 QBluetoothSocket *socket = rfcommServer->nextPendingConnection();
167 if (!socket)
168 return;
169
170 connect(sender: socket, signal: &QBluetoothSocket::readyRead, receiver: this, slot: &ChatServer::readSocket);
171 connect(sender: socket, signal: &QBluetoothSocket::disconnected, receiver: this, slot: QOverload<>::of(ptr: &ChatServer::clientDisconnected));
172 clientSockets.append(t: socket);
173 emit clientConnected(name: socket->peerName());
174}
175//! [clientConnected]
176
177//! [clientDisconnected]
178void ChatServer::clientDisconnected()
179{
180 QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(object: sender());
181 if (!socket)
182 return;
183
184 emit clientDisconnected(name: socket->peerName());
185
186 clientSockets.removeOne(t: socket);
187
188 socket->deleteLater();
189}
190//! [clientDisconnected]
191
192//! [readSocket]
193void ChatServer::readSocket()
194{
195 QBluetoothSocket *socket = qobject_cast<QBluetoothSocket *>(object: sender());
196 if (!socket)
197 return;
198
199 while (socket->canReadLine()) {
200 QByteArray line = socket->readLine().trimmed();
201 emit messageReceived(sender: socket->peerName(),
202 message: QString::fromUtf8(str: line.constData(), size: line.length()));
203 }
204}
205//! [readSocket]
206

source code of qtconnectivity/examples/bluetooth/btchat/chatserver.cpp