File: ApplicationManager.h

package info (click to toggle)
qtop 2.3.4-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,976 kB
  • sloc: cpp: 40,477; makefile: 7
file content (237 lines) | stat: -rw-r--r-- 6,364 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#ifndef ApplicationManager_h
#define ApplicationManager_h

/******************************************************************************
*
* Copyright (C) 2002 Hugo PEREIRA <mailto: hugo.pereira@free.fr>
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* Any WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program.  If not, see <http://www.gnu.org/licenses/>.
*
*******************************************************************************/

#include "Client.h"
#include "CommandLineArguments.h"
#include "CommandLineParser.h"
#include "Counter.h"
#include "ServerCommand.h"

#include <QBasicTimer>
#include <QHostAddress>
#include <QList>
#include <QMap>
#include <QObject>
#include <QPair>
#include <QTcpServer>
#include <QTimerEvent>

namespace Server
{

    //* ensures only one instance of an application is running
    class ApplicationManager: public QObject, private Base::Counter<ApplicationManager>
    {

        //* Qt meta object macro
        Q_OBJECT

        public:

        //* constructor
        explicit ApplicationManager( QObject* );

        //* destructor
        ~ApplicationManager() override;

        //* application name
        void setApplicationName( const QString& );

        //* commandLine parser
        static CommandLineParser commandLineParser( CommandLineArguments = CommandLineArguments(), bool ignoreWarnings = true );

        //* application state enumeration
        enum State
        {

            StateUnknown,
            AwaitingReply,
            Alive,
            Dead
        };

        //* changes application state, emit signal if changed
        bool setState( const State& state )
        {
            if( state == state_ ) return false;
            state_ = state;
            return true;
        }

        //* reference to "this" client
        Client& client() const
        { return *client_; }

        //* retrieve Application ID
        const ApplicationId& id() const
        { return id_; }

        public Q_SLOTS:

        //* (re)initialize server/client connections
        void initialize( CommandLineArguments args = CommandLineArguments() );

        Q_SIGNALS:

        //* emitted when a given command is recieved
        void commandRecieved( Server::ServerCommand );

        //* emitted when the server is (re)initialized
        void initialized();

        protected:

        //* timer event
        void timerEvent( QTimerEvent* ) override;

        //* pair of application id and client
        using ClientPair = QPair< ApplicationId, Client* >;

        //* map of clients
        using ClientMap = QMap< ApplicationId, Client* >;

        //* list of clients
        using ClientList = QList< Client* >;

        //* used to retrieve clients for a given state
        class SameStateFTor: public Client::SameStateFTor
        {
            public:

            //* constructor
            explicit SameStateFTor( QAbstractSocket::SocketState state ):
                Client::SameStateFTor( state )
            {}

            //* predicate
            bool operator() ( const ClientPair& pair ) const
            { return Client::SameStateFTor::operator() (pair.second); }

            //* predicate
            bool operator() ( const Client* client ) const
            { return Client::SameStateFTor::operator() (client); }

        };

        //* used to retrieve pair with matching client
        class SameClientFTor
        {
            public:

            //* constructor
            explicit SameClientFTor( Client* client ):
                client_( client )
                {}

            //* predicate
            bool operator() ( const ClientPair& pair ) const
            { return pair.second == client_; }

            //* predicate
            bool operator() ( Client* client ) const
            { return client == client_; }

            private:

            //* prediction
            Client* client_;
        };

        /** \brief register a client, returns true if application is new.
        if forced is set to true, the old cliend, if any, is replaced
        */
        ClientMap::iterator _register( const ApplicationId& id, Client* client, bool forced = false );

        //* redirect message
        void _redirect( ServerCommand, Client* );

        //* broadcast a message to all registered clients but the sender (if valid)
        void _broadcast( ServerCommand, Client* sender = 0 );

        protected Q_SLOTS:

        //* a new connection is granted
        void _newConnection();

        //* a connection was closed
        void _serverConnectionClosed();

        //* a connection was closed
        void _clientConnectionClosed();

        //* client recieves errors
        void _error( QAbstractSocket::SocketError );

        //* redistribute message when a connected client sends one
        void _redirect( Server::ServerCommand );

        //* reads signal from server
        void _process( Server::ServerCommand );

        //* start timeout
        void _startTimer();

        private:

        //* initialize client
        bool _initializeClient();

        //* initialize server
        bool _initializeServer();

        //* host
        QHostAddress host_;

        //* port
        int port_ = 0;

        //* arguments
        CommandLineArguments arguments_;

        //* Server
        QTcpServer* server_ = nullptr;

        //* true if initializeServer was called
        bool serverInitialized_ = false;

        //* Client
        Client* client_ = nullptr;

        //* list of connected clients
        ClientList connectedClients_;

        //* maps accepted clients and amount of request
        ClientMap acceptedClients_;

        //* application name
        ApplicationId id_;

        //* manager status
        State state_ = StateUnknown;

        //* reply timeout
        QBasicTimer timer_;

    };
};

#endif