File indexing completed on 2025-01-05 03:53:06

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2021-07-24
0007  * Description : a MJPEG Stream server to export items on the network.
0008  *
0009  * SPDX-FileCopyrightText: 2021-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #ifndef DIGIKAM_MJPEG_SERVER_P_H
0016 #define DIGIKAM_MJPEG_SERVER_P_H
0017 
0018 // Qt includes
0019 
0020 #include <QList>
0021 #include <QStringList>
0022 #include <QFuture>
0023 #include <QMutex>
0024 #include <QTcpSocket>
0025 #include <QTcpServer>
0026 #include <QByteArray>
0027 
0028 // Local includes
0029 
0030 #include "mjpegserver.h"
0031 #include "digikam_debug.h"
0032 
0033 namespace DigikamGenericMjpegStreamPlugin
0034 {
0035 
0036 /**
0037  * MJPEG Server private container.
0038  * Internal use only.
0039  */
0040 class Q_DECL_HIDDEN MjpegServer::Private : public QObject
0041 {
0042     Q_OBJECT
0043 
0044 public:
0045 
0046     explicit Private(QObject* const parent);
0047     ~Private();
0048 
0049     /**
0050      * Handle maximum clients connected to the server.
0051      */
0052     void setMaxClients(int);
0053     int  maxClients() const;
0054 
0055     /**
0056      * Write data in native socket file descriptor.
0057      * We need to use native low level socket to write data inside
0058      * from separated threads, as QTCPSocket only work with a single thread.
0059      */
0060     int writeInSocket(int sock, const QByteArray& data) const;
0061 
0062     /**
0063      * Return an human readable description of client connected through a socket.
0064      */
0065     QString clientDescription(QTcpSocket* const client) const;
0066 
0067     /**
0068      * Return true if the server is running.
0069      */
0070     bool isOpened() const;
0071 
0072     /**
0073      * Initialize the server.
0074      */
0075     bool open(const QString& address, int port);
0076 
0077     /**
0078      * Start the server (aka listening on network).
0079      */
0080     void start();
0081 
0082     /**
0083      * Stop the server (aka not listening on network).
0084      */
0085     void stop();
0086 
0087     /**
0088      * Shutdown the server.
0089      */
0090     void close();
0091 
0092 public:
0093 
0094     QTcpServer*        server;       ///< main tcp/ip server.
0095     int                rate;         ///< stream frames rate per secs [1...30].
0096     int                delay;        ///< delay between frames in us (1E6/rate).
0097     QList<QTcpSocket*> clients;      ///< list of client connected sockets.
0098     QByteArray         lastFrame;    ///< the current JPEG frame to dispatch to all connected clients.
0099     QFuture<void>      srvTask;      ///< server threaded task used to stream on clients.
0100     QMutex             mutexClients; ///< to protect current clients list.
0101     QMutex             mutexFrame;   ///< to protect current frame data.
0102     QStringList        blackList;    ///< Clients Ip address list to ban.
0103 
0104 private Q_SLOTS:
0105 
0106     /**
0107      * Called by server when new clients arrive.
0108      */
0109     void slotNewConnection();
0110 
0111     /**
0112      * Called by server when client left the server.
0113      */
0114     void slotClientDisconnected();
0115 
0116 private:
0117 
0118     /**
0119      * Single thread method called to write data to all clients.
0120      */
0121     void writerThread();
0122 
0123     /**
0124      * This method dispatch to all clients connected to a
0125      * separated thread running on one available core automatically.
0126      * This method is called through writerThread().
0127      */
0128     void clientWriteMultithreaded(int client, const QByteArray& data);
0129 };
0130 
0131 } // namespace DigikamGenericMjpegStreamPlugin
0132 
0133 #endif // DIGIKAM_MJPEG_SERVER_P_H