File indexing completed on 2024-05-12 04:58:51

0001 /**
0002  * SPDX-FileCopyrightText: 2019 Matthijs Tijink <matthijstijink@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #ifndef CONNECTIONMULTIPLEXER_H
0008 #define CONNECTIONMULTIPLEXER_H
0009 
0010 #include <QByteArray>
0011 #include <QHash>
0012 #include <QObject>
0013 #include <QSharedPointer>
0014 #include <memory>
0015 
0016 class QBluetoothUuid;
0017 class MultiplexChannel;
0018 class MultiplexChannelState;
0019 class QBluetoothSocket;
0020 
0021 /**
0022  * An utility class to split a single (bluetooth) connection to multiple independent channels.
0023  * By default (and without needing any communication with the other endpoint), a single default channel is open.
0024  *
0025  * Destroying/closing this object will automatically close all channels.
0026  */
0027 class ConnectionMultiplexer : public QObject
0028 {
0029     Q_OBJECT
0030 public:
0031     ConnectionMultiplexer(QBluetoothSocket *socket, QObject *parent = nullptr);
0032     ~ConnectionMultiplexer();
0033 
0034     /**
0035      * Open a new channel within this connection.
0036      *
0037      * @return The uuid to refer to this channel.
0038      * @see getChannel()
0039      */
0040     QBluetoothUuid newChannel();
0041     /**
0042      * Get the channel device for the specified channel uuid.
0043      * If the channel does not exist, this will return a null pointer.
0044      *
0045      * A channel is guaranteed to exist until the first call to get it.
0046      * @param channelId The channel uuid
0047      * @return A shared pointer to the channel object
0048      * @see getDefaultChannel()
0049      */
0050     std::unique_ptr<MultiplexChannel> getChannel(QBluetoothUuid channelId);
0051     /**
0052      * Get the default channel.
0053      *
0054      * @see getChannel()
0055      */
0056     std::unique_ptr<MultiplexChannel> getDefaultChannel();
0057 
0058     /**
0059      * Close all channels and the underlying connection.
0060      */
0061     void close();
0062 
0063     /**
0064      * Check if the underlying connection is still open.
0065      * @return True if the connection is open
0066      * @see close()
0067      */
0068     bool isOpen() const;
0069 
0070 private:
0071     /**
0072      * The underlying connection
0073      */
0074     QBluetoothSocket *mSocket;
0075     /**
0076      * The buffer of to-be-written bytes
0077      */
0078     QByteArray to_write_bytes;
0079     /**
0080      * The channels not requested by the user yet
0081      */
0082     QHash<QBluetoothUuid, MultiplexChannel *> unrequested_channels;
0083     /**
0084      * All channels currently open
0085      */
0086     QHash<QBluetoothUuid, QSharedPointer<MultiplexChannelState>> channels;
0087     /**
0088      * True once the other side has sent its protocol version
0089      */
0090     bool receivedProtocolVersion;
0091 
0092     /**
0093      * Slot for connection reading
0094      */
0095     void readyRead();
0096     /**
0097      * Slot for disconnection
0098      */
0099     void disconnected();
0100     /**
0101      * Slot for progress in writing data/new data available to be written
0102      */
0103     void bytesWritten();
0104     /**
0105      * Tries to parse a single connection message.
0106      *
0107      * @return True if a message was parsed successfully.
0108      */
0109     bool tryParseMessage();
0110     /**
0111      * Add a new channel. Assumes that the communication about this channel is done
0112      * (i.e. the other endpoint also knows this channel exists).
0113      *
0114      * @param new_id The channel uuid
0115      */
0116     void addChannel(QBluetoothUuid new_id);
0117 
0118     /**
0119      * Slot for closing a channel
0120      */
0121     void closeChannel(QBluetoothUuid channelId);
0122     /**
0123      * Slot for writing a channel's data to the other endpoint
0124      */
0125     void channelCanWrite(QBluetoothUuid channelId);
0126     /**
0127      * Slot for indicating that a channel can receive more data
0128      */
0129     void channelCanRead(QBluetoothUuid channelId);
0130     /**
0131      * Slot for removing a channel from tracking
0132      */
0133     void removeChannel(QBluetoothUuid channelId);
0134 };
0135 
0136 #endif