1 /***
2     This file is part of snapcast
3     Copyright (C) 2014-2021  Johannes Pohl
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 ***/
18 
19 #ifndef STREAM_SERVER_HPP
20 #define STREAM_SERVER_HPP
21 
22 #include <boost/asio.hpp>
23 #include <memory>
24 #include <mutex>
25 #include <set>
26 #include <sstream>
27 #include <vector>
28 
29 #include "common/queue.h"
30 #include "common/sample_format.hpp"
31 #include "control_server.hpp"
32 #include "jsonrpcpp.hpp"
33 #include "message/codec_header.hpp"
34 #include "message/message.hpp"
35 #include "message/server_settings.hpp"
36 #include "server_settings.hpp"
37 #include "stream_session.hpp"
38 #include "streamreader/stream_manager.hpp"
39 
40 using namespace streamreader;
41 
42 using boost::asio::ip::tcp;
43 using acceptor_ptr = std::unique_ptr<tcp::acceptor>;
44 using session_ptr = std::shared_ptr<StreamSession>;
45 
46 
47 /// Forwars PCM data to the connected clients
48 /**
49  * Reads PCM data using PipeStream, implements PcmListener to get the (encoded) PCM stream.
50  * Accepts and holds client connections (StreamSession)
51  * Receives (via the StreamMessageReceiver interface) and answers messages from the clients
52  * Forwards PCM data to the clients
53  */
54 class StreamServer : public StreamMessageReceiver
55 {
56 public:
57     StreamServer(boost::asio::io_context& io_context, const ServerSettings& serverSettings, StreamMessageReceiver* messageReceiver = nullptr);
58     virtual ~StreamServer();
59 
60     void start();
61     void stop();
62 
63     /// Send a message to all connceted clients
64     //	void send(const msg::BaseMessage* message);
65 
66     void addSession(const std::shared_ptr<StreamSession>& session);
67     void onMetaChanged(const PcmStream* pcmStream, std::shared_ptr<msg::StreamTags> meta);
68     void onChunkEncoded(const PcmStream* pcmStream, bool isDefaultStream, std::shared_ptr<msg::PcmChunk> chunk, double duration);
69 
70     session_ptr getStreamSession(const std::string& clientId) const;
71     session_ptr getStreamSession(StreamSession* session) const;
72 
73 private:
74     void startAccept();
75     void handleAccept(tcp::socket socket);
76     void cleanup();
77 
78     /// Implementation of StreamMessageReceiver
79     void onMessageReceived(StreamSession* streamSession, const msg::BaseMessage& baseMessage, char* buffer) override;
80     void onDisconnect(StreamSession* streamSession) override;
81 
82     mutable std::recursive_mutex sessionsMutex_;
83     mutable std::recursive_mutex clientMutex_;
84     std::vector<std::weak_ptr<StreamSession>> sessions_;
85     boost::asio::io_context& io_context_;
86     std::vector<acceptor_ptr> acceptor_;
87     boost::asio::steady_timer config_timer_;
88 
89     ServerSettings settings_;
90     Queue<std::shared_ptr<msg::BaseMessage>> messages_;
91     StreamMessageReceiver* messageReceiver_;
92 };
93 
94 
95 
96 #endif
97