1 /*
2  * Copyright (c) 2020, Peter Thorson, Steve Wills. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above copyright
9  *       notice, this list of conditions and the following disclaimer in the
10  *       documentation and/or other materials provided with the distribution.
11  *     * Neither the name of the WebSocket++ Project nor the
12  *       names of its contributors may be used to endorse or promote products
13  *       derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #ifndef CHATTERINOWEBSOCKETPPLOGGER_HPP
29 #define CHATTERINOWEBSOCKETPPLOGGER_HPP
30 
31 #include <string>
32 #include <websocketpp/common/cpp11.hpp>
33 #include <websocketpp/logger/basic.hpp>
34 #include <websocketpp/logger/levels.hpp>
35 #include "common/QLogging.hpp"
36 
37 namespace websocketpp {
38 namespace log {
39 
40     template <typename concurrency, typename names>
41     class chatterinowebsocketpplogger : public basic<concurrency, names>
42     {
43     public:
44         typedef chatterinowebsocketpplogger<concurrency, names> base;
45 
46         chatterinowebsocketpplogger<concurrency, names>(
47             channel_type_hint::value)
48             : m_static_channels(0xffffffff)
49             , m_dynamic_channels(0)
50         {
51         }
52 
53         chatterinowebsocketpplogger<concurrency, names>(std::ostream *)
54             : m_static_channels(0xffffffff)
55             , m_dynamic_channels(0)
56         {
57         }
58 
59         chatterinowebsocketpplogger<concurrency, names>(
60             level c, channel_type_hint::value)
61             : m_static_channels(c)
62             , m_dynamic_channels(0)
63         {
64         }
65 
66         chatterinowebsocketpplogger<concurrency, names>(level c, std::ostream *)
67             : m_static_channels(c)
68             , m_dynamic_channels(0)
69         {
70         }
71 
72         ~chatterinowebsocketpplogger<concurrency, names>()
73         {
74         }
75 
76         chatterinowebsocketpplogger<concurrency, names>(
77             chatterinowebsocketpplogger<concurrency, names> const &other)
78             : m_static_channels(other.m_static_channels)
79             , m_dynamic_channels(other.m_dynamic_channels)
80         {
81         }
82 
83 #ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
84         chatterinowebsocketpplogger<concurrency, names> &operator=(
85             chatterinowebsocketpplogger<concurrency, names> const &) = delete;
86 #endif  // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
87 
88 #ifdef _WEBSOCKETPP_MOVE_SEMANTICS_
89         /// Move constructor
90         chatterinowebsocketpplogger<concurrency, names>(
91             chatterinowebsocketpplogger<concurrency, names> &&other)
92             : m_static_channels(other.m_static_channels)
93             , m_dynamic_channels(other.m_dynamic_channels)
94         {
95         }
96 #    ifdef _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
97         // no move assignment operator because of const member variables
98         chatterinowebsocketpplogger<concurrency, names> &operator=(
99             chatterinowebsocketpplogger<concurrency, names> &&) = delete;
100 #    endif  // _WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_
101 #endif      // _WEBSOCKETPP_MOVE_SEMANTICS_
102 
103         /// Explicitly do nothing, this logger doesn't support changing ostream
set_ostream(std::ostream *)104         void set_ostream(std::ostream *)
105         {
106         }
107 
108         /// Dynamically enable the given list of channels
109         /**
110      * @param channels The package of channels to enable
111      */
set_channels(level channels)112         void set_channels(level channels)
113         {
114             if (channels == names::none)
115             {
116                 clear_channels(names::all);
117                 return;
118             }
119 
120             scoped_lock_type lock(m_lock);
121             m_dynamic_channels |= (channels & m_static_channels);
122         }
123 
124         /// Dynamically disable the given list of channels
125         /**
126      * @param channels The package of channels to disable
127      */
clear_channels(level channels)128         void clear_channels(level channels)
129         {
130             scoped_lock_type lock(m_lock);
131             m_dynamic_channels &= ~channels;
132         }
133 
134         /// Write a string message to the given channel
135         /**
136      * @param channel The channel to write to
137      * @param msg The message to write
138      */
write(level channel,std::string const & msg)139         void write(level channel, std::string const &msg)
140         {
141             scoped_lock_type lock(m_lock);
142             if (!this->dynamic_test(channel))
143             {
144                 return;
145             }
146             qCDebug(chatterinoWebsocket).nospace()
147                 << names::channel_name(channel) << ": "
148                 << QString::fromStdString(msg);
149         }
150 
151         /// Write a cstring message to the given channel
152         /**
153      * @param channel The channel to write to
154      * @param msg The message to write
155      */
write(level channel,char const * msg)156         void write(level channel, char const *msg)
157         {
158             scoped_lock_type lock(m_lock);
159             if (!this->dynamic_test(channel))
160             {
161                 return;
162             }
163             qCDebug(chatterinoWebsocket).nospace()
164                 << names::channel_name(channel) << ": " << msg;
165         }
166 
167         /// Test whether a channel is statically enabled
168         /**
169      * @param channel The package of channels to test
170      */
171 
static_test(level channel) const172         _WEBSOCKETPP_CONSTEXPR_TOKEN_ bool static_test(level channel) const
173         {
174             return ((channel & m_static_channels) != 0);
175         }
176 
177         /// Test whether a channel is dynamically enabled
178         /**
179      * @param channel The package of channels to test
180      */
dynamic_test(level channel)181         bool dynamic_test(level channel)
182         {
183             return ((channel & m_dynamic_channels) != 0);
184         }
185 
186     protected:
187         typedef typename concurrency::scoped_lock_type scoped_lock_type;
188         typedef typename concurrency::mutex_type mutex_type;
189         mutex_type m_lock;
190 
191     private:
192         level const m_static_channels;
193         level m_dynamic_channels;
194     };
195 
196 }  // namespace log
197 }  // namespace websocketpp
198 
199 #endif  // CHATTERINOWEBSOCKETPPLOGGER_HPP
200