File: control_requests.hpp

package info (click to toggle)
snapcast 0.34.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,252 kB
  • sloc: cpp: 40,067; python: 3,260; sh: 455; makefile: 16
file content (474 lines) | stat: -rw-r--r-- 13,785 bytes parent folder | download
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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
/***
    This file is part of snapcast
    Copyright (C) 2014-2025  Johannes Pohl

    This program 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 3 of the License, or
    (at your option) any later version.

    This program 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/>.
***/

#pragma once


// local headers
#include "authinfo.hpp"
#include "config.hpp"
#include "jsonrpcpp.hpp"
#include "stream_server.hpp"
#include "streamreader/stream_manager.hpp"

// 3rd party headers

// standard headers
#include <functional>
#include <string>
#include <vector>

class Server;

/// Base class of a Snapserver control request
class Request
{
public:
    /// Description of the request
    struct Description
    {
        /// Type of a value or parameter
        enum class Type
        {
            string,  ///< string
            number,  ///< integer
            boolean, ///< bool
            array,   ///< array
            object,  ///< json object
            null,    ///< null
        };

        /// @return the string representation of @p type
        std::string toString(Type type)
        {
            switch (type)
            {
                case Type::string:
                    return "string";
                case Type::number:
                    return "number";
                case Type::boolean:
                    return "boolean";
                case Type::array:
                    return "array";
                case Type::object:
                    return "object";
                case Type::null:
                default:
                    return "null";
            }
        };

        /// An RPC parameter
        struct Parameter
        {
            std::string name;        ///< param name
            Type type;               ///< param type (string, number, bool, array, object)
            std::string description; ///< param description
        };

        /// The RPC command's resilt
        struct Result
        {
            Type type = Type::null;  ///< result type (string, number, bool, array, object)
            std::string description; ///< result description
        };

        /// c'tor
        // NOLINTNEXTLINE
        Description(std::string description, std::vector<Parameter> parameters = {}, Result result = {Type::null, ""})
            : description(std::move(description)), parameters(std::move(parameters)), result(std::move(result))
        {
        }

        /// Description
        std::string description;
        /// Parameters
        std::vector<Parameter> parameters;
        /// Return value
        Result result;

        /// @return description as json
        Json toJson()
        {
            Json jres;
            jres["description"] = description;
            if (result.type != Type::null)
                jres["return"] = {toString(result.type), result.description};
            if (!parameters.empty())
            {
                Json jparams = Json::array();
                for (const auto& parameter : parameters)
                {
                    Json jparam;
                    jparam["parameter"] = parameter.name;
                    jparam["description"] = parameter.description;
                    jparam["type"] = toString(parameter.type);
                    jparams.push_back(std::move(jparam));
                }
                jres["parameters"] = jparams;
            }
            return jres;
        }
    };

    // TODO: revise handler names
    /// Response handler for json control requests, returning a @p response and/or a @p notification broadcast
    using OnResponse = std::function<void(jsonrpcpp::entity_ptr response, jsonrpcpp::notification_ptr notification)>;

    /// No default c'tor
    Request() = delete;

    /// c'tor
    explicit Request(const Server& server, std::string method);

    /// d'tor
    virtual ~Request() = default;

    /// Execute the Request
    virtual void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) = 0;

    /// @return description
    virtual Description description() const = 0;

    /// @return true if the user has the permission for the request
    virtual bool hasPermission(const AuthInfo& authinfo) const;

    /// @return user needs to be authenticated
    virtual bool requiresAuthentication() const;
    /// @return user needs authorization
    virtual bool requiresAuthorization() const;

    /// @return the name of the method
    const std::string& method() const;

protected:
    /// @return the server's stream server
    const StreamServer& getStreamServer() const;
    /// @return the server's stream manager
    StreamManager& getStreamManager() const;
    /// @return server settings
    const ServerSettings& getSettings() const;

private:
    /// the server
    const Server& server_;
    /// the command
    std::string method_;
    /// the ressource
    std::string ressource_;
};


/// Control request factory
class ControlRequestFactory
{
public:
    /// c'tor
    explicit ControlRequestFactory(const Server& server);
    /// @return Request instance to handle @p method
    std::shared_ptr<Request> getRequest(const std::string& method) const;

private:
    /// storage for all available requests
    std::map<std::string, std::shared_ptr<Request>> request_map_;
};



/// Base for "Client." requests
class ClientRequest : public Request
{
public:
    /// c'tor
    ClientRequest(const Server& server, const std::string& method);

protected:
    /// update the client that is referenced in the @p request
    void updateClient(const jsonrpcpp::request_ptr& request);

    /// @return the client referenced in the request
    static ClientInfoPtr getClient(const jsonrpcpp::request_ptr& request);
};


/// Base for "Client.GetStatus" requests
class ClientGetStatusRequest : public ClientRequest
{
public:
    /// c'tor
    explicit ClientGetStatusRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// Base for "Client.SetVolume" requests
class ClientSetVolumeRequest : public ClientRequest
{
public:
    /// c'tor
    explicit ClientSetVolumeRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// Base for "Client.SetLatency" requests
class ClientSetLatencyRequest : public ClientRequest
{
public:
    /// c'tor
    explicit ClientSetLatencyRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// Base for "Client.SetName" requests
class ClientSetNameRequest : public ClientRequest
{
public:
    /// c'tor
    explicit ClientSetNameRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};



/// Base for "Group." requests
class GroupRequest : public Request
{
public:
    /// c'tor
    GroupRequest(const Server& server, const std::string& method);

protected:
    /// @return the group referenced in the request
    static GroupPtr getGroup(const jsonrpcpp::request_ptr& request);
};


/// "Group.GetStatus" request
class GroupGetStatusRequest : public GroupRequest
{
public:
    /// c'tor
    explicit GroupGetStatusRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Group.SetName" request
class GroupSetNameRequest : public GroupRequest
{
public:
    /// c'tor
    explicit GroupSetNameRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Group.SetMute" request
class GroupSetMuteRequest : public GroupRequest
{
public:
    /// c'tor
    explicit GroupSetMuteRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Group.SetStream" request
class GroupSetStreamRequest : public GroupRequest
{
public:
    /// c'tor
    explicit GroupSetStreamRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Group.SetClients" request
class GroupSetClientsRequest : public GroupRequest
{
public:
    /// c'tor
    explicit GroupSetClientsRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};



/// Base for "Stream." requests
class StreamRequest : public Request
{
public:
    /// c'tor
    StreamRequest(const Server& server, const std::string& method);

protected:
    /// @return the stream referenced in the request
    static PcmStreamPtr getStream(const StreamManager& stream_manager, const jsonrpcpp::request_ptr& request);
    /// @return the stream id referenced in the request
    static std::string getStreamId(const jsonrpcpp::request_ptr& request);
};


/// "Stream.Control" request
class StreamControlRequest : public StreamRequest
{
public:
    /// c'tor
    explicit StreamControlRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Stream.SetProperty" request
class StreamSetPropertyRequest : public StreamRequest
{
public:
    /// c'tor
    explicit StreamSetPropertyRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Stream.AddStream" request
class StreamAddRequest : public StreamRequest
{
public:
    /// c'tor
    explicit StreamAddRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Stream.RemoveStream" request
class StreamRemoveRequest : public StreamRequest
{
public:
    /// c'tor
    explicit StreamRemoveRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};



/// "Server.GetRPCVersion" request
class ServerGetRpcVersionRequest : public Request
{
public:
    /// c'tor
    explicit ServerGetRpcVersionRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Server.GetStatus" request
class ServerGetStatusRequest : public Request
{
public:
    /// c'tor
    explicit ServerGetStatusRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Server.DeleteClient" request
class ServerDeleteClientRequest : public Request
{
public:
    /// c'tor
    explicit ServerDeleteClientRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;
};


/// "Server.Authenticate" request
class ServerAuthenticateRequest : public Request
{
public:
    /// c'tor
    explicit ServerAuthenticateRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;

    bool requiresAuthentication() const override
    {
        return false;
    }

    bool requiresAuthorization() const override
    {
        return false;
    }
};


#if 0
/// "Server.GetToken" request
class ServerGetTokenRequest : public Request
{
public:
    /// c'tor
    explicit ServerGetTokenRequest(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
};
#endif


/// "General.GetRpcCommands" request
class GeneralGetRpcCommands : public Request
{
public:
    /// c'tor
    explicit GeneralGetRpcCommands(const Server& server);
    void execute(const jsonrpcpp::request_ptr& request, AuthInfo& authinfo, const OnResponse& on_response) override;
    Description description() const override;

    /// Set available @p requests
    void setCommands(std::vector<std::shared_ptr<Request>> requests);

    bool requiresAuthentication() const override
    {
        return true;
    }

    bool requiresAuthorization() const override
    {
        return false;
    }

private:
    std::vector<std::shared_ptr<Request>> requests_;
};