1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8
9 #include "td/telegram/Global.h"
10 #include "td/telegram/Version.h"
11
12 #include "td/utils/buffer.h"
13 #include "td/utils/common.h"
14 #include "td/utils/format.h"
15 #include "td/utils/logging.h"
16 #include "td/utils/misc.h"
17 #include "td/utils/Slice.h"
18 #include "td/utils/Status.h"
19 #include "td/utils/StorerBase.h"
20 #include "td/utils/StringBuilder.h"
21 #include "td/utils/tl_helpers.h"
22 #include "td/utils/tl_parsers.h"
23 #include "td/utils/tl_storers.h"
24
25 namespace td {
26 namespace log_event {
27
28 template <class ParentT>
29 class WithVersion : public ParentT {
30 public:
31 using ParentT::ParentT;
set_version(int32 version)32 void set_version(int32 version) {
33 version_ = version;
34 }
version()35 int32 version() const {
36 return version_;
37 }
38
39 private:
40 int32 version_{};
41 };
42
43 template <class ParentT, class ContextT>
44 class WithContext : public ParentT {
45 public:
46 using ParentT::ParentT;
set_context(ContextT context)47 void set_context(ContextT context) {
48 context_ = context;
49 }
context()50 ContextT context() const {
51 return context_;
52 }
53
54 private:
55 ContextT context_{};
56 };
57
58 class LogEvent {
59 public:
60 LogEvent() = default;
61 LogEvent(const LogEvent &) = delete;
62 LogEvent &operator=(const LogEvent &) = delete;
63 virtual ~LogEvent() = default;
64 enum HandlerType : uint32 {
65 SecretChats = 1,
66 Users = 2,
67 Chats = 3,
68 Channels = 4,
69 SecretChatInfos = 5,
70 WebPages = 0x10,
71 SetPollAnswer = 0x20,
72 StopPoll = 0x21,
73 SendMessage = 0x100,
74 DeleteMessage = 0x101,
75 DeleteMessagesOnServer = 0x102,
76 ReadHistoryOnServer = 0x103,
77 ForwardMessages = 0x104,
78 ReadMessageContentsOnServer = 0x105,
79 SendBotStartMessage = 0x106,
80 SendScreenshotTakenNotificationMessage = 0x107,
81 SendInlineQueryResultMessage = 0x108,
82 DeleteDialogHistoryOnServer = 0x109,
83 ReadAllDialogMentionsOnServer = 0x10a,
84 DeleteAllChannelMessagesFromSenderOnServer = 0x10b,
85 ToggleDialogIsPinnedOnServer = 0x10c,
86 ReorderPinnedDialogsOnServer = 0x10d,
87 SaveDialogDraftMessageOnServer = 0x10e,
88 UpdateDialogNotificationSettingsOnServer = 0x10f,
89 UpdateScopeNotificationSettingsOnServer = 0x110,
90 ResetAllNotificationSettingsOnServer = 0x111,
91 ToggleDialogReportSpamStateOnServer = 0x112,
92 RegetDialog = 0x113,
93 ReadHistoryInSecretChat = 0x114,
94 ToggleDialogIsMarkedAsUnreadOnServer = 0x115,
95 SetDialogFolderIdOnServer = 0x116,
96 DeleteScheduledMessagesOnServer = 0x117,
97 ToggleDialogIsBlockedOnServer = 0x118,
98 ReadMessageThreadHistoryOnServer = 0x119,
99 BlockMessageSenderFromRepliesOnServer = 0x120,
100 UnpinAllDialogMessagesOnServer = 0x121,
101 DeleteAllCallMessagesOnServer = 0x122,
102 DeleteDialogMessagesByDateOnServer = 0x123,
103 GetChannelDifference = 0x140,
104 AddMessagePushNotification = 0x200,
105 EditMessagePushNotification = 0x201,
106 ConfigPmcMagic = 0x1f18,
107 BinlogPmcMagic = 0x4327
108 };
109
110 using Id = uint64;
111
log_event_id()112 Id log_event_id() const {
113 return log_event_id_;
114 }
set_log_event_id(Id log_event_id)115 void set_log_event_id(Id log_event_id) {
116 log_event_id_ = log_event_id;
117 }
118
print(StringBuilder & sb)119 virtual StringBuilder &print(StringBuilder &sb) const {
120 return sb << "[Logevent " << tag("id", log_event_id()) << "]";
121 }
122
123 private:
124 Id log_event_id_{};
125 };
126
127 inline StringBuilder &operator<<(StringBuilder &sb, const LogEvent &log_event) {
128 return log_event.print(sb);
129 }
130
131 class LogEventParser final : public WithVersion<WithContext<TlParser, Global *>> {
132 public:
LogEventParser(Slice data)133 explicit LogEventParser(Slice data) : WithVersion<WithContext<TlParser, Global *>>(data) {
134 set_version(fetch_int());
135 LOG_CHECK(version() < static_cast<int32>(Version::Next)) << "Wrong version " << version();
136 set_context(G());
137 }
138 };
139
140 class LogEventStorerCalcLength final : public WithContext<TlStorerCalcLength, Global *> {
141 public:
LogEventStorerCalcLength()142 LogEventStorerCalcLength() : WithContext<TlStorerCalcLength, Global *>() {
143 store_int(static_cast<int32>(Version::Next) - 1);
144 set_context(G());
145 }
146 };
147
148 class LogEventStorerUnsafe final : public WithContext<TlStorerUnsafe, Global *> {
149 public:
LogEventStorerUnsafe(unsigned char * buf)150 explicit LogEventStorerUnsafe(unsigned char *buf) : WithContext<TlStorerUnsafe, Global *>(buf) {
151 store_int(static_cast<int32>(Version::Next) - 1);
152 set_context(G());
153 }
154 };
155
156 template <class T>
157 class LogEventStorerImpl final : public Storer {
158 public:
LogEventStorerImpl(const T & event)159 explicit LogEventStorerImpl(const T &event) : event_(event) {
160 }
161
size()162 size_t size() const final {
163 LogEventStorerCalcLength storer;
164 td::store(event_, storer);
165 return storer.get_length();
166 }
store(uint8 * ptr)167 size_t store(uint8 *ptr) const final {
168 LogEventStorerUnsafe storer(ptr);
169 td::store(event_, storer);
170 #ifdef TD_DEBUG
171 T check_result;
172 log_event_parse(check_result, Slice(ptr, storer.get_buf())).ensure();
173 #endif
174 return static_cast<size_t>(storer.get_buf() - ptr);
175 }
176
177 private:
178 const T &event_;
179 };
180
181 } // namespace log_event
182
183 using LogEvent = log_event::LogEvent;
184 using LogEventParser = log_event::LogEventParser;
185 using LogEventStorerCalcLength = log_event::LogEventStorerCalcLength;
186 using LogEventStorerUnsafe = log_event::LogEventStorerUnsafe;
187
188 template <class T>
189 Status log_event_parse(T &data, Slice slice) TD_WARN_UNUSED_RESULT;
190
191 template <class T>
log_event_parse(T & data,Slice slice)192 Status log_event_parse(T &data, Slice slice) {
193 LogEventParser parser(slice);
194 parse(data, parser);
195 parser.fetch_end();
196 return parser.get_status();
197 }
198
199 template <class T>
log_event_store(const T & data)200 BufferSlice log_event_store(const T &data) {
201 LogEventStorerCalcLength storer_calc_length;
202 store(data, storer_calc_length);
203
204 BufferSlice value_buffer{storer_calc_length.get_length()};
205 auto ptr = value_buffer.as_slice().ubegin();
206 LOG_CHECK(is_aligned_pointer<4>(ptr)) << ptr;
207
208 LogEventStorerUnsafe storer_unsafe(ptr);
209 store(data, storer_unsafe);
210
211 #ifdef TD_DEBUG
212 T check_result;
213 log_event_parse(check_result, value_buffer.as_slice()).ensure();
214 #endif
215 return value_buffer;
216 }
217
218 template <class T>
get_log_event_storer(const T & event)219 log_event::LogEventStorerImpl<T> get_log_event_storer(const T &event) {
220 return log_event::LogEventStorerImpl<T>(event);
221 }
222
223 } // namespace td
224