1 /*
2 
3 Copyright (c) 2003-2018, Arvid Norberg, Daniel Wallin
4 All rights reserved.
5 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9 
10     * Redistributions of source code must retain the above copyright
11       notice, this list of conditions and the following disclaimer.
12     * Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in
14       the documentation and/or other materials provided with the distribution.
15     * Neither the name of the author nor the names of its
16       contributors may be used to endorse or promote products derived
17       from this software without specific prior written permission.
18 
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
30 
31 */
32 
33 #include <string>
34 #include <cstdio> // for snprintf
35 #include <cinttypes> // for PRId64 et.al.
36 
37 #include "libtorrent/config.hpp"
38 #include "libtorrent/alert.hpp"
39 #include "libtorrent/alert_types.hpp"
40 #include "libtorrent/socket_io.hpp"
41 #include "libtorrent/error_code.hpp"
42 #include "libtorrent/torrent.hpp"
43 #include "libtorrent/performance_counters.hpp"
44 #include "libtorrent/stack_allocator.hpp"
45 #include "libtorrent/piece_block.hpp"
46 #include "libtorrent/hex.hpp" // to_hex
47 #include "libtorrent/session_stats.hpp"
48 
49 #if TORRENT_ABI_VERSION == 1
50 #include "libtorrent/write_resume_data.hpp"
51 #endif
52 
53 #include "libtorrent/aux_/escape_string.hpp" // for convert_from_native
54 
55 namespace libtorrent {
56 
57 	constexpr alert_category_t alert::error_notification;
58 	constexpr alert_category_t alert::peer_notification;
59 	constexpr alert_category_t alert::port_mapping_notification;
60 	constexpr alert_category_t alert::storage_notification;
61 	constexpr alert_category_t alert::tracker_notification;
62 	constexpr alert_category_t alert::connect_notification;
63 	constexpr alert_category_t alert::status_notification;
64 #if TORRENT_ABI_VERSION == 1
65 	constexpr alert_category_t alert::debug_notification;
66 	constexpr alert_category_t alert::progress_notification;
67 #endif
68 	constexpr alert_category_t alert::ip_block_notification;
69 	constexpr alert_category_t alert::performance_warning;
70 	constexpr alert_category_t alert::dht_notification;
71 	constexpr alert_category_t alert::stats_notification;
72 	constexpr alert_category_t alert::session_log_notification;
73 	constexpr alert_category_t alert::torrent_log_notification;
74 	constexpr alert_category_t alert::peer_log_notification;
75 	constexpr alert_category_t alert::incoming_request_notification;
76 	constexpr alert_category_t alert::dht_log_notification;
77 	constexpr alert_category_t alert::dht_operation_notification;
78 	constexpr alert_category_t alert::port_mapping_log_notification;
79 	constexpr alert_category_t alert::picker_log_notification;
80 	constexpr alert_category_t alert::file_progress_notification;
81 	constexpr alert_category_t alert::piece_progress_notification;
82 	constexpr alert_category_t alert::upload_notification;
83 	constexpr alert_category_t alert::block_progress_notification;
84 
85 	constexpr alert_category_t alert::all_categories;
86 #if TORRENT_ABI_VERSION == 1
87 	constexpr alert_category_t alert::rss_notification;
88 #endif
89 
alert()90 	alert::alert() : m_timestamp(clock_type::now()) {}
91 	alert::~alert() = default;
timestamp() const92 	time_point alert::timestamp() const { return m_timestamp; }
93 
torrent_alert(aux::stack_allocator & alloc,torrent_handle const & h)94 	torrent_alert::torrent_alert(aux::stack_allocator& alloc
95 		, torrent_handle const& h)
96 		: handle(h)
97 		, m_alloc(alloc)
98 	{
99 		std::shared_ptr<torrent> t = h.native_handle();
100 		if (t)
101 		{
102 			std::string name_str = t->name();
103 			if (!name_str.empty())
104 			{
105 				m_name_idx = alloc.copy_string(name_str);
106 			}
107 			else
108 			{
109 				m_name_idx = alloc.copy_string(aux::to_hex(t->info_hash()));
110 			}
111 		}
112 		else
113 		{
114 			m_name_idx = alloc.copy_string("");
115 		}
116 
117 #if TORRENT_ABI_VERSION == 1
118 		name = m_alloc.get().ptr(m_name_idx);
119 #endif
120 	}
121 
torrent_name() const122 	char const* torrent_alert::torrent_name() const
123 	{
124 		return m_alloc.get().ptr(m_name_idx);
125 	}
126 
message() const127 	std::string torrent_alert::message() const
128 	{
129 #ifdef TORRENT_DISABLE_ALERT_MSG
130 		return {};
131 #else
132 		if (!handle.is_valid()) return " - ";
133 		return torrent_name();
134 #endif
135 	}
136 
peer_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & i,peer_id const & pi)137 	peer_alert::peer_alert(aux::stack_allocator& alloc
138 		, torrent_handle const& h
139 		, tcp::endpoint const& i
140 		, peer_id const& pi)
141 		: torrent_alert(alloc, h)
142 		, endpoint(i)
143 		, pid(pi)
144 #if TORRENT_ABI_VERSION == 1
145 		, ip(i)
146 #endif
147 	{}
148 
message() const149 	std::string peer_alert::message() const
150 	{
151 #ifdef TORRENT_DISABLE_ALERT_MSG
152 		return {};
153 #else
154 		return torrent_alert::message() + " peer [ " + print_endpoint(endpoint)
155 			+ " client: " + aux::identify_client_impl(pid) + " ]";
156 #endif
157 	}
158 
tracker_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,string_view u)159 	tracker_alert::tracker_alert(aux::stack_allocator& alloc
160 		, torrent_handle const& h, tcp::endpoint const& ep, string_view u)
161 		: torrent_alert(alloc, h)
162 		, local_endpoint(ep)
163 		, m_url_idx(alloc.copy_string(u))
164 #if TORRENT_ABI_VERSION == 1
165 		, url(u)
166 #endif
167 	{}
168 
tracker_url() const169 	char const* tracker_alert::tracker_url() const
170 	{
171 		return m_alloc.get().ptr(m_url_idx);
172 	}
173 
message() const174 	std::string tracker_alert::message() const
175 	{
176 #ifdef TORRENT_DISABLE_ALERT_MSG
177 		return {};
178 #else
179 		return torrent_alert::message() + " (" + tracker_url() + ")"
180 			+ "[" + print_endpoint(local_endpoint) + "]";
181 #endif
182 	}
183 
read_piece_alert(aux::stack_allocator & alloc,torrent_handle const & h,piece_index_t p,boost::shared_array<char> d,int s)184 	read_piece_alert::read_piece_alert(aux::stack_allocator& alloc
185 		, torrent_handle const& h
186 		, piece_index_t p, boost::shared_array<char> d, int s)
187 		: torrent_alert(alloc, h)
188 		, buffer(std::move(d))
189 		, piece(p)
190 		, size(s)
191 	{}
192 
read_piece_alert(aux::stack_allocator & alloc,torrent_handle h,piece_index_t p,error_code e)193 	read_piece_alert::read_piece_alert(aux::stack_allocator& alloc
194 		, torrent_handle h, piece_index_t p, error_code e)
195 		: torrent_alert(alloc, h)
196 		, error(e)
197 		, piece(p)
198 		, size(0)
199 #if TORRENT_ABI_VERSION == 1
200 		, ec(e)
201 #endif
202 	{}
203 
message() const204 	std::string read_piece_alert::message() const
205 	{
206 #ifdef TORRENT_DISABLE_ALERT_MSG
207 		return {};
208 #else
209 		char msg[200];
210 		if (error)
211 		{
212 			std::snprintf(msg, sizeof(msg), "%s: read_piece %d failed: %s"
213 				, torrent_alert::message().c_str() , static_cast<int>(piece)
214 				, convert_from_native(error.message()).c_str());
215 		}
216 		else
217 		{
218 			std::snprintf(msg, sizeof(msg), "%s: read_piece %d successful"
219 				, torrent_alert::message().c_str() , static_cast<int>(piece));
220 		}
221 		return msg;
222 #endif
223 	}
224 
file_completed_alert(aux::stack_allocator & alloc,torrent_handle const & h,file_index_t idx)225 	file_completed_alert::file_completed_alert(aux::stack_allocator& alloc
226 		, torrent_handle const& h
227 		, file_index_t idx)
228 		: torrent_alert(alloc, h)
229 		, index(idx)
230 	{}
231 
message() const232 	std::string file_completed_alert::message() const
233 	{
234 #ifdef TORRENT_DISABLE_ALERT_MSG
235 		return {};
236 #else
237 		std::string ret { torrent_alert::message() };
238 		char msg[200];
239 		std::snprintf(msg, sizeof(msg), ": file %d finished downloading"
240 			, static_cast<int>(index));
241 		ret.append(msg);
242 		return ret;
243 #endif
244 	}
245 
file_renamed_alert(aux::stack_allocator & alloc,torrent_handle const & h,string_view n,file_index_t const idx)246 	file_renamed_alert::file_renamed_alert(aux::stack_allocator& alloc
247 		, torrent_handle const& h, string_view n, file_index_t const idx)
248 		: torrent_alert(alloc, h)
249 		, index(idx)
250 		, m_name_idx(alloc.copy_string(n))
251 #if TORRENT_ABI_VERSION == 1
252 		, name(n)
253 #endif
254 	{}
255 
new_name() const256 	char const* file_renamed_alert::new_name() const
257 	{
258 		return m_alloc.get().ptr(m_name_idx);
259 	}
260 
message() const261 	std::string file_renamed_alert::message() const
262 	{
263 #ifdef TORRENT_DISABLE_ALERT_MSG
264 		return {};
265 #else
266 		std::string ret { torrent_alert::message() };
267 		char msg[200];
268 		std::snprintf(msg, sizeof(msg), ": file %d renamed to "
269 			, static_cast<int>(index));
270 		ret.append(msg);
271 		ret.append(new_name());
272 		return ret;
273 #endif
274 	}
275 
file_rename_failed_alert(aux::stack_allocator & alloc,torrent_handle const & h,file_index_t const idx,error_code ec)276 	file_rename_failed_alert::file_rename_failed_alert(aux::stack_allocator& alloc
277 		, torrent_handle const& h
278 		, file_index_t const idx
279 		, error_code ec)
280 		: torrent_alert(alloc, h)
281 		, index(idx)
282 		, error(ec)
283 	{}
284 
message() const285 	std::string file_rename_failed_alert::message() const
286 	{
287 #ifdef TORRENT_DISABLE_ALERT_MSG
288 		return {};
289 #else
290 		std::string ret { torrent_alert::message() };
291 		char msg[200];
292 		std::snprintf(msg, sizeof(msg), ": failed to rename file %d: "
293 			, static_cast<int>(index));
294 		ret.append(msg);
295 		ret.append(convert_from_native(error.message()));
296 		return ret;
297 #endif
298 	}
299 
performance_alert(aux::stack_allocator & alloc,torrent_handle const & h,performance_warning_t w)300 	performance_alert::performance_alert(aux::stack_allocator& alloc
301 		, torrent_handle const& h
302 		, performance_warning_t w)
303 		: torrent_alert(alloc, h)
304 		, warning_code(w)
305 	{}
306 
performance_warning_str(performance_alert::performance_warning_t i)307 	char const* performance_warning_str(performance_alert::performance_warning_t i)
308 	{
309 #ifdef TORRENT_DISABLE_ALERT_MSG
310 		TORRENT_UNUSED(i);
311 		return "";
312 #else
313 		static char const* const warning_str[] =
314 		{
315 			"max outstanding disk writes reached",
316 			"max outstanding piece requests reached",
317 			"upload limit too low (download rate will suffer)",
318 			"download limit too low (upload rate will suffer)",
319 			"send buffer watermark too low (upload rate will suffer)",
320 			"too many optimistic unchoke slots",
321 			"the disk queue limit is too high compared to the cache size. The disk queue eats into the cache size",
322 			"outstanding AIO operations limit reached",
323 			"using bittyrant unchoker with no upload rate limit set",
324 			"too few ports allowed for outgoing connections",
325 			"too few file descriptors are allowed for this process. connection limit lowered"
326 		};
327 
328 		TORRENT_ASSERT(i >= 0);
329 		TORRENT_ASSERT(i < std::end(warning_str) - std::begin(warning_str));
330 		return warning_str[i];
331 #endif
332 	}
333 
message() const334 	std::string performance_alert::message() const
335 	{
336 		return torrent_alert::message() + ": performance warning: "
337 			+ performance_warning_str(warning_code);
338 	}
339 
state_changed_alert(aux::stack_allocator & alloc,torrent_handle const & h,torrent_status::state_t st,torrent_status::state_t prev_st)340 	state_changed_alert::state_changed_alert(aux::stack_allocator& alloc
341 		, torrent_handle const& h
342 		, torrent_status::state_t st
343 		, torrent_status::state_t prev_st)
344 		: torrent_alert(alloc, h)
345 		, state(st)
346 		, prev_state(prev_st)
347 	{}
348 
message() const349 	std::string state_changed_alert::message() const
350 	{
351 #ifdef TORRENT_DISABLE_ALERT_MSG
352 		return {};
353 #else
354 		static char const* const state_str[] =
355 			{"checking (q)", "checking", "dl metadata"
356 			, "downloading", "finished", "seeding", "allocating"
357 			, "checking (r)"};
358 
359 		return torrent_alert::message() + ": state changed to: "
360 			+ state_str[state];
361 #endif
362 	}
363 
tracker_error_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,int times,string_view u,error_code const & e,string_view m)364 	tracker_error_alert::tracker_error_alert(aux::stack_allocator& alloc
365 		, torrent_handle const& h, tcp::endpoint const& ep, int times
366 		, string_view u, error_code const& e, string_view m)
367 		: tracker_alert(alloc, h, ep, u)
368 		, times_in_row(times)
369 		, error(e)
370 		, m_msg_idx(alloc.copy_string(m))
371 #if TORRENT_ABI_VERSION == 1
372 		, status_code(e && e.category() == http_category() ? e.value() : -1)
373 		, msg(m)
374 #endif
375 	{
376 		TORRENT_ASSERT(!u.empty());
377 	}
378 
error_message() const379 	char const* tracker_error_alert::error_message() const
380 	{
381 		return m_alloc.get().ptr(m_msg_idx);
382 	}
383 
message() const384 	std::string tracker_error_alert::message() const
385 	{
386 #ifdef TORRENT_DISABLE_ALERT_MSG
387 		return {};
388 #else
389 		char ret[400];
390 		std::snprintf(ret, sizeof(ret), "%s %s \"%s\" (%d)"
391 			, tracker_alert::message().c_str()
392 			, convert_from_native(error.message()).c_str(), error_message()
393 			, times_in_row);
394 		return ret;
395 #endif
396 	}
397 
tracker_warning_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,string_view u,string_view m)398 	tracker_warning_alert::tracker_warning_alert(aux::stack_allocator& alloc
399 		, torrent_handle const& h, tcp::endpoint const& ep
400 		, string_view u, string_view m)
401 		: tracker_alert(alloc, h, ep, u)
402 		, m_msg_idx(alloc.copy_string(m))
403 #if TORRENT_ABI_VERSION == 1
404 		, msg(m)
405 #endif
406 	{
407 		TORRENT_ASSERT(!u.empty());
408 	}
409 
warning_message() const410 	char const* tracker_warning_alert::warning_message() const
411 	{
412 		return m_alloc.get().ptr(m_msg_idx);
413 	}
414 
message() const415 	std::string tracker_warning_alert::message() const
416 	{
417 #ifdef TORRENT_DISABLE_ALERT_MSG
418 		return {};
419 #else
420 		return tracker_alert::message() + " warning: " + warning_message();
421 #endif
422 	}
423 
scrape_reply_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,int incomp,int comp,string_view u)424 	scrape_reply_alert::scrape_reply_alert(aux::stack_allocator& alloc
425 		, torrent_handle const& h, tcp::endpoint const& ep
426 		, int incomp, int comp, string_view u)
427 		: tracker_alert(alloc, h, ep, u)
428 		, incomplete(incomp)
429 		, complete(comp)
430 	{
431 		TORRENT_ASSERT(!u.empty());
432 	}
433 
message() const434 	std::string scrape_reply_alert::message() const
435 	{
436 #ifdef TORRENT_DISABLE_ALERT_MSG
437 		return {};
438 #else
439 		char ret[400];
440 		std::snprintf(ret, sizeof(ret), "%s scrape reply: %d %d"
441 			, tracker_alert::message().c_str(), incomplete, complete);
442 		return ret;
443 #endif
444 	}
445 
scrape_failed_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,string_view u,error_code const & e)446 	scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc
447 		, torrent_handle const& h, tcp::endpoint const& ep
448 		, string_view u, error_code const& e)
449 		: tracker_alert(alloc, h, ep, u)
450 		, error(e)
451 		, m_msg_idx()
452 #if TORRENT_ABI_VERSION == 1
453 		, msg(convert_from_native(e.message()))
454 #endif
455 	{
456 		TORRENT_ASSERT(!u.empty());
457 	}
458 
scrape_failed_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,string_view u,string_view m)459 	scrape_failed_alert::scrape_failed_alert(aux::stack_allocator& alloc
460 		, torrent_handle const& h, tcp::endpoint const& ep
461 		, string_view u, string_view m)
462 		: tracker_alert(alloc, h, ep, u)
463 		, error(errors::tracker_failure)
464 		, m_msg_idx(alloc.copy_string(m))
465 #if TORRENT_ABI_VERSION == 1
466 		, msg(m)
467 #endif
468 	{
469 		TORRENT_ASSERT(!u.empty());
470 	}
471 
error_message() const472 	char const* scrape_failed_alert::error_message() const
473 	{
474 		if (m_msg_idx == aux::allocation_slot()) return "";
475 		else return m_alloc.get().ptr(m_msg_idx);
476 	}
477 
message() const478 	std::string scrape_failed_alert::message() const
479 	{
480 #ifdef TORRENT_DISABLE_ALERT_MSG
481 		return {};
482 #else
483 		return tracker_alert::message() + " scrape failed: " + error_message();
484 #endif
485 	}
486 
tracker_reply_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,int np,string_view u)487 	tracker_reply_alert::tracker_reply_alert(aux::stack_allocator& alloc
488 		, torrent_handle const& h, tcp::endpoint const& ep
489 		, int np, string_view u)
490 		: tracker_alert(alloc, h, ep, u)
491 		, num_peers(np)
492 	{
493 		TORRENT_ASSERT(!u.empty());
494 	}
495 
message() const496 	std::string tracker_reply_alert::message() const
497 	{
498 #ifdef TORRENT_DISABLE_ALERT_MSG
499 		return {};
500 #else
501 		char ret[400];
502 		std::snprintf(ret, sizeof(ret), "%s received peers: %d"
503 			, tracker_alert::message().c_str(), num_peers);
504 		return ret;
505 #endif
506 	}
507 
dht_reply_alert(aux::stack_allocator & alloc,torrent_handle const & h,int np)508 	dht_reply_alert::dht_reply_alert(aux::stack_allocator& alloc
509 		, torrent_handle const& h
510 		, int np)
511 		: tracker_alert(alloc, h, {}, "")
512 		, num_peers(np)
513 	{}
514 
message() const515 	std::string dht_reply_alert::message() const
516 	{
517 #ifdef TORRENT_DISABLE_ALERT_MSG
518 		return {};
519 #else
520 		char ret[400];
521 		std::snprintf(ret, sizeof(ret), "%s received DHT peers: %d"
522 			, tracker_alert::message().c_str(), num_peers);
523 		return ret;
524 #endif
525 	}
526 
tracker_announce_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,string_view u,int e)527 	tracker_announce_alert::tracker_announce_alert(aux::stack_allocator& alloc
528 		, torrent_handle const& h, tcp::endpoint const& ep, string_view u, int e)
529 		: tracker_alert(alloc, h, ep, u)
530 		, event(e)
531 	{
532 		TORRENT_ASSERT(!u.empty());
533 	}
534 
message() const535 	std::string tracker_announce_alert::message() const
536 	{
537 #ifdef TORRENT_DISABLE_ALERT_MSG
538 		return {};
539 #else
540 		static const char* const event_str[] = {"none", "completed", "started", "stopped", "paused"};
541 		TORRENT_ASSERT_VAL(event < int(sizeof(event_str) / sizeof(event_str[0])), event);
542 		return tracker_alert::message() + " sending announce (" + event_str[event] + ")";
543 #endif
544 	}
545 
hash_failed_alert(aux::stack_allocator & alloc,torrent_handle const & h,piece_index_t index)546 	hash_failed_alert::hash_failed_alert(
547 		aux::stack_allocator& alloc
548 		, torrent_handle const& h
549 		, piece_index_t index)
550 		: torrent_alert(alloc, h)
551 		, piece_index(index)
552 	{
553 		TORRENT_ASSERT(index >= piece_index_t(0));
554 	}
555 
message() const556 	std::string hash_failed_alert::message() const
557 	{
558 #ifdef TORRENT_DISABLE_ALERT_MSG
559 		return {};
560 #else
561 		char ret[400];
562 		std::snprintf(ret, sizeof(ret), "%s hash for piece %d failed"
563 			, torrent_alert::message().c_str(), static_cast<int>(piece_index));
564 		return ret;
565 #endif
566 	}
567 
peer_ban_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id)568 	peer_ban_alert::peer_ban_alert(aux::stack_allocator& alloc
569 		, torrent_handle h, tcp::endpoint const& ep
570 		, peer_id const& peer_id)
571 		: peer_alert(alloc, h, ep, peer_id)
572 	{}
573 
message() const574 	std::string peer_ban_alert::message() const
575 	{
576 #ifdef TORRENT_DISABLE_ALERT_MSG
577 		return {};
578 #else
579 		return peer_alert::message() + " banned peer";
580 #endif
581 	}
582 
peer_unsnubbed_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id)583 	peer_unsnubbed_alert::peer_unsnubbed_alert(aux::stack_allocator& alloc
584 		, torrent_handle h, tcp::endpoint const& ep
585 		, peer_id const& peer_id)
586 		: peer_alert(alloc, h, ep, peer_id)
587 	{}
588 
message() const589 	std::string peer_unsnubbed_alert::message() const
590 	{
591 #ifdef TORRENT_DISABLE_ALERT_MSG
592 		return {};
593 #else
594 		return peer_alert::message() + " peer unsnubbed";
595 #endif
596 	}
597 
peer_snubbed_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id)598 	peer_snubbed_alert::peer_snubbed_alert(aux::stack_allocator& alloc
599 		, torrent_handle h, tcp::endpoint const& ep
600 		, peer_id const& peer_id)
601 		: peer_alert(alloc, h, ep, peer_id)
602 	{}
603 
message() const604 	std::string peer_snubbed_alert::message() const
605 	{
606 #ifdef TORRENT_DISABLE_ALERT_MSG
607 		return {};
608 #else
609 		return peer_alert::message() + " peer snubbed";
610 #endif
611 	}
612 
invalid_request_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,peer_id const & peer_id,peer_request const & r,bool _have,bool _peer_interested,bool _withheld)613 	invalid_request_alert::invalid_request_alert(aux::stack_allocator& alloc
614 		, torrent_handle const& h, tcp::endpoint const& ep
615 		, peer_id const& peer_id, peer_request const& r
616 		, bool _have, bool _peer_interested, bool _withheld)
617 		: peer_alert(alloc, h, ep, peer_id)
618 		, request(r)
619 		, we_have(_have)
620 		, peer_interested(_peer_interested)
621 		, withheld(_withheld)
622 	{}
623 
message() const624 	std::string invalid_request_alert::message() const
625 	{
626 #ifdef TORRENT_DISABLE_ALERT_MSG
627 		return {};
628 #else
629 		char ret[400];
630 		std::snprintf(ret, sizeof(ret), "%s peer sent an invalid piece request "
631 			"(piece: %d start: %d len: %d)%s"
632 			, peer_alert::message().c_str()
633 			, static_cast<int>(request.piece)
634 			, request.start
635 			, request.length
636 			, withheld ? ": super seeding withheld piece"
637 			: !we_have ? ": we don't have piece"
638 			: !peer_interested ? ": peer is not interested"
639 			: "");
640 		return ret;
641 #endif
642 	}
643 
torrent_finished_alert(aux::stack_allocator & alloc,torrent_handle h)644 	torrent_finished_alert::torrent_finished_alert(aux::stack_allocator& alloc
645 		, torrent_handle h)
646 		: torrent_alert(alloc, h)
647 	{}
648 
message() const649 	std::string torrent_finished_alert::message() const
650 	{
651 #ifdef TORRENT_DISABLE_ALERT_MSG
652 		return {};
653 #else
654 		return torrent_alert::message() + " torrent finished downloading";
655 #endif
656 	}
657 
piece_finished_alert(aux::stack_allocator & alloc,torrent_handle const & h,piece_index_t piece_num)658 	piece_finished_alert::piece_finished_alert(aux::stack_allocator& alloc
659 		, torrent_handle const& h, piece_index_t piece_num)
660 		: torrent_alert(alloc, h)
661 		, piece_index(piece_num)
662 	{}
663 
message() const664 	std::string piece_finished_alert::message() const
665 	{
666 #ifdef TORRENT_DISABLE_ALERT_MSG
667 		return {};
668 #else
669 		char ret[200];
670 		std::snprintf(ret, sizeof(ret), "%s piece: %d finished downloading"
671 			, torrent_alert::message().c_str(), static_cast<int>(piece_index));
672 		return ret;
673 #endif
674 	}
675 
request_dropped_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id,int block_num,piece_index_t piece_num)676 	request_dropped_alert::request_dropped_alert(aux::stack_allocator& alloc, torrent_handle h
677 		, tcp::endpoint const& ep, peer_id const& peer_id, int block_num
678 		, piece_index_t piece_num)
679 		: peer_alert(alloc, h, ep, peer_id)
680 		, block_index(block_num)
681 		, piece_index(piece_num)
682 	{
683 		TORRENT_ASSERT(block_index >= 0 && piece_index >= piece_index_t(0));
684 	}
685 
message() const686 	std::string request_dropped_alert::message() const
687 	{
688 #ifdef TORRENT_DISABLE_ALERT_MSG
689 		return {};
690 #else
691 		char ret[200];
692 		std::snprintf(ret, sizeof(ret), "%s peer dropped block ( piece: %d block: %d)"
693 			, peer_alert::message().c_str(), static_cast<int>(piece_index), block_index);
694 		return ret;
695 #endif
696 	}
697 
block_timeout_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id,int block_num,piece_index_t piece_num)698 	block_timeout_alert::block_timeout_alert(aux::stack_allocator& alloc, torrent_handle h
699 		, tcp::endpoint const& ep, peer_id const& peer_id, int block_num
700 		, piece_index_t piece_num)
701 		: peer_alert(alloc, h, ep, peer_id)
702 		, block_index(block_num)
703 		, piece_index(piece_num)
704 	{
705 		TORRENT_ASSERT(block_index >= 0 && piece_index >= piece_index_t(0));
706 	}
707 
message() const708 	std::string block_timeout_alert::message() const
709 	{
710 #ifdef TORRENT_DISABLE_ALERT_MSG
711 		return {};
712 #else
713 		char ret[200];
714 		std::snprintf(ret, sizeof(ret), "%s peer timed out request ( piece: %d block: %d)"
715 			, peer_alert::message().c_str(), static_cast<int>(piece_index), block_index);
716 		return ret;
717 #endif
718 	}
719 
block_finished_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id,int block_num,piece_index_t piece_num)720 	block_finished_alert::block_finished_alert(aux::stack_allocator& alloc, torrent_handle h
721 		, tcp::endpoint const& ep, peer_id const& peer_id, int block_num
722 		, piece_index_t piece_num)
723 		: peer_alert(alloc, h, ep, peer_id)
724 		, block_index(block_num)
725 		, piece_index(piece_num)
726 	{
727 		TORRENT_ASSERT(block_index >= 0 && piece_index >= piece_index_t(0));
728 	}
729 
message() const730 	std::string block_finished_alert::message() const
731 	{
732 #ifdef TORRENT_DISABLE_ALERT_MSG
733 		return {};
734 #else
735 		char ret[200];
736 		std::snprintf(ret, sizeof(ret), "%s block finished downloading (piece: %d block: %d)"
737 			, peer_alert::message().c_str(), static_cast<int>(piece_index), block_index);
738 		return ret;
739 #endif
740 	}
741 
block_downloading_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id,int block_num,piece_index_t piece_num)742 	block_downloading_alert::block_downloading_alert(aux::stack_allocator& alloc, torrent_handle h
743 		, tcp::endpoint const& ep
744 		, peer_id const& peer_id, int block_num, piece_index_t piece_num)
745 		: peer_alert(alloc, h, ep, peer_id)
746 		, block_index(block_num)
747 		, piece_index(piece_num)
748 #if TORRENT_ABI_VERSION == 1
749 		, peer_speedmsg("")
750 #endif
751 	{
752 		TORRENT_ASSERT(block_index >= 0 && piece_index >= piece_index_t(0));
753 	}
754 
message() const755 	std::string block_downloading_alert::message() const
756 	{
757 #ifdef TORRENT_DISABLE_ALERT_MSG
758 		return {};
759 #else
760 		char ret[200];
761 		std::snprintf(ret, sizeof(ret), "%s requested block (piece: %d block: %d)"
762 			, peer_alert::message().c_str(), static_cast<int>(piece_index), block_index);
763 		return ret;
764 #endif
765 	}
766 
unwanted_block_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id,int block_num,piece_index_t piece_num)767 	unwanted_block_alert::unwanted_block_alert(aux::stack_allocator& alloc, torrent_handle h
768 		, tcp::endpoint const& ep
769 		, peer_id const& peer_id, int block_num, piece_index_t piece_num)
770 		: peer_alert(alloc, h, ep, peer_id)
771 		, block_index(block_num)
772 		, piece_index(piece_num)
773 	{
774 		TORRENT_ASSERT(block_index >= 0 && piece_index >= piece_index_t(0));
775 	}
776 
message() const777 	std::string unwanted_block_alert::message() const
778 	{
779 #ifdef TORRENT_DISABLE_ALERT_MSG
780 		return {};
781 #else
782 		char ret[200];
783 		std::snprintf(ret, sizeof(ret), "%s received block not in download queue (piece: %d block: %d)"
784 			, peer_alert::message().c_str(), static_cast<int>(piece_index), block_index);
785 		return ret;
786 #endif
787 	}
788 
storage_moved_alert(aux::stack_allocator & alloc,torrent_handle const & h,string_view p)789 	storage_moved_alert::storage_moved_alert(aux::stack_allocator& alloc
790 		, torrent_handle const& h, string_view p)
791 		: torrent_alert(alloc, h)
792 		, m_path_idx(alloc.copy_string(p))
793 #if TORRENT_ABI_VERSION == 1
794 		, path(p)
795 #endif
796 	{}
797 
message() const798 	std::string storage_moved_alert::message() const
799 	{
800 #ifdef TORRENT_DISABLE_ALERT_MSG
801 		return {};
802 #else
803 		return torrent_alert::message() + " moved storage to: "
804 			+ storage_path();
805 #endif
806 	}
807 
storage_path() const808 	char const* storage_moved_alert::storage_path() const
809 	{
810 		return m_alloc.get().ptr(m_path_idx);
811 	}
812 
storage_moved_failed_alert(aux::stack_allocator & alloc,torrent_handle const & h,error_code const & e,string_view f,operation_t const op_)813 	storage_moved_failed_alert::storage_moved_failed_alert(
814 		aux::stack_allocator& alloc, torrent_handle const& h, error_code const& e
815 		, string_view f, operation_t const op_)
816 		: torrent_alert(alloc, h)
817 		, error(e)
818 		, op(op_)
819 		, m_file_idx(alloc.copy_string(f))
820 #if TORRENT_ABI_VERSION == 1
821 		, operation(operation_name(op_))
822 		, file(f)
823 #endif
824 	{}
825 
file_path() const826 	char const* storage_moved_failed_alert::file_path() const
827 	{
828 		return m_alloc.get().ptr(m_file_idx);
829 	}
830 
message() const831 	std::string storage_moved_failed_alert::message() const
832 	{
833 #ifdef TORRENT_DISABLE_ALERT_MSG
834 		return {};
835 #else
836 		return torrent_alert::message() + " storage move failed. "
837 			+ operation_name(op) + " (" + file_path() + "): "
838 			+ convert_from_native(error.message());
839 #endif
840 	}
841 
torrent_deleted_alert(aux::stack_allocator & alloc,torrent_handle const & h,sha1_hash const & ih)842 	torrent_deleted_alert::torrent_deleted_alert(aux::stack_allocator& alloc
843 		, torrent_handle const& h, sha1_hash const& ih)
844 		: torrent_alert(alloc, h)
845 		, info_hash(ih)
846 	{}
847 
message() const848 	std::string torrent_deleted_alert::message() const
849 	{
850 #ifdef TORRENT_DISABLE_ALERT_MSG
851 		return {};
852 #else
853 		return torrent_alert::message() + " deleted";
854 #endif
855 	}
856 
torrent_delete_failed_alert(aux::stack_allocator & alloc,torrent_handle const & h,error_code const & e,sha1_hash const & ih)857 	torrent_delete_failed_alert::torrent_delete_failed_alert(aux::stack_allocator& alloc
858 		, torrent_handle const& h, error_code const& e, sha1_hash const& ih)
859 		: torrent_alert(alloc, h)
860 		, error(e)
861 		, info_hash(ih)
862 #if TORRENT_ABI_VERSION == 1
863 		, msg(convert_from_native(error.message()))
864 #endif
865 	{
866 	}
867 
message() const868 	std::string torrent_delete_failed_alert::message() const
869 	{
870 #ifdef TORRENT_DISABLE_ALERT_MSG
871 		return {};
872 #else
873 		return torrent_alert::message() + " torrent deletion failed: "
874 			+ convert_from_native(error.message());
875 #endif
876 	}
877 
save_resume_data_alert(aux::stack_allocator & alloc,add_torrent_params && p,torrent_handle const & h)878 	save_resume_data_alert::save_resume_data_alert(aux::stack_allocator& alloc
879 		, add_torrent_params&& p
880 		, torrent_handle const& h)
881 		: torrent_alert(alloc, h)
882 		, params(std::move(p))
883 #if TORRENT_ABI_VERSION == 1
884 		, resume_data(std::make_shared<entry>(write_resume_data(params)))
885 #endif
886 	{
887 	}
888 
message() const889 	std::string save_resume_data_alert::message() const
890 	{
891 #ifdef TORRENT_DISABLE_ALERT_MSG
892 		return {};
893 #else
894 		return torrent_alert::message() + " resume data generated";
895 #endif
896 	}
897 
save_resume_data_failed_alert(aux::stack_allocator & alloc,torrent_handle const & h,error_code const & e)898 	save_resume_data_failed_alert::save_resume_data_failed_alert(aux::stack_allocator& alloc
899 		, torrent_handle const& h, error_code const& e)
900 		: torrent_alert(alloc, h)
901 		, error(e)
902 #if TORRENT_ABI_VERSION == 1
903 		, msg(convert_from_native(error.message()))
904 #endif
905 	{
906 	}
907 
message() const908 	std::string save_resume_data_failed_alert::message() const
909 	{
910 #ifdef TORRENT_DISABLE_ALERT_MSG
911 		return {};
912 #else
913 		return torrent_alert::message() + " resume data was not generated: "
914 			+ convert_from_native(error.message());
915 #endif
916 	}
917 
torrent_paused_alert(aux::stack_allocator & alloc,torrent_handle const & h)918 	torrent_paused_alert::torrent_paused_alert(aux::stack_allocator& alloc
919 		, torrent_handle const& h)
920 		: torrent_alert(alloc, h)
921 	{}
922 
message() const923 	std::string torrent_paused_alert::message() const
924 	{
925 #ifdef TORRENT_DISABLE_ALERT_MSG
926 		return {};
927 #else
928 		return torrent_alert::message() + " paused";
929 #endif
930 	}
931 
torrent_resumed_alert(aux::stack_allocator & alloc,torrent_handle const & h)932 	torrent_resumed_alert::torrent_resumed_alert(aux::stack_allocator& alloc
933 		, torrent_handle const& h)
934 		: torrent_alert(alloc, h)
935 	{}
936 
message() const937 	std::string torrent_resumed_alert::message() const
938 	{
939 #ifdef TORRENT_DISABLE_ALERT_MSG
940 		return {};
941 #else
942 		return torrent_alert::message() + " resumed";
943 #endif
944 	}
945 
torrent_checked_alert(aux::stack_allocator & alloc,torrent_handle const & h)946 	torrent_checked_alert::torrent_checked_alert(aux::stack_allocator& alloc
947 		, torrent_handle const& h)
948 		: torrent_alert(alloc, h)
949 	{}
950 
message() const951 	std::string torrent_checked_alert::message() const
952 	{
953 #ifdef TORRENT_DISABLE_ALERT_MSG
954 		return {};
955 #else
956 		return torrent_alert::message() + " checked";
957 #endif
958 	}
959 
960 namespace {
961 
sock_type_idx(socket_type_t type)962 	int sock_type_idx(socket_type_t type)
963 	{
964 		int idx =
965 			static_cast<std::underlying_type<socket_type_t>::type>(type);
966 		TORRENT_ASSERT(0 <= idx && idx < 6);
967 		return idx;
968 	}
969 
970 #ifndef TORRENT_DISABLE_ALERT_MSG
sock_type_str(socket_type_t type)971 	char const* sock_type_str(socket_type_t type)
972 	{
973 		static char const* const type_str[] =
974 			{ "TCP", "TCP/SSL", "UDP", "I2P", "Socks5", "uTP/SSL" };
975 
976 		return type_str[sock_type_idx(type)];
977 	}
978 
979 	char const* const nat_type_str[] = {"NAT-PMP", "UPnP"};
980 
981 	char const* const protocol_str[] = {"none", "TCP", "UDP"};
982 
983 	char const* const socket_type_str[] = {
984 		"null",
985 		"TCP",
986 		"Socks5/TCP",
987 		"HTTP",
988 		"uTP",
989 		"i2p",
990 		"SSL/TCP",
991 		"SSL/Socks5",
992 		"HTTPS",
993 		"SSL/uTP"
994 	};
995 #endif
996 
997 #if TORRENT_ABI_VERSION == 1
998 
to_op_t(operation_t op)999 	int to_op_t(operation_t op)
1000 	{
1001 		using o = operation_t;
1002 		using lfo = listen_failed_alert::op_t;
1003 
1004 		// we have to use deprecated enum values here. suppress the warnings
1005 #ifdef _MSC_VER
1006 #pragma warning(push, 1)
1007 // warning C4996: X: was declared deprecated
1008 #pragma warning( disable : 4996 )
1009 #endif
1010 #ifdef __GNUC__
1011 #pragma GCC diagnostic push
1012 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1013 #endif
1014 		switch (op)
1015 		{
1016 			case o::bittorrent: return -1;
1017 			case o::iocontrol: return -1;
1018 			case o::getpeername: return -1;
1019 			case o::getname: return lfo::get_socket_name;
1020 			case o::alloc_recvbuf: return -1;
1021 			case o::alloc_sndbuf: return -1;
1022 			case o::file_write: return -1;
1023 			case o::file_read: return -1;
1024 			case o::file: return -1;
1025 			case o::sock_write: return -1;
1026 			case o::sock_read: return -1;
1027 			case o::sock_open: return lfo::open;
1028 			case o::sock_bind: return lfo::bind;
1029 			case o::available: return -1;
1030 			case o::encryption: return -1;
1031 			case o::connect: return -1;
1032 			case o::ssl_handshake: return -1;
1033 			case o::get_interface: return -1;
1034 			case o::unknown: return -1;
1035 			case o::sock_listen: return lfo::listen;
1036 			case o::sock_bind_to_device: return lfo::bind_to_device;
1037 			case o::sock_accept: return lfo::accept;
1038 			case o::parse_address: return lfo::parse_addr;
1039 			case o::enum_if: return lfo::enum_if;
1040 			case o::file_stat: return -1;
1041 			case o::file_copy: return -1;
1042 			case o::file_fallocate: return -1;
1043 			case o::file_hard_link: return -1;
1044 			case o::file_remove: return -1;
1045 			case o::file_rename: return -1;
1046 			case o::file_open: return -1;
1047 			case o::mkdir: return -1;
1048 			case o::check_resume: return -1;
1049 			case o::exception: return -1;
1050 			case o::alloc_cache_piece: return -1;
1051 			case o::partfile_move: return -1;
1052 			case o::partfile_read: return -1;
1053 			case o::partfile_write: return -1;
1054 			case o::hostname_lookup: return -1;
1055 			case o::symlink: return -1;
1056 			case o::handshake: return -1;
1057 			case o::sock_option: return -1;
1058 			case o::enum_route: return -1;
1059 		}
1060 		return -1;
1061 	}
1062 #ifdef __GNUC__
1063 #pragma GCC diagnostic pop
1064 #endif
1065 #ifdef _MSC_VER
1066 #pragma warning(pop)
1067 #endif
1068 
1069 #endif // TORRENT_ABI_VERSION
1070 
1071 } // anonymous namespace
1072 
listen_failed_alert(aux::stack_allocator & alloc,string_view iface,libtorrent::address const & listen_addr,int listen_port,operation_t const op_,error_code const & ec,libtorrent::socket_type_t t)1073 	listen_failed_alert::listen_failed_alert(
1074 		aux::stack_allocator& alloc
1075 		, string_view iface
1076 		, libtorrent::address const& listen_addr
1077 		, int listen_port
1078 		, operation_t const op_
1079 		, error_code const& ec
1080 		, libtorrent::socket_type_t t)
1081 		: error(ec)
1082 		, op(op_)
1083 		, socket_type(t)
1084 		, address(listen_addr)
1085 		, port(listen_port)
1086 		, m_alloc(alloc)
1087 		, m_interface_idx(alloc.copy_string(iface))
1088 #if TORRENT_ABI_VERSION == 1
1089 		, operation(to_op_t(op_))
1090 		, endpoint(listen_addr, std::uint16_t(listen_port))
1091 		, sock_type(static_cast<socket_type_t>(sock_type_idx(t)))
1092 #endif
1093 	{}
1094 
listen_failed_alert(aux::stack_allocator & alloc,string_view iface,tcp::endpoint const & ep,operation_t const op_,error_code const & ec,libtorrent::socket_type_t t)1095 	listen_failed_alert::listen_failed_alert(
1096 		aux::stack_allocator& alloc
1097 		, string_view iface
1098 		, tcp::endpoint const& ep
1099 		, operation_t const op_
1100 		, error_code const& ec
1101 		, libtorrent::socket_type_t t)
1102 		: listen_failed_alert(alloc
1103 			, iface
1104 			, ep.address()
1105 			, ep.port()
1106 			, op_
1107 			, ec
1108 			, t)
1109 	{}
1110 
listen_failed_alert(aux::stack_allocator & alloc,string_view iface,udp::endpoint const & ep,operation_t const op_,error_code const & ec,libtorrent::socket_type_t t)1111 	listen_failed_alert::listen_failed_alert(
1112 		aux::stack_allocator& alloc
1113 		, string_view iface
1114 		, udp::endpoint const& ep
1115 		, operation_t const op_
1116 		, error_code const& ec
1117 		, libtorrent::socket_type_t t)
1118 		: listen_failed_alert(alloc
1119 			, iface
1120 			, ep.address()
1121 			, ep.port()
1122 			, op_
1123 			, ec
1124 			, t)
1125 	{}
1126 
listen_failed_alert(aux::stack_allocator & alloc,string_view iface,operation_t const op_,error_code const & ec,libtorrent::socket_type_t t)1127 	listen_failed_alert::listen_failed_alert(
1128 		aux::stack_allocator& alloc
1129 		, string_view iface
1130 		, operation_t const op_
1131 		, error_code const& ec
1132 		, libtorrent::socket_type_t t)
1133 		: listen_failed_alert(alloc
1134 			, iface
1135 			, libtorrent::address()
1136 			, 0
1137 			, op_
1138 			, ec
1139 			, t)
1140 	{}
1141 
listen_interface() const1142 	char const* listen_failed_alert::listen_interface() const
1143 	{
1144 		return m_alloc.get().ptr(m_interface_idx);
1145 	}
1146 
message() const1147 	std::string listen_failed_alert::message() const
1148 	{
1149 #ifdef TORRENT_DISABLE_ALERT_MSG
1150 		return {};
1151 #else
1152 		char ret[300];
1153 		std::snprintf(ret, sizeof(ret), "listening on %s (device: %s) failed: [%s] [%s] %s"
1154 			, print_endpoint(address, port).c_str()
1155 			, listen_interface()
1156 			, operation_name(op)
1157 			, sock_type_str(socket_type)
1158 			, convert_from_native(error.message()).c_str());
1159 		return ret;
1160 #endif
1161 	}
1162 
metadata_failed_alert(aux::stack_allocator & alloc,const torrent_handle & h,error_code const & e)1163 	metadata_failed_alert::metadata_failed_alert(aux::stack_allocator& alloc
1164 		, const torrent_handle& h, error_code const& e)
1165 		: torrent_alert(alloc, h)
1166 		, error(e)
1167 	{}
1168 
message() const1169 	std::string metadata_failed_alert::message() const
1170 	{
1171 #ifdef TORRENT_DISABLE_ALERT_MSG
1172 		return {};
1173 #else
1174 		return torrent_alert::message() + " invalid metadata received";
1175 #endif
1176 	}
1177 
metadata_received_alert(aux::stack_allocator & alloc,const torrent_handle & h)1178 	metadata_received_alert::metadata_received_alert(aux::stack_allocator& alloc
1179 		, const torrent_handle& h)
1180 		: torrent_alert(alloc, h)
1181 	{}
1182 
message() const1183 	std::string metadata_received_alert::message() const
1184 	{
1185 #ifdef TORRENT_DISABLE_ALERT_MSG
1186 		return {};
1187 #else
1188 		return torrent_alert::message() + " metadata successfully received";
1189 #endif
1190 	}
1191 
udp_error_alert(aux::stack_allocator &,udp::endpoint const & ep,operation_t op,error_code const & ec)1192 	udp_error_alert::udp_error_alert(
1193 		aux::stack_allocator&
1194 		, udp::endpoint const& ep
1195 		, operation_t op
1196 		, error_code const& ec)
1197 		: endpoint(ep)
1198 		, operation(op)
1199 		, error(ec)
1200 	{}
1201 
message() const1202 	std::string udp_error_alert::message() const
1203 	{
1204 #ifdef TORRENT_DISABLE_ALERT_MSG
1205 		return {};
1206 #else
1207 		error_code ec;
1208 		return "UDP error: " + convert_from_native(error.message())
1209 			+ " from: " + endpoint.address().to_string(ec)
1210 			+ " op: " + operation_name(operation);
1211 #endif
1212 	}
1213 
external_ip_alert(aux::stack_allocator &,address const & ip)1214 	external_ip_alert::external_ip_alert(aux::stack_allocator&
1215 		, address const& ip)
1216 		: external_address(ip)
1217 	{}
1218 
message() const1219 	std::string external_ip_alert::message() const
1220 	{
1221 #ifdef TORRENT_DISABLE_ALERT_MSG
1222 		return {};
1223 #else
1224 		error_code ec;
1225 		return "external IP received: " + external_address.to_string(ec);
1226 #endif
1227 	}
1228 
listen_succeeded_alert(aux::stack_allocator &,libtorrent::address const & listen_addr,int listen_port,libtorrent::socket_type_t t)1229 	listen_succeeded_alert::listen_succeeded_alert(aux::stack_allocator&
1230 		, libtorrent::address const& listen_addr
1231 		, int listen_port
1232 		, libtorrent::socket_type_t t)
1233 		: address(listen_addr)
1234 		, port(listen_port)
1235 		, socket_type(t)
1236 #if TORRENT_ABI_VERSION == 1
1237 		, endpoint(listen_addr, std::uint16_t(listen_port))
1238 		, sock_type(static_cast<socket_type_t>(sock_type_idx(t)))
1239 #endif
1240 	{}
1241 
listen_succeeded_alert(aux::stack_allocator & alloc,tcp::endpoint const & ep,libtorrent::socket_type_t t)1242 	listen_succeeded_alert::listen_succeeded_alert(aux::stack_allocator& alloc
1243 		, tcp::endpoint const& ep
1244 		, libtorrent::socket_type_t t)
1245 		: listen_succeeded_alert(alloc
1246 			, ep.address()
1247 			, ep.port()
1248 			, t)
1249 	{}
1250 
listen_succeeded_alert(aux::stack_allocator & alloc,udp::endpoint const & ep,libtorrent::socket_type_t t)1251 	listen_succeeded_alert::listen_succeeded_alert(aux::stack_allocator& alloc
1252 		, udp::endpoint const& ep
1253 		, libtorrent::socket_type_t t)
1254 		: listen_succeeded_alert(alloc
1255 			, ep.address()
1256 			, ep.port()
1257 			, t)
1258 	{}
1259 
message() const1260 	std::string listen_succeeded_alert::message() const
1261 	{
1262 #ifdef TORRENT_DISABLE_ALERT_MSG
1263 		return {};
1264 #else
1265 		char ret[200];
1266 		std::snprintf(ret, sizeof(ret), "successfully listening on [%s] %s"
1267 			, sock_type_str(socket_type), print_endpoint(address, port).c_str());
1268 		return ret;
1269 #endif
1270 	}
1271 
portmap_error_alert(aux::stack_allocator &,port_mapping_t const i,portmap_transport const t,error_code const & e)1272 	portmap_error_alert::portmap_error_alert(aux::stack_allocator&
1273 		, port_mapping_t const i, portmap_transport const t, error_code const& e)
1274 		: mapping(i)
1275 		, map_transport(t)
1276 		, error(e)
1277 #if TORRENT_ABI_VERSION == 1
1278 		, map_type(static_cast<int>(t))
1279 		, msg(convert_from_native(error.message()))
1280 #endif
1281 	{}
1282 
message() const1283 	std::string portmap_error_alert::message() const
1284 	{
1285 #ifdef TORRENT_DISABLE_ALERT_MSG
1286 		return {};
1287 #else
1288 		return std::string("could not map port using ")
1289 			+ nat_type_str[static_cast<int>(map_transport)]
1290 			+ ": " + convert_from_native(error.message());
1291 #endif
1292 	}
1293 
portmap_alert(aux::stack_allocator &,port_mapping_t const i,int port,portmap_transport const t,portmap_protocol const proto)1294 	portmap_alert::portmap_alert(aux::stack_allocator&, port_mapping_t const i
1295 		, int port
1296 		, portmap_transport const t
1297 		, portmap_protocol const proto)
1298 		: mapping(i)
1299 		, external_port(port)
1300 		, map_protocol(proto)
1301 		, map_transport(t)
1302 #if TORRENT_ABI_VERSION == 1
1303 		, protocol(static_cast<int>(proto))
1304 		, map_type(static_cast<int>(t))
1305 #endif
1306 	{}
1307 
message() const1308 	std::string portmap_alert::message() const
1309 	{
1310 #ifdef TORRENT_DISABLE_ALERT_MSG
1311 		return {};
1312 #else
1313 		char ret[200];
1314 		std::snprintf(ret, sizeof(ret), "successfully mapped port using %s. external port: %s/%d"
1315 			, nat_type_str[static_cast<int>(map_transport)]
1316 			, protocol_str[static_cast<int>(map_protocol)], external_port);
1317 		return ret;
1318 #endif
1319 	}
1320 
portmap_log_alert(aux::stack_allocator & alloc,portmap_transport const t,const char * m)1321 	portmap_log_alert::portmap_log_alert(aux::stack_allocator& alloc
1322 		, portmap_transport const t, const char* m)
1323 		: map_transport(t)
1324 		, m_alloc(alloc)
1325 		, m_log_idx(alloc.copy_string(m))
1326 #if TORRENT_ABI_VERSION == 1
1327 		, map_type(static_cast<int>(t))
1328 		, msg(m)
1329 #endif
1330 	{}
1331 
log_message() const1332 	char const* portmap_log_alert::log_message() const
1333 	{
1334 		return m_alloc.get().ptr(m_log_idx);
1335 	}
1336 
message() const1337 	std::string portmap_log_alert::message() const
1338 	{
1339 #ifdef TORRENT_DISABLE_ALERT_MSG
1340 		return {};
1341 #else
1342 		char ret[1024];
1343 		std::snprintf(ret, sizeof(ret), "%s: %s"
1344 			, nat_type_str[static_cast<int>(map_transport)]
1345 			, log_message());
1346 		return ret;
1347 #endif
1348 	}
1349 
fastresume_rejected_alert(aux::stack_allocator & alloc,torrent_handle const & h,error_code const & ec,string_view f,operation_t const op_)1350 	fastresume_rejected_alert::fastresume_rejected_alert(
1351 		aux::stack_allocator& alloc
1352 		, torrent_handle const& h
1353 		, error_code const& ec
1354 		, string_view f
1355 		, operation_t const op_)
1356 		: torrent_alert(alloc, h)
1357 		, error(ec)
1358 		, op(op_)
1359 		, m_path_idx(alloc.copy_string(f))
1360 #if TORRENT_ABI_VERSION == 1
1361 		, operation(operation_name(op_))
1362 		, file(f)
1363 		, msg(convert_from_native(error.message()))
1364 #endif
1365 	{
1366 	}
1367 
message() const1368 	std::string fastresume_rejected_alert::message() const
1369 	{
1370 #ifdef TORRENT_DISABLE_ALERT_MSG
1371 		return {};
1372 #else
1373 		return torrent_alert::message() + " fast resume rejected. "
1374 			+ operation_name(op) + "(" + file_path() + "): "
1375 			+ convert_from_native(error.message());
1376 #endif
1377 	}
1378 
file_path() const1379 	char const* fastresume_rejected_alert::file_path() const
1380 	{
1381 		return m_alloc.get().ptr(m_path_idx);
1382 	}
1383 
peer_blocked_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,int r)1384 	peer_blocked_alert::peer_blocked_alert(aux::stack_allocator& alloc
1385 		, torrent_handle const& h, tcp::endpoint const& ep, int r)
1386 		: peer_alert(alloc, h, ep, peer_id(nullptr))
1387 		, reason(r)
1388 	{}
1389 
message() const1390 	std::string peer_blocked_alert::message() const
1391 	{
1392 #ifdef TORRENT_DISABLE_ALERT_MSG
1393 		return {};
1394 #else
1395 		char ret[600];
1396 		static char const* const reason_str[] =
1397 		{
1398 			"ip_filter",
1399 			"port_filter",
1400 			"i2p_mixed",
1401 			"privileged_ports",
1402 			"utp_disabled",
1403 			"tcp_disabled",
1404 			"invalid_local_interface",
1405 			"ssrf_mitigation"
1406 		};
1407 
1408 		std::snprintf(ret, sizeof(ret), "%s: blocked peer [%s]"
1409 			, peer_alert::message().c_str(), reason_str[reason]);
1410 		return ret;
1411 #endif
1412 	}
1413 
dht_announce_alert(aux::stack_allocator &,address const & i,int p,sha1_hash const & ih)1414 	dht_announce_alert::dht_announce_alert(aux::stack_allocator&
1415 		, address const& i, int p
1416 		, sha1_hash const& ih)
1417 		: ip(i)
1418 		, port(p)
1419 		, info_hash(ih)
1420 	{}
1421 
message() const1422 	std::string dht_announce_alert::message() const
1423 	{
1424 #ifdef TORRENT_DISABLE_ALERT_MSG
1425 		return {};
1426 #else
1427 		error_code ec;
1428 		char msg[200];
1429 		std::snprintf(msg, sizeof(msg), "incoming dht announce: %s:%d (%s)"
1430 			, ip.to_string(ec).c_str(), port, aux::to_hex(info_hash).c_str());
1431 		return msg;
1432 #endif
1433 	}
1434 
dht_get_peers_alert(aux::stack_allocator &,sha1_hash const & ih)1435 	dht_get_peers_alert::dht_get_peers_alert(aux::stack_allocator&
1436 		, sha1_hash const& ih)
1437 		: info_hash(ih)
1438 	{}
1439 
message() const1440 	std::string dht_get_peers_alert::message() const
1441 	{
1442 #ifdef TORRENT_DISABLE_ALERT_MSG
1443 		return {};
1444 #else
1445 		char msg[200];
1446 		std::snprintf(msg, sizeof(msg), "incoming dht get_peers: %s", aux::to_hex(info_hash).c_str());
1447 		return msg;
1448 #endif
1449 	}
1450 
1451 namespace {
1452 
stat_to_array(stat const & s)1453 		std::array<int, stats_alert::num_channels> stat_to_array(stat const& s)
1454 		{
1455 			std::array<int, stats_alert::num_channels> arr;
1456 
1457 			arr[stats_alert::upload_payload] = s[stat::upload_payload].counter();
1458 			arr[stats_alert::upload_protocol] = s[stat::upload_protocol].counter();
1459 			arr[stats_alert::download_payload] = s[stat::download_payload].counter();
1460 			arr[stats_alert::download_protocol] = s[stat::download_protocol].counter();
1461 			arr[stats_alert::upload_ip_protocol] = s[stat::upload_ip_protocol].counter();
1462 			arr[stats_alert::download_ip_protocol] = s[stat::download_ip_protocol].counter();
1463 
1464 #if TORRENT_ABI_VERSION == 1
1465 			arr[stats_alert::upload_dht_protocol] = 0;
1466 			arr[stats_alert::upload_tracker_protocol] = 0;
1467 			arr[stats_alert::download_dht_protocol] = 0;
1468 			arr[stats_alert::download_tracker_protocol] = 0;
1469 #else
1470 			arr[stats_alert::deprecated1] = 0;
1471 			arr[stats_alert::deprecated2] = 0;
1472 			arr[stats_alert::deprecated3] = 0;
1473 			arr[stats_alert::deprecated4] = 0;
1474 #endif
1475 			return arr;
1476 		}
1477 	}
1478 
stats_alert(aux::stack_allocator & alloc,torrent_handle const & h,int in,stat const & s)1479 	stats_alert::stats_alert(aux::stack_allocator& alloc
1480 		, torrent_handle const& h, int in, stat const& s)
1481 		: torrent_alert(alloc, h)
1482 		, transferred(stat_to_array(s))
1483 		, interval(in)
1484 	{}
1485 
message() const1486 	std::string stats_alert::message() const
1487 	{
1488 #ifdef TORRENT_DISABLE_ALERT_MSG
1489 		return {};
1490 #else
1491 		char msg[200];
1492 		std::snprintf(msg, sizeof(msg), "%s: [%d] %d %d %d %d %d %d"
1493 #if TORRENT_ABI_VERSION == 1
1494 			" %d %d %d %d"
1495 #endif
1496 			, torrent_alert::message().c_str()
1497 			, interval
1498 			, transferred[0]
1499 			, transferred[1]
1500 			, transferred[2]
1501 			, transferred[3]
1502 			, transferred[4]
1503 			, transferred[5]
1504 #if TORRENT_ABI_VERSION == 1
1505 			, transferred[6]
1506 			, transferred[7]
1507 			, transferred[8]
1508 			, transferred[9]
1509 #endif
1510 			);
1511 		return msg;
1512 #endif
1513 	}
1514 
cache_flushed_alert(aux::stack_allocator & alloc,torrent_handle const & h)1515 	cache_flushed_alert::cache_flushed_alert(aux::stack_allocator& alloc
1516 		, torrent_handle const& h)
1517 		: torrent_alert(alloc, h) {}
1518 
1519 #if TORRENT_ABI_VERSION == 1
anonymous_mode_alert(aux::stack_allocator & alloc,torrent_handle const & h,int k,string_view s)1520 	anonymous_mode_alert::anonymous_mode_alert(aux::stack_allocator& alloc
1521 		, torrent_handle const& h, int k, string_view s)
1522 		: torrent_alert(alloc, h)
1523 		, kind(k)
1524 		, str(s)
1525 	{}
1526 
message() const1527 	std::string anonymous_mode_alert::message() const
1528 	{
1529 #ifdef TORRENT_DISABLE_ALERT_MSG
1530 		return {};
1531 #else
1532 		char msg[200];
1533 		static char const* const msgs[] = {
1534 			"tracker is not anonymous, set a proxy"
1535 		};
1536 		std::snprintf(msg, sizeof(msg), "%s: %s: %s"
1537 			, torrent_alert::message().c_str()
1538 			, msgs[kind], str.c_str());
1539 		return msg;
1540 #endif
1541 	}
1542 #endif // TORRENT_ABI_VERSION
1543 
lsd_peer_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & i)1544 	lsd_peer_alert::lsd_peer_alert(aux::stack_allocator& alloc, torrent_handle const& h
1545 		, tcp::endpoint const& i)
1546 		: peer_alert(alloc, h, i, peer_id(nullptr))
1547 	{}
1548 
message() const1549 	std::string lsd_peer_alert::message() const
1550 	{
1551 #ifdef TORRENT_DISABLE_ALERT_MSG
1552 		return {};
1553 #else
1554 		char msg[200];
1555 		std::snprintf(msg, sizeof(msg), "%s: received peer from local service discovery"
1556 			, peer_alert::message().c_str());
1557 		return msg;
1558 #endif
1559 	}
1560 
trackerid_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,string_view u,const std::string & id)1561 	trackerid_alert::trackerid_alert(
1562 		aux::stack_allocator& alloc
1563 		, torrent_handle const& h
1564 		, tcp::endpoint const& ep
1565 		, string_view u
1566 		, const std::string& id)
1567 		: tracker_alert(alloc, h,  ep, u)
1568 		, m_tracker_idx(alloc.copy_string(id))
1569 #if TORRENT_ABI_VERSION == 1
1570 		, trackerid(id)
1571 #endif
1572 	{}
1573 
tracker_id() const1574 	char const* trackerid_alert::tracker_id() const
1575 	{
1576 		return m_alloc.get().ptr(m_tracker_idx);
1577 	}
1578 
message() const1579 	std::string trackerid_alert::message() const
1580 	{
1581 #ifdef TORRENT_DISABLE_ALERT_MSG
1582 		return {};
1583 #else
1584 		return std::string("trackerid received: ") + tracker_id();
1585 #endif
1586 	}
1587 
dht_bootstrap_alert(aux::stack_allocator &)1588 	dht_bootstrap_alert::dht_bootstrap_alert(aux::stack_allocator&)
1589 	{}
1590 
message() const1591 	std::string dht_bootstrap_alert::message() const
1592 	{
1593 #ifdef TORRENT_DISABLE_ALERT_MSG
1594 		return {};
1595 #else
1596 		return "DHT bootstrap complete";
1597 #endif
1598 	}
1599 
torrent_error_alert(aux::stack_allocator & alloc,torrent_handle const & h,error_code const & e,string_view f)1600 	torrent_error_alert::torrent_error_alert(
1601 		aux::stack_allocator& alloc
1602 		, torrent_handle const& h
1603 		, error_code const& e, string_view f)
1604 		: torrent_alert(alloc, h)
1605 		, error(e)
1606 		, m_file_idx(alloc.copy_string(f))
1607 #if TORRENT_ABI_VERSION == 1
1608 		, error_file(f)
1609 #endif
1610 	{}
1611 
message() const1612 	std::string torrent_error_alert::message() const
1613 	{
1614 #ifdef TORRENT_DISABLE_ALERT_MSG
1615 		return {};
1616 #else
1617 		char msg[400];
1618 		if (error)
1619 		{
1620 			std::snprintf(msg, sizeof(msg), " ERROR: (%d %s) %s"
1621 				, error.value(), convert_from_native(error.message()).c_str()
1622 				, filename());
1623 		}
1624 		else
1625 		{
1626 			std::snprintf(msg, sizeof(msg), " ERROR: %s", filename());
1627 		}
1628 		return torrent_alert::message() + msg;
1629 #endif
1630 	}
1631 
filename() const1632 	char const* torrent_error_alert::filename() const
1633 	{
1634 		return m_alloc.get().ptr(m_file_idx);
1635 	}
1636 
1637 #if TORRENT_ABI_VERSION == 1
torrent_added_alert(aux::stack_allocator & alloc,torrent_handle const & h)1638 	torrent_added_alert::torrent_added_alert(aux::stack_allocator& alloc
1639 		, torrent_handle const& h)
1640 		: torrent_alert(alloc, h)
1641 	{}
1642 
message() const1643 	std::string torrent_added_alert::message() const
1644 	{
1645 #ifdef TORRENT_DISABLE_ALERT_MSG
1646 		return {};
1647 #else
1648 		return torrent_alert::message() + " added";
1649 #endif
1650 	}
1651 #endif
1652 
torrent_removed_alert(aux::stack_allocator & alloc,torrent_handle const & h,sha1_hash const & ih)1653 	torrent_removed_alert::torrent_removed_alert(aux::stack_allocator& alloc
1654 		, torrent_handle const& h, sha1_hash const& ih)
1655 		: torrent_alert(alloc, h)
1656 		, info_hash(ih)
1657 	{}
1658 
message() const1659 	std::string torrent_removed_alert::message() const
1660 	{
1661 #ifdef TORRENT_DISABLE_ALERT_MSG
1662 		return {};
1663 #else
1664 		return torrent_alert::message() + " removed";
1665 #endif
1666 	}
1667 
torrent_need_cert_alert(aux::stack_allocator & alloc,torrent_handle const & h)1668 	torrent_need_cert_alert::torrent_need_cert_alert(aux::stack_allocator& alloc
1669 		, torrent_handle const& h)
1670 		: torrent_alert(alloc, h)
1671 	{}
1672 
message() const1673 	std::string torrent_need_cert_alert::message() const
1674 	{
1675 #ifdef TORRENT_DISABLE_ALERT_MSG
1676 		return {};
1677 #else
1678 		return torrent_alert::message() + " needs SSL certificate";
1679 #endif
1680 	}
1681 
incoming_connection_alert(aux::stack_allocator &,int t,tcp::endpoint const & i)1682 	incoming_connection_alert::incoming_connection_alert(aux::stack_allocator&, int t
1683 		, tcp::endpoint const& i)
1684 		: socket_type(t)
1685 		, endpoint(i)
1686 #if TORRENT_ABI_VERSION == 1
1687 		, ip(i)
1688 #endif
1689 	{}
1690 
message() const1691 	std::string incoming_connection_alert::message() const
1692 	{
1693 #ifdef TORRENT_DISABLE_ALERT_MSG
1694 		return {};
1695 #else
1696 		char msg[600];
1697 		std::snprintf(msg, sizeof(msg), "incoming connection from %s (%s)"
1698 			, print_endpoint(endpoint).c_str(), socket_type_str[socket_type]);
1699 		return msg;
1700 #endif
1701 	}
1702 
peer_connect_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id,int type)1703 	peer_connect_alert::peer_connect_alert(aux::stack_allocator& alloc, torrent_handle h
1704 		, tcp::endpoint const& ep, peer_id const& peer_id, int type)
1705 		: peer_alert(alloc, h, ep, peer_id)
1706 		, socket_type(type)
1707 	{}
1708 
message() const1709 	std::string peer_connect_alert::message() const
1710 	{
1711 #ifdef TORRENT_DISABLE_ALERT_MSG
1712 		return {};
1713 #else
1714 		char msg[600];
1715 		std::snprintf(msg, sizeof(msg), "%s connecting to peer (%s)"
1716 			, peer_alert::message().c_str(), socket_type_str[socket_type]);
1717 		return msg;
1718 #endif
1719 	}
1720 
add_torrent_alert(aux::stack_allocator & alloc,torrent_handle const & h,add_torrent_params const & p,error_code const & ec)1721 	add_torrent_alert::add_torrent_alert(aux::stack_allocator& alloc, torrent_handle const& h
1722 		, add_torrent_params const& p, error_code const& ec)
1723 		: torrent_alert(alloc, h)
1724 		, params(p)
1725 		, error(ec)
1726 	{}
1727 
message() const1728 	std::string add_torrent_alert::message() const
1729 	{
1730 #ifdef TORRENT_DISABLE_ALERT_MSG
1731 		return {};
1732 #else
1733 		char msg[600];
1734 		char info_hash[41];
1735 		char const* torrent_name = info_hash;
1736 		if (params.ti) torrent_name = params.ti->name().c_str();
1737 		else if (!params.name.empty()) torrent_name = params.name.c_str();
1738 #if TORRENT_ABI_VERSION == 1
1739 		else if (!params.url.empty()) torrent_name = params.url.c_str();
1740 #endif
1741 		else aux::to_hex(params.info_hash, info_hash);
1742 
1743 		if (error)
1744 		{
1745 			std::snprintf(msg, sizeof(msg), "failed to add torrent \"%s\": [%s] %s"
1746 				, torrent_name, error.category().name()
1747 				, convert_from_native(error.message()).c_str());
1748 		}
1749 		else
1750 		{
1751 			std::snprintf(msg, sizeof(msg), "added torrent: %s", torrent_name);
1752 		}
1753 		return msg;
1754 #endif
1755 	}
1756 
state_update_alert(aux::stack_allocator &,std::vector<torrent_status> st)1757 	state_update_alert::state_update_alert(aux::stack_allocator&
1758 		, std::vector<torrent_status> st)
1759 		: status(std::move(st))
1760 	{}
1761 
message() const1762 	std::string state_update_alert::message() const
1763 	{
1764 #ifdef TORRENT_DISABLE_ALERT_MSG
1765 		return {};
1766 #else
1767 		char msg[600];
1768 		std::snprintf(msg, sizeof(msg), "state updates for %d torrents", int(status.size()));
1769 		return msg;
1770 #endif
1771 	}
1772 
1773 #if TORRENT_ABI_VERSION == 1
mmap_cache_alert(aux::stack_allocator &,error_code const & ec)1774 	mmap_cache_alert::mmap_cache_alert(aux::stack_allocator&
1775 		, error_code const& ec): error(ec)
1776 	{}
1777 
message() const1778 	std::string mmap_cache_alert::message() const
1779 	{
1780 #ifdef TORRENT_DISABLE_ALERT_MSG
1781 		return {};
1782 #else
1783 		char msg[600];
1784 		std::snprintf(msg, sizeof(msg), "mmap cache failed: (%d) %s", error.value()
1785 			, convert_from_native(error.message()).c_str());
1786 		return msg;
1787 #endif
1788 	}
1789 #endif
1790 
operation_name(operation_t const op)1791 	char const* operation_name(operation_t const op)
1792 	{
1793 #ifdef TORRENT_DISABLE_ALERT_MSG
1794 		TORRENT_UNUSED(op);
1795 		return "";
1796 #else
1797 		static char const* const names[] = {
1798 			"unknown",
1799 			"bittorrent",
1800 			"iocontrol",
1801 			"getpeername",
1802 			"getname",
1803 			"alloc_recvbuf",
1804 			"alloc_sndbuf",
1805 			"file_write",
1806 			"file_read",
1807 			"file",
1808 			"sock_write",
1809 			"sock_read",
1810 			"sock_open",
1811 			"sock_bind",
1812 			"available",
1813 			"encryption",
1814 			"connect",
1815 			"ssl_handshake",
1816 			"get_interface",
1817 			"sock_listen",
1818 			"sock_bind_to_device",
1819 			"sock_accept",
1820 			"parse_address",
1821 			"enum_if",
1822 			"file_stat",
1823 			"file_copy",
1824 			"file_fallocate",
1825 			"file_hard_link",
1826 			"file_remove",
1827 			"file_rename",
1828 			"file_open",
1829 			"mkdir",
1830 			"check_resume",
1831 			"exception",
1832 			"alloc_cache_piece",
1833 			"partfile_move",
1834 			"partfile_read",
1835 			"partfile_write",
1836 			"hostname_lookup",
1837 			"symlink",
1838 			"handshake",
1839 			"sock_option",
1840 			"enum_route"
1841 		};
1842 
1843 		int const idx = static_cast<int>(op);
1844 		if (idx < 0 || idx >= int(sizeof(names) / sizeof(names[0])))
1845 			return "unknown operation";
1846 
1847 		return names[idx];
1848 #endif
1849 	}
1850 
1851 #if TORRENT_ABI_VERSION == 1
operation_name(int const op)1852 	char const* operation_name(int const op)
1853 	{
1854 		return operation_name(static_cast<operation_t>(op));
1855 	}
1856 #endif
1857 
peer_error_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,peer_id const & peer_id,operation_t const op_,error_code const & e)1858 	peer_error_alert::peer_error_alert(aux::stack_allocator& alloc, torrent_handle const& h
1859 		, tcp::endpoint const& ep, peer_id const& peer_id, operation_t const op_
1860 		, error_code const& e)
1861 		: peer_alert(alloc, h, ep, peer_id)
1862 		, op(op_)
1863 		, error(e)
1864 #if TORRENT_ABI_VERSION == 1
1865 		, operation(static_cast<int>(op_))
1866 		, msg(convert_from_native(error.message()))
1867 #endif
1868 	{}
1869 
message() const1870 	std::string peer_error_alert::message() const
1871 	{
1872 #ifdef TORRENT_DISABLE_ALERT_MSG
1873 		return {};
1874 #else
1875 		char buf[200];
1876 		std::snprintf(buf, sizeof(buf), "%s peer error [%s] [%s]: %s"
1877 			, peer_alert::message().c_str()
1878 			, operation_name(op), error.category().name()
1879 			, convert_from_native(error.message()).c_str());
1880 		return buf;
1881 #endif
1882 	}
1883 
1884 #if TORRENT_ABI_VERSION == 1
torrent_update_alert(aux::stack_allocator & alloc,torrent_handle h,sha1_hash const & old_hash,sha1_hash const & new_hash)1885 	torrent_update_alert::torrent_update_alert(aux::stack_allocator& alloc, torrent_handle h
1886 		, sha1_hash const& old_hash, sha1_hash const& new_hash)
1887 		: torrent_alert(alloc, h)
1888 		, old_ih(old_hash)
1889 		, new_ih(new_hash)
1890 	{}
1891 
message() const1892 	std::string torrent_update_alert::message() const
1893 	{
1894 #ifdef TORRENT_DISABLE_ALERT_MSG
1895 		return {};
1896 #else
1897 		char msg[200];
1898 		std::snprintf(msg, sizeof(msg), " torrent changed info-hash from: %s to %s"
1899 			, aux::to_hex(old_ih).c_str()
1900 			, aux::to_hex(new_ih).c_str());
1901 		return torrent_alert::message() + msg;
1902 #endif
1903 	}
1904 #endif
1905 
peer_disconnected_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,peer_id const & peer_id,operation_t op_,int type,error_code const & e,close_reason_t r)1906 	peer_disconnected_alert::peer_disconnected_alert(aux::stack_allocator& alloc
1907 		, torrent_handle const& h, tcp::endpoint const& ep
1908 		, peer_id const& peer_id, operation_t op_, int type, error_code const& e
1909 		, close_reason_t r)
1910 		: peer_alert(alloc, h, ep, peer_id)
1911 		, socket_type(type)
1912 		, op(op_)
1913 		, error(e)
1914 		, reason(r)
1915 #if TORRENT_ABI_VERSION == 1
1916 		, operation(static_cast<int>(op))
1917 		, msg(convert_from_native(error.message()))
1918 #endif
1919 	{}
1920 
message() const1921 	std::string peer_disconnected_alert::message() const
1922 	{
1923 #ifdef TORRENT_DISABLE_ALERT_MSG
1924 		return {};
1925 #else
1926 		char buf[600];
1927 		std::snprintf(buf, sizeof(buf), "%s disconnecting (%s) [%s] [%s]: %s (reason: %d)"
1928 			, peer_alert::message().c_str()
1929 			, socket_type_str[socket_type]
1930 			, operation_name(op), error.category().name()
1931 			, convert_from_native(error.message()).c_str()
1932 			, int(reason));
1933 		return buf;
1934 #endif
1935 	}
1936 
dht_error_alert(aux::stack_allocator &,operation_t const op_,error_code const & ec)1937 	dht_error_alert::dht_error_alert(aux::stack_allocator&
1938 		, operation_t const op_
1939 		, error_code const& ec)
1940 		: error(ec)
1941 		, op(op_)
1942 #if TORRENT_ABI_VERSION == 1
1943 		, operation(op_ == operation_t::hostname_lookup
1944 			? op_t::hostname_lookup : op_t::unknown)
1945 #endif
1946 	{}
1947 
message() const1948 	std::string dht_error_alert::message() const
1949 	{
1950 #ifdef TORRENT_DISABLE_ALERT_MSG
1951 		return {};
1952 #else
1953 		char msg[600];
1954 		std::snprintf(msg, sizeof(msg), "DHT error [%s] (%d) %s"
1955 			, operation_name(op)
1956 			, error.value()
1957 			, convert_from_native(error.message()).c_str());
1958 		return msg;
1959 #endif
1960 	}
1961 
dht_immutable_item_alert(aux::stack_allocator &,sha1_hash const & t,entry const & i)1962 	dht_immutable_item_alert::dht_immutable_item_alert(aux::stack_allocator&
1963 		, sha1_hash const& t, entry const& i)
1964 		: target(t), item(i)
1965 	{}
1966 
message() const1967 	std::string dht_immutable_item_alert::message() const
1968 	{
1969 #ifdef TORRENT_DISABLE_ALERT_MSG
1970 		return {};
1971 #else
1972 		char msg[1050];
1973 		std::snprintf(msg, sizeof(msg), "DHT immutable item %s [ %s ]"
1974 			, aux::to_hex(target).c_str()
1975 			, item.to_string().c_str());
1976 		return msg;
1977 #endif
1978 	}
1979 
1980 	// TODO: 2 the salt here is allocated on the heap. It would be nice to
1981 	// allocate in the stack_allocator
dht_mutable_item_alert(aux::stack_allocator &,std::array<char,32> const & k,std::array<char,64> const & sig,std::int64_t sequence,string_view s,entry const & i,bool a)1982 	dht_mutable_item_alert::dht_mutable_item_alert(aux::stack_allocator&
1983 		, std::array<char, 32> const& k
1984 		, std::array<char, 64> const& sig
1985 		, std::int64_t sequence
1986 		, string_view s
1987 		, entry const& i
1988 		, bool a)
1989 		: key(k), signature(sig), seq(sequence), salt(s), item(i), authoritative(a)
1990 	{}
1991 
message() const1992 	std::string dht_mutable_item_alert::message() const
1993 	{
1994 #ifdef TORRENT_DISABLE_ALERT_MSG
1995 		return {};
1996 #else
1997 		char msg[1050];
1998 		std::snprintf(msg, sizeof(msg), "DHT mutable item (key=%s salt=%s seq=%" PRId64 " %s) [ %s ]"
1999 			, aux::to_hex(key).c_str()
2000 			, salt.c_str()
2001 			, seq
2002 			, authoritative ? "auth" : "non-auth"
2003 			, item.to_string().c_str());
2004 		return msg;
2005 #endif
2006 	}
2007 
dht_put_alert(aux::stack_allocator &,sha1_hash const & t,int n)2008 	dht_put_alert::dht_put_alert(aux::stack_allocator&, sha1_hash const& t, int n)
2009 		: target(t)
2010 		, public_key()
2011 		, signature()
2012 		, salt()
2013 		, seq(0)
2014 		, num_success(n)
2015 	{}
2016 
dht_put_alert(aux::stack_allocator &,std::array<char,32> const & key,std::array<char,64> const & sig,std::string s,std::int64_t sequence_number,int n)2017 	dht_put_alert::dht_put_alert(aux::stack_allocator&
2018 		, std::array<char, 32> const& key
2019 		, std::array<char, 64> const& sig
2020 		, std::string s
2021 		, std::int64_t sequence_number
2022 		, int n)
2023 		: target(nullptr)
2024 		, public_key(key)
2025 		, signature(sig)
2026 		, salt(std::move(s))
2027 		, seq(sequence_number)
2028 		, num_success(n)
2029 	{}
2030 
message() const2031 	std::string dht_put_alert::message() const
2032 	{
2033 #ifdef TORRENT_DISABLE_ALERT_MSG
2034 		return {};
2035 #else
2036 		char msg[1050];
2037 		if (target.is_all_zeros())
2038 		{
2039 			std::snprintf(msg, sizeof(msg), "DHT put complete (success=%d key=%s sig=%s salt=%s seq=%" PRId64 ")"
2040 				, num_success
2041 				, aux::to_hex(public_key).c_str()
2042 				, aux::to_hex(signature).c_str()
2043 				, salt.c_str()
2044 				, seq);
2045 			return msg;
2046 		}
2047 
2048 		std::snprintf(msg, sizeof(msg), "DHT put complete (success=%d hash=%s)"
2049 			, num_success
2050 			, aux::to_hex(target).c_str());
2051 		return msg;
2052 #endif
2053 	}
2054 
i2p_alert(aux::stack_allocator &,error_code const & ec)2055 	i2p_alert::i2p_alert(aux::stack_allocator&, error_code const& ec)
2056 		: error(ec)
2057 	{}
2058 
message() const2059 	std::string i2p_alert::message() const
2060 	{
2061 #ifdef TORRENT_DISABLE_ALERT_MSG
2062 		return {};
2063 #else
2064 		char msg[600];
2065 		std::snprintf(msg, sizeof(msg), "i2p_error: [%s] %s"
2066 			, error.category().name(), convert_from_native(error.message()).c_str());
2067 		return msg;
2068 #endif
2069 	}
2070 
dht_outgoing_get_peers_alert(aux::stack_allocator &,sha1_hash const & ih,sha1_hash const & obfih,udp::endpoint ep)2071 	dht_outgoing_get_peers_alert::dht_outgoing_get_peers_alert(aux::stack_allocator&
2072 		, sha1_hash const& ih, sha1_hash const& obfih
2073 		, udp::endpoint ep)
2074 		: info_hash(ih)
2075 		, obfuscated_info_hash(obfih)
2076 		, endpoint(std::move(ep))
2077 #if TORRENT_ABI_VERSION == 1
2078 		, ip(endpoint)
2079 #endif
2080 	{}
2081 
message() const2082 	std::string dht_outgoing_get_peers_alert::message() const
2083 	{
2084 #ifdef TORRENT_DISABLE_ALERT_MSG
2085 		return {};
2086 #else
2087 		char msg[600];
2088 		char obf[70];
2089 		obf[0] = '\0';
2090 		if (obfuscated_info_hash != info_hash)
2091 		{
2092 			std::snprintf(obf, sizeof(obf), " [obfuscated: %s]"
2093 			, aux::to_hex(obfuscated_info_hash).c_str());
2094 		}
2095 		std::snprintf(msg, sizeof(msg), "outgoing dht get_peers : %s%s -> %s"
2096 			, aux::to_hex(info_hash).c_str()
2097 			, obf
2098 			, print_endpoint(endpoint).c_str());
2099 		return msg;
2100 #endif
2101 	}
2102 
log_alert(aux::stack_allocator & alloc,char const * log)2103 	log_alert::log_alert(aux::stack_allocator& alloc, char const* log)
2104 		: m_alloc(alloc)
2105 		, m_str_idx(alloc.copy_string(log))
2106 	{}
log_alert(aux::stack_allocator & alloc,char const * fmt,va_list v)2107 	log_alert::log_alert(aux::stack_allocator& alloc, char const* fmt, va_list v)
2108 		: m_alloc(alloc)
2109 		, m_str_idx(alloc.format_string(fmt, v))
2110 	{}
2111 
log_message() const2112 	char const* log_alert::log_message() const
2113 	{
2114 		return m_alloc.get().ptr(m_str_idx);
2115 	}
2116 
2117 #if TORRENT_ABI_VERSION == 1
msg() const2118 	char const* log_alert::msg() const
2119 	{
2120 		return log_message();
2121 	}
2122 #endif
2123 
message() const2124 	std::string log_alert::message() const
2125 	{
2126 #ifdef TORRENT_DISABLE_ALERT_MSG
2127 		return {};
2128 #else
2129 		return log_message();
2130 #endif
2131 	}
2132 
torrent_log_alert(aux::stack_allocator & alloc,torrent_handle const & h,char const * fmt,va_list v)2133 	torrent_log_alert::torrent_log_alert(aux::stack_allocator& alloc, torrent_handle const& h
2134 		, char const* fmt, va_list v)
2135 		: torrent_alert(alloc, h)
2136 		, m_str_idx(alloc.format_string(fmt, v))
2137 	{}
2138 
log_message() const2139 	char const* torrent_log_alert::log_message() const
2140 	{
2141 		return m_alloc.get().ptr(m_str_idx);
2142 	}
2143 
2144 #if TORRENT_ABI_VERSION == 1
msg() const2145 	char const* torrent_log_alert::msg() const
2146 	{
2147 		return log_message();
2148 	}
2149 #endif
2150 
message() const2151 	std::string torrent_log_alert::message() const
2152 	{
2153 #ifdef TORRENT_DISABLE_ALERT_MSG
2154 		return {};
2155 #else
2156 		return torrent_alert::message() + ": " + log_message();
2157 #endif
2158 	}
2159 
peer_log_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & i,peer_id const & pi,peer_log_alert::direction_t dir,char const * event,char const * fmt,va_list v)2160 	peer_log_alert::peer_log_alert(aux::stack_allocator& alloc
2161 		, torrent_handle const& h
2162 		, tcp::endpoint const& i, peer_id const& pi
2163 		, peer_log_alert::direction_t dir
2164 		, char const* event, char const* fmt, va_list v)
2165 		: peer_alert(alloc, h, i, pi)
2166 		, event_type(event)
2167 		, direction(dir)
2168 		, m_str_idx(alloc.format_string(fmt, v))
2169 	{}
2170 
log_message() const2171 	char const* peer_log_alert::log_message() const
2172 	{
2173 		return m_alloc.get().ptr(m_str_idx);
2174 	}
2175 
2176 #if TORRENT_ABI_VERSION == 1
msg() const2177 	char const* peer_log_alert::msg() const
2178 	{
2179 		return log_message();
2180 	}
2181 #endif
2182 
message() const2183 	std::string peer_log_alert::message() const
2184 	{
2185 #ifdef TORRENT_DISABLE_ALERT_MSG
2186 		return {};
2187 #else
2188 		static char const* const mode[] =
2189 		{ "<==", "==>", "<<<", ">>>", "***" };
2190 		return peer_alert::message() + " [" + print_endpoint(endpoint) + "] "
2191 			+ mode[direction] + " " + event_type + " [ " + log_message() + " ]";
2192 #endif
2193 	}
2194 
lsd_error_alert(aux::stack_allocator &,error_code const & ec)2195 	lsd_error_alert::lsd_error_alert(aux::stack_allocator&, error_code const& ec)
2196 		: alert()
2197 		, error(ec)
2198 	{}
2199 
message() const2200 	std::string lsd_error_alert::message() const
2201 	{
2202 #ifdef TORRENT_DISABLE_ALERT_MSG
2203 		return {};
2204 #else
2205 		return "Local Service Discovery startup error: " + convert_from_native(error.message());
2206 #endif
2207 	}
2208 
2209 #if TORRENT_ABI_VERSION == 1
2210 namespace {
2211 
counters_to_array(counters const & cnt)2212 	aux::array<std::int64_t, counters::num_counters> counters_to_array(counters const& cnt)
2213 	{
2214 		aux::array<std::int64_t, counters::num_counters> arr;
2215 
2216 		for (int i = 0; i < counters::num_counters; ++i)
2217 			arr[i] = cnt[i];
2218 
2219 		return arr;
2220 	}
2221 }
2222 #else
2223 namespace {
2224 	template <typename T, typename U>
2225 	T* align_pointer(U* ptr)
2226 	{
2227 		return reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(ptr) + alignof(T) - 1)
2228 			& ~(alignof(T) - 1));
2229 	}
2230 }
2231 #endif
2232 
2233 #if TORRENT_ABI_VERSION == 1
session_stats_alert(aux::stack_allocator &,struct counters const & cnt)2234 	session_stats_alert::session_stats_alert(aux::stack_allocator&, struct counters const& cnt)
2235 		: values(counters_to_array(cnt))
2236 	{}
2237 #else
session_stats_alert(aux::stack_allocator & alloc,struct counters const & cnt)2238 	session_stats_alert::session_stats_alert(aux::stack_allocator& alloc, struct counters const& cnt)
2239 		: m_alloc(alloc)
2240 		, m_counters_idx(alloc.allocate(sizeof(std::int64_t)
2241 			* counters::num_counters + sizeof(std::int64_t) - 1))
2242 	{
2243 		std::int64_t* ptr = align_pointer<std::int64_t>(alloc.ptr(m_counters_idx));
2244 		for (int i = 0; i < counters::num_counters; ++i, ++ptr)
2245 			*ptr = cnt[i];
2246 	}
2247 #endif
2248 
message() const2249 	std::string session_stats_alert::message() const
2250 	{
2251 #ifdef TORRENT_DISABLE_ALERT_MSG
2252 		return {};
2253 #else
2254 		char msg[50];
2255 		auto cnt = counters();
2256 		std::snprintf(msg, sizeof(msg), "session stats (%d values): " , int(cnt.size()));
2257 		std::string ret = msg;
2258 		bool first = true;
2259 		for (auto v : cnt)
2260 		{
2261 			std::snprintf(msg, sizeof(msg), first ? "%" PRId64 : ", %" PRId64, v);
2262 			first = false;
2263 			ret += msg;
2264 		}
2265 		return ret;
2266 #endif
2267 	}
2268 
counters() const2269 	span<std::int64_t const> session_stats_alert::counters() const
2270 	{
2271 #if TORRENT_ABI_VERSION == 1
2272 		return values;
2273 #else
2274 		return { align_pointer<std::int64_t const>(m_alloc.get().ptr(m_counters_idx))
2275 			, counters::num_counters };
2276 #endif
2277 	}
2278 
dht_stats_alert(aux::stack_allocator &,std::vector<dht_routing_bucket> table,std::vector<dht_lookup> requests)2279 	dht_stats_alert::dht_stats_alert(aux::stack_allocator&
2280 		, std::vector<dht_routing_bucket> table
2281 		, std::vector<dht_lookup> requests)
2282 		: alert()
2283 		, active_requests(std::move(requests))
2284 		, routing_table(std::move(table))
2285 	{}
2286 
message() const2287 	std::string dht_stats_alert::message() const
2288 	{
2289 #ifdef TORRENT_DISABLE_ALERT_MSG
2290 		return {};
2291 #else
2292 		char buf[2048];
2293 		std::snprintf(buf, sizeof(buf), "DHT stats: reqs: %d buckets: %d"
2294 			, int(active_requests.size())
2295 			, int(routing_table.size()));
2296 		return buf;
2297 #endif
2298 	}
2299 
url_seed_alert(aux::stack_allocator & alloc,torrent_handle const & h,string_view u,error_code const & e)2300 	url_seed_alert::url_seed_alert(aux::stack_allocator& alloc, torrent_handle const& h
2301 		, string_view u, error_code const& e)
2302 		: torrent_alert(alloc, h)
2303 		, error(e)
2304 		, m_url_idx(alloc.copy_string(u))
2305 		, m_msg_idx()
2306 #if TORRENT_ABI_VERSION == 1
2307 		, url(u)
2308 		, msg(convert_from_native(e.message()))
2309 #endif
2310 	{}
2311 
url_seed_alert(aux::stack_allocator & alloc,torrent_handle const & h,string_view u,string_view m)2312 	url_seed_alert::url_seed_alert(aux::stack_allocator& alloc, torrent_handle const& h
2313 		, string_view u, string_view m)
2314 		: torrent_alert(alloc, h)
2315 		, m_url_idx(alloc.copy_string(u))
2316 		, m_msg_idx(alloc.copy_string(m))
2317 #if TORRENT_ABI_VERSION == 1
2318 		, url(u)
2319 		, msg(m)
2320 #endif
2321 	{}
2322 
message() const2323 	std::string url_seed_alert::message() const
2324 	{
2325 #ifdef TORRENT_DISABLE_ALERT_MSG
2326 		return {};
2327 #else
2328 		return torrent_alert::message() + " url seed ("
2329 			+ server_url() + ") failed: " + convert_from_native(error.message());
2330 #endif
2331 	}
2332 
server_url() const2333 	char const* url_seed_alert::server_url() const
2334 	{
2335 		return m_alloc.get().ptr(m_url_idx);
2336 	}
2337 
error_message() const2338 	char const* url_seed_alert::error_message() const
2339 	{
2340 		if (m_msg_idx == aux::allocation_slot()) return "";
2341 		return m_alloc.get().ptr(m_msg_idx);
2342 	}
2343 
file_error_alert(aux::stack_allocator & alloc,error_code const & ec,string_view f,operation_t const op_,torrent_handle const & h)2344 	file_error_alert::file_error_alert(aux::stack_allocator& alloc
2345 		, error_code const& ec, string_view f, operation_t const op_
2346 		, torrent_handle const& h)
2347 		: torrent_alert(alloc, h)
2348 		, error(ec)
2349 		, op(op_)
2350 		, m_file_idx(alloc.copy_string(f))
2351 #if TORRENT_ABI_VERSION == 1
2352 		, operation(operation_name(op_))
2353 		, file(f)
2354 		, msg(convert_from_native(error.message()))
2355 #endif
2356 	{}
2357 
filename() const2358 	char const* file_error_alert::filename() const
2359 	{
2360 		return m_alloc.get().ptr(m_file_idx);
2361 	}
2362 
message() const2363 	std::string file_error_alert::message() const
2364 	{
2365 #ifdef TORRENT_DISABLE_ALERT_MSG
2366 		return {};
2367 #else
2368 		return torrent_alert::message() + " "
2369 			+ operation_name(op) + " (" + filename()
2370 			+ ") error: " + convert_from_native(error.message());
2371 #endif
2372 	}
2373 
incoming_request_alert(aux::stack_allocator & alloc,peer_request r,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id)2374 	incoming_request_alert::incoming_request_alert(aux::stack_allocator& alloc
2375 		, peer_request r, torrent_handle h
2376 		, tcp::endpoint const& ep, peer_id const& peer_id)
2377 		: peer_alert(alloc, h, ep, peer_id)
2378 		, req(r)
2379 	{}
2380 
message() const2381 	std::string incoming_request_alert::message() const
2382 	{
2383 #ifdef TORRENT_DISABLE_ALERT_MSG
2384 		return {};
2385 #else
2386 		char msg[1024];
2387 		std::snprintf(msg, sizeof(msg), "%s: incoming request [ piece: %d start: %d length: %d ]"
2388 			, peer_alert::message().c_str(), static_cast<int>(req.piece)
2389 			, req.start, req.length);
2390 		return msg;
2391 #endif
2392 	}
2393 
dht_log_alert(aux::stack_allocator & alloc,dht_log_alert::dht_module_t m,const char * fmt,va_list v)2394 	dht_log_alert::dht_log_alert(aux::stack_allocator& alloc
2395 		, dht_log_alert::dht_module_t m, const char* fmt, va_list v)
2396 		: module(m)
2397 		, m_alloc(alloc)
2398 		, m_msg_idx(alloc.format_string(fmt, v))
2399 	{}
2400 
log_message() const2401 	char const* dht_log_alert::log_message() const
2402 	{
2403 		return m_alloc.get().ptr(m_msg_idx);
2404 	}
2405 
message() const2406 	std::string dht_log_alert::message() const
2407 	{
2408 #ifdef TORRENT_DISABLE_ALERT_MSG
2409 		return {};
2410 #else
2411 		static char const* const dht_modules[] =
2412 		{
2413 			"tracker",
2414 			"node",
2415 			"routing_table",
2416 			"rpc_manager",
2417 			"traversal"
2418 		};
2419 
2420 		char ret[900];
2421 		std::snprintf(ret, sizeof(ret), "DHT %s: %s", dht_modules[module]
2422 			, log_message());
2423 		return ret;
2424 #endif
2425 	}
2426 
dht_pkt_alert(aux::stack_allocator & alloc,span<char const> buf,dht_pkt_alert::direction_t d,udp::endpoint const & ep)2427 	dht_pkt_alert::dht_pkt_alert(aux::stack_allocator& alloc
2428 		, span<char const> buf, dht_pkt_alert::direction_t d
2429 		, udp::endpoint const& ep)
2430 		: direction(d)
2431 		, node(ep)
2432 		, m_alloc(alloc)
2433 		, m_msg_idx(alloc.copy_buffer(buf))
2434 		, m_size(aux::numeric_cast<int>(buf.size()))
2435 #if TORRENT_ABI_VERSION == 1
2436 		, dir(d)
2437 #endif
2438 	{}
2439 
pkt_buf() const2440 	span<char const> dht_pkt_alert::pkt_buf() const
2441 	{
2442 		return {m_alloc.get().ptr(m_msg_idx), m_size};
2443 	}
2444 
message() const2445 	std::string dht_pkt_alert::message() const
2446 	{
2447 #ifdef TORRENT_DISABLE_ALERT_MSG
2448 		return {};
2449 #else
2450 		bdecode_node print;
2451 		error_code ec;
2452 
2453 		// ignore errors here. This is best-effort. It may be a broken encoding
2454 		// but at least we'll print the valid parts
2455 		span<char const> pkt = pkt_buf();
2456 		bdecode(pkt.data(), pkt.data() + int(pkt.size()), print, ec, nullptr, 100, 100);
2457 
2458 		std::string msg = print_entry(print, true);
2459 
2460 		static char const* const prefix[2] = {"<==", "==>"};
2461 		char buf[1024];
2462 		std::snprintf(buf, sizeof(buf), "%s [%s] %s", prefix[direction]
2463 			, print_endpoint(node).c_str(), msg.c_str());
2464 
2465 		return buf;
2466 #endif
2467 	}
2468 
dht_get_peers_reply_alert(aux::stack_allocator & alloc,sha1_hash const & ih,std::vector<tcp::endpoint> const & peers)2469 	dht_get_peers_reply_alert::dht_get_peers_reply_alert(aux::stack_allocator& alloc
2470 		, sha1_hash const& ih
2471 		, std::vector<tcp::endpoint> const& peers)
2472 		: info_hash(ih)
2473 		, m_alloc(alloc)
2474 	{
2475 		for (auto const& endp : peers)
2476 		{
2477 			if (is_v4(endp))
2478 				m_v4_num_peers++;
2479 			else
2480 				m_v6_num_peers++;
2481 		}
2482 
2483 		m_v4_peers_idx = alloc.allocate(m_v4_num_peers * 6);
2484 		m_v6_peers_idx = alloc.allocate(m_v6_num_peers * 18);
2485 
2486 		char* v4_ptr = alloc.ptr(m_v4_peers_idx);
2487 		char* v6_ptr = alloc.ptr(m_v6_peers_idx);
2488 		for (auto const& endp : peers)
2489 		{
2490 			if (is_v4(endp))
2491 				detail::write_endpoint(endp, v4_ptr);
2492 			else
2493 				detail::write_endpoint(endp, v6_ptr);
2494 		}
2495 	}
2496 
message() const2497 	std::string dht_get_peers_reply_alert::message() const
2498 	{
2499 #ifdef TORRENT_DISABLE_ALERT_MSG
2500 		return {};
2501 #else
2502 		char msg[200];
2503 		std::snprintf(msg, sizeof(msg), "incoming dht get_peers reply: %s, peers %d"
2504 			, aux::to_hex(info_hash).c_str(), num_peers());
2505 		return msg;
2506 #endif
2507 	}
2508 
num_peers() const2509 	int dht_get_peers_reply_alert::num_peers() const
2510 	{
2511 		return m_v4_num_peers + m_v6_num_peers;
2512 	}
2513 
2514 #if TORRENT_ABI_VERSION == 1
peers(std::vector<tcp::endpoint> & v) const2515 	void dht_get_peers_reply_alert::peers(std::vector<tcp::endpoint> &v) const
2516 	{
2517 		std::vector<tcp::endpoint> p(peers());
2518 		v.reserve(p.size());
2519 		std::copy(p.begin(), p.end(), std::back_inserter(v));
2520 	}
2521 #endif
peers() const2522 	std::vector<tcp::endpoint> dht_get_peers_reply_alert::peers() const
2523 	{
2524 		aux::vector<tcp::endpoint> peers;
2525 		peers.reserve(num_peers());
2526 
2527 		char const* v4_ptr = m_alloc.get().ptr(m_v4_peers_idx);
2528 		for (int i = 0; i < m_v4_num_peers; i++)
2529 			peers.push_back(detail::read_v4_endpoint<tcp::endpoint>(v4_ptr));
2530 		char const* v6_ptr = m_alloc.get().ptr(m_v6_peers_idx);
2531 		for (int i = 0; i < m_v6_num_peers; i++)
2532 			peers.push_back(detail::read_v6_endpoint<tcp::endpoint>(v6_ptr));
2533 
2534 		return std::move(peers);
2535 	}
2536 
dht_direct_response_alert(aux::stack_allocator & alloc,void * userdata_,udp::endpoint const & addr_,bdecode_node const & response)2537 	dht_direct_response_alert::dht_direct_response_alert(
2538 		aux::stack_allocator& alloc, void* userdata_
2539 		, udp::endpoint const& addr_, bdecode_node const& response)
2540 		: userdata(userdata_), endpoint(addr_)
2541 		, m_alloc(alloc)
2542 		, m_response_idx(alloc.copy_buffer(response.data_section()))
2543 		, m_response_size(int(response.data_section().size()))
2544 #if TORRENT_ABI_VERSION == 1
2545 		, addr(addr_)
2546 #endif
2547 	{}
2548 
dht_direct_response_alert(aux::stack_allocator & alloc,void * userdata_,udp::endpoint const & addr_)2549 	dht_direct_response_alert::dht_direct_response_alert(
2550 		aux::stack_allocator& alloc
2551 		, void* userdata_
2552 		, udp::endpoint const& addr_)
2553 		: userdata(userdata_), endpoint(addr_)
2554 		, m_alloc(alloc)
2555 		, m_response_idx()
2556 		, m_response_size(0)
2557 #if TORRENT_ABI_VERSION == 1
2558 		, addr(addr_)
2559 #endif
2560 	{}
2561 
message() const2562 	std::string dht_direct_response_alert::message() const
2563 	{
2564 #ifdef TORRENT_DISABLE_ALERT_MSG
2565 		return {};
2566 #else
2567 		char msg[1050];
2568 		std::snprintf(msg, sizeof(msg), "DHT direct response (address=%s) [ %s ]"
2569 			, endpoint.address().to_string().c_str()
2570 			, m_response_size ? std::string(m_alloc.get().ptr(m_response_idx)
2571 				, aux::numeric_cast<std::size_t>(m_response_size)).c_str() : "");
2572 		return msg;
2573 #endif
2574 	}
2575 
response() const2576 	bdecode_node dht_direct_response_alert::response() const
2577 	{
2578 		if (m_response_size == 0) return bdecode_node();
2579 		char const* start = m_alloc.get().ptr(m_response_idx);
2580 		char const* end = start + m_response_size;
2581 		error_code ec;
2582 		bdecode_node ret;
2583 		bdecode(start, end, ret, ec);
2584 		TORRENT_ASSERT(!ec);
2585 		return ret;
2586 	}
2587 
picker_log_alert(aux::stack_allocator & alloc,torrent_handle const & h,tcp::endpoint const & ep,peer_id const & peer_id,picker_flags_t const flags,span<piece_block const> blocks)2588 	picker_log_alert::picker_log_alert(aux::stack_allocator& alloc, torrent_handle const& h
2589 		, tcp::endpoint const& ep, peer_id const& peer_id, picker_flags_t const flags
2590 		, span<piece_block const> blocks)
2591 		: peer_alert(alloc, h, ep, peer_id)
2592 		, picker_flags(flags)
2593 		, m_array_idx(alloc.copy_buffer({reinterpret_cast<char const*>(blocks.data())
2594 			, blocks.size() * int(sizeof(piece_block))}))
2595 		, m_num_blocks(int(blocks.size()))
2596 	{}
2597 
blocks() const2598 	std::vector<piece_block> picker_log_alert::blocks() const
2599 	{
2600 		// we need to copy this array to make sure the structures are properly
2601 		// aligned, not just to have a nice API
2602 		std::size_t const num_blocks = aux::numeric_cast<std::size_t>(m_num_blocks);
2603 		std::vector<piece_block> ret(num_blocks);
2604 
2605 		char const* start = m_alloc.get().ptr(m_array_idx);
2606 		std::memcpy(ret.data(), start, num_blocks * sizeof(piece_block));
2607 
2608 		return ret;
2609 	}
2610 
2611 	constexpr picker_flags_t picker_log_alert::partial_ratio;
2612 	constexpr picker_flags_t picker_log_alert::prioritize_partials;
2613 	constexpr picker_flags_t picker_log_alert::rarest_first_partials;
2614 	constexpr picker_flags_t picker_log_alert::rarest_first;
2615 	constexpr picker_flags_t picker_log_alert::reverse_rarest_first;
2616 	constexpr picker_flags_t picker_log_alert::suggested_pieces;
2617 	constexpr picker_flags_t picker_log_alert::prio_sequential_pieces;
2618 	constexpr picker_flags_t picker_log_alert::sequential_pieces;
2619 	constexpr picker_flags_t picker_log_alert::reverse_pieces;
2620 	constexpr picker_flags_t picker_log_alert::time_critical;
2621 	constexpr picker_flags_t picker_log_alert::random_pieces;
2622 	constexpr picker_flags_t picker_log_alert::prefer_contiguous;
2623 	constexpr picker_flags_t picker_log_alert::reverse_sequential;
2624 	constexpr picker_flags_t picker_log_alert::backup1;
2625 	constexpr picker_flags_t picker_log_alert::backup2;
2626 	constexpr picker_flags_t picker_log_alert::end_game;
2627 	constexpr picker_flags_t picker_log_alert::extent_affinity;
2628 
message() const2629 	std::string picker_log_alert::message() const
2630 	{
2631 #ifdef TORRENT_DISABLE_ALERT_MSG
2632 		return {};
2633 #else
2634 		static char const* const flag_names[] =
2635 		{
2636 			"partial_ratio ",
2637 			"prioritize_partials ",
2638 			"rarest_first_partials ",
2639 			"rarest_first ",
2640 			"reverse_rarest_first ",
2641 			"suggested_pieces ",
2642 			"prio_sequential_pieces ",
2643 			"sequential_pieces ",
2644 			"reverse_pieces ",
2645 			"time_critical ",
2646 			"random_pieces ",
2647 			"prefer_contiguous ",
2648 			"reverse_sequential ",
2649 			"backup1 ",
2650 			"backup2 ",
2651 			"end_game ",
2652 			"extent_affinity ",
2653 		};
2654 
2655 		std::string ret = peer_alert::message();
2656 
2657 		auto flags = static_cast<std::uint32_t>(picker_flags);
2658 		int idx = 0;
2659 		ret += " picker_log [ ";
2660 		for (; flags != 0; flags >>= 1, ++idx)
2661 		{
2662 			if ((flags & 1) == 0) continue;
2663 			ret += flag_names[idx];
2664 		}
2665 		ret += "] ";
2666 
2667 		std::vector<piece_block> b = blocks();
2668 
2669 		for (auto const& p : b)
2670 		{
2671 			char buf[50];
2672 			std::snprintf(buf, sizeof(buf), "(%d,%d) "
2673 				, static_cast<int>(p.piece_index), p.block_index);
2674 			ret += buf;
2675 		}
2676 		return ret;
2677 #endif
2678 	}
2679 
session_error_alert(aux::stack_allocator & alloc,error_code e,string_view error_str)2680 	session_error_alert::session_error_alert(aux::stack_allocator& alloc
2681 		, error_code e, string_view error_str)
2682 		: error(e)
2683 		, m_alloc(alloc)
2684 		, m_msg_idx(alloc.copy_buffer(error_str))
2685 	{}
2686 
message() const2687 	std::string session_error_alert::message() const
2688 	{
2689 #ifdef TORRENT_DISABLE_ALERT_MSG
2690 		return {};
2691 #else
2692 		char buf[400];
2693 		if (error)
2694 		{
2695 			std::snprintf(buf, sizeof(buf), "session error: (%d %s) %s"
2696 				, error.value(), convert_from_native(error.message()).c_str()
2697 				, m_alloc.get().ptr(m_msg_idx));
2698 		}
2699 		else
2700 		{
2701 			std::snprintf(buf, sizeof(buf), "session error: %s"
2702 				, m_alloc.get().ptr(m_msg_idx));
2703 		}
2704 		return buf;
2705 #endif
2706 	}
2707 
2708 namespace {
2709 
2710 	using nodes_slot = std::tuple<int, aux::allocation_slot, int, aux::allocation_slot>;
2711 
write_nodes(aux::stack_allocator & alloc,std::vector<std::pair<sha1_hash,udp::endpoint>> const & nodes)2712 	nodes_slot write_nodes(aux::stack_allocator& alloc
2713 		, std::vector<std::pair<sha1_hash, udp::endpoint>> const& nodes)
2714 	{
2715 		int v4_num_nodes = 0;
2716 		int v6_num_nodes = 0;
2717 
2718 		for (auto const& n : nodes)
2719 		{
2720 			if (is_v4(n.second))
2721 				v4_num_nodes++;
2722 			else
2723 				v6_num_nodes++;
2724 		}
2725 
2726 		aux::allocation_slot const v4_nodes_idx = alloc.allocate(v4_num_nodes * (20 + 6));
2727 		aux::allocation_slot const v6_nodes_idx = alloc.allocate(v6_num_nodes * (20 + 18));
2728 
2729 		char* v4_ptr = alloc.ptr(v4_nodes_idx);
2730 		char* v6_ptr = alloc.ptr(v6_nodes_idx);
2731 		for (auto const& n : nodes)
2732 		{
2733 			udp::endpoint const& endp = n.second;
2734 			if (is_v4(endp))
2735 			{
2736 				detail::write_string(n.first.to_string(), v4_ptr);
2737 				detail::write_endpoint(endp, v4_ptr);
2738 			}
2739 			else
2740 			{
2741 				detail::write_string(n.first.to_string(), v6_ptr);
2742 				detail::write_endpoint(endp, v6_ptr);
2743 			}
2744 		}
2745 
2746 		return nodes_slot{v4_num_nodes, v4_nodes_idx, v6_num_nodes, v6_nodes_idx};
2747 	}
2748 
read_nodes(aux::stack_allocator const & alloc,int const v4_num_nodes,aux::allocation_slot const v4_nodes_idx,int const v6_num_nodes,aux::allocation_slot const v6_nodes_idx)2749 	std::vector<std::pair<sha1_hash, udp::endpoint>> read_nodes(
2750 		aux::stack_allocator const& alloc
2751 		, int const v4_num_nodes, aux::allocation_slot const v4_nodes_idx
2752 		, int const v6_num_nodes, aux::allocation_slot const v6_nodes_idx)
2753 	{
2754 		aux::vector<std::pair<sha1_hash, udp::endpoint>> nodes;
2755 		nodes.reserve(v4_num_nodes + v6_num_nodes);
2756 
2757 		char const* v4_ptr = alloc.ptr(v4_nodes_idx);
2758 		for (int i = 0; i < v4_num_nodes; i++)
2759 		{
2760 			sha1_hash ih;
2761 			std::memcpy(ih.data(), v4_ptr, 20);
2762 			v4_ptr += 20;
2763 			nodes.emplace_back(ih, detail::read_v4_endpoint<udp::endpoint>(v4_ptr));
2764 		}
2765 		char const* v6_ptr = alloc.ptr(v6_nodes_idx);
2766 		for (int i = 0; i < v6_num_nodes; i++)
2767 		{
2768 			sha1_hash ih;
2769 			std::memcpy(ih.data(), v6_ptr, 20);
2770 			v6_ptr += 20;
2771 			nodes.emplace_back(ih, detail::read_v6_endpoint<udp::endpoint>(v6_ptr));
2772 		}
2773 
2774 		return std::move(nodes);
2775 	}
2776 	}
2777 
dht_live_nodes_alert(aux::stack_allocator & alloc,sha1_hash const & nid,std::vector<std::pair<sha1_hash,udp::endpoint>> const & nodes)2778 	dht_live_nodes_alert::dht_live_nodes_alert(aux::stack_allocator& alloc
2779 		, sha1_hash const& nid
2780 		, std::vector<std::pair<sha1_hash, udp::endpoint>> const& nodes)
2781 		: node_id(nid)
2782 		, m_alloc(alloc)
2783 	{
2784 		std::tie(m_v4_num_nodes, m_v4_nodes_idx, m_v6_num_nodes, m_v6_nodes_idx)
2785 			= write_nodes(alloc, nodes);
2786 	}
2787 
message() const2788 	std::string dht_live_nodes_alert::message() const
2789 	{
2790 #ifdef TORRENT_DISABLE_ALERT_MSG
2791 		return {};
2792 #else
2793 		char msg[200];
2794 		std::snprintf(msg, sizeof(msg), "dht live nodes for id: %s, nodes %d"
2795 			, aux::to_hex(node_id).c_str(), num_nodes());
2796 		return msg;
2797 #endif
2798 	}
2799 
num_nodes() const2800 	int dht_live_nodes_alert::num_nodes() const
2801 	{
2802 		return m_v4_num_nodes + m_v6_num_nodes;
2803 	}
2804 
nodes() const2805 	std::vector<std::pair<sha1_hash, udp::endpoint>> dht_live_nodes_alert::nodes() const
2806 	{
2807 		return read_nodes(m_alloc.get()
2808 			, m_v4_num_nodes, m_v4_nodes_idx
2809 			, m_v6_num_nodes, m_v6_nodes_idx);
2810 	}
2811 
session_stats_header_alert(aux::stack_allocator &)2812 	session_stats_header_alert::session_stats_header_alert(aux::stack_allocator&)
2813 	{}
2814 
message() const2815 	std::string session_stats_header_alert::message() const
2816 	{
2817 #ifdef TORRENT_DISABLE_ALERT_MSG
2818 		return {};
2819 #else
2820 		std::string stats_header = "session stats header: ";
2821 		std::vector<stats_metric> stats = session_stats_metrics();
2822 		std::sort(stats.begin(), stats.end()
2823 			, [] (stats_metric const& lhs, stats_metric const& rhs)
2824 			{ return lhs.value_index < rhs.value_index; });
2825 		bool first = true;
2826 		for (auto const& s : stats)
2827 		{
2828 			if (!first) stats_header += ", ";
2829 			stats_header += s.name;
2830 			first = false;
2831 		}
2832 
2833 		return stats_header;
2834 #endif
2835 	}
2836 
dht_sample_infohashes_alert(aux::stack_allocator & alloc,udp::endpoint const & endp,time_duration _interval,int _num,std::vector<sha1_hash> const & samples,std::vector<std::pair<sha1_hash,udp::endpoint>> const & nodes)2837 	dht_sample_infohashes_alert::dht_sample_infohashes_alert(aux::stack_allocator& alloc
2838 		, udp::endpoint const& endp
2839 		, time_duration _interval
2840 		, int _num
2841 		, std::vector<sha1_hash> const& samples
2842 		, std::vector<std::pair<sha1_hash, udp::endpoint>> const& nodes)
2843 		: endpoint(endp)
2844 		, interval(_interval)
2845 		, num_infohashes(_num)
2846 		, m_alloc(alloc)
2847 		, m_num_samples(aux::numeric_cast<int>(samples.size()))
2848 	{
2849 		m_samples_idx = alloc.allocate(m_num_samples * 20);
2850 
2851 		char *ptr = alloc.ptr(m_samples_idx);
2852 		std::memcpy(ptr, samples.data(), samples.size() * 20);
2853 
2854 		std::tie(m_v4_num_nodes, m_v4_nodes_idx, m_v6_num_nodes, m_v6_nodes_idx)
2855 			= write_nodes(alloc, nodes);
2856 	}
2857 
message() const2858 	std::string dht_sample_infohashes_alert::message() const
2859 	{
2860 #ifdef TORRENT_DISABLE_ALERT_MSG
2861 		return {};
2862 #else
2863 		char msg[200];
2864 		std::snprintf(msg, sizeof(msg)
2865 			, "incoming dht sample_infohashes reply from: %s, samples %d"
2866 			, print_endpoint(endpoint).c_str(), m_num_samples);
2867 		return msg;
2868 #endif
2869 	}
2870 
num_samples() const2871 	int dht_sample_infohashes_alert::num_samples() const
2872 	{
2873 		return m_num_samples;
2874 	}
2875 
samples() const2876 	std::vector<sha1_hash> dht_sample_infohashes_alert::samples() const
2877 	{
2878 		aux::vector<sha1_hash> samples;
2879 		samples.resize(m_num_samples);
2880 
2881 		char const* ptr = m_alloc.get().ptr(m_samples_idx);
2882 		std::memcpy(samples.data(), ptr, samples.size() * 20);
2883 
2884 		return std::move(samples);
2885 	}
2886 
num_nodes() const2887 	int dht_sample_infohashes_alert::num_nodes() const
2888 	{
2889 		return m_v4_num_nodes + m_v6_num_nodes;
2890 	}
2891 
nodes() const2892 	std::vector<std::pair<sha1_hash, udp::endpoint>> dht_sample_infohashes_alert::nodes() const
2893 	{
2894 		return read_nodes(m_alloc.get()
2895 			, m_v4_num_nodes, m_v4_nodes_idx
2896 			, m_v6_num_nodes, m_v6_nodes_idx);
2897 	}
2898 
block_uploaded_alert(aux::stack_allocator & alloc,torrent_handle h,tcp::endpoint const & ep,peer_id const & peer_id,int block_num,piece_index_t piece_num)2899 	block_uploaded_alert::block_uploaded_alert(aux::stack_allocator& alloc, torrent_handle h
2900 		, tcp::endpoint const& ep, peer_id const& peer_id, int block_num
2901 		, piece_index_t piece_num)
2902 		: peer_alert(alloc, h, ep, peer_id)
2903 		, block_index(block_num)
2904 		, piece_index(piece_num)
2905 	{
2906 		TORRENT_ASSERT(block_index >= 0 && piece_index >= piece_index_t{0});
2907 	}
2908 
message() const2909 	std::string block_uploaded_alert::message() const
2910 	{
2911 #ifdef TORRENT_DISABLE_ALERT_MSG
2912 		return {};
2913 #else
2914 		char ret[200];
2915 		snprintf(ret, sizeof(ret), "%s block uploaded to a peer (piece: %d block: %d)"
2916 			, peer_alert::message().c_str(), static_cast<int>(piece_index), block_index);
2917 		return ret;
2918 #endif
2919 	}
2920 
alerts_dropped_alert(aux::stack_allocator &,std::bitset<num_alert_types> const & dropped)2921 	alerts_dropped_alert::alerts_dropped_alert(aux::stack_allocator&
2922 		, std::bitset<num_alert_types> const& dropped)
2923 		: dropped_alerts(dropped)
2924 	{}
2925 
alert_name(int const alert_type)2926 	char const* alert_name(int const alert_type)
2927 	{
2928 		static std::array<char const*, num_alert_types> const names = {{
2929 #if TORRENT_ABI_VERSION == 1
2930 		"torrent", "peer", "tracker", "torrent_added",
2931 #else
2932 		"", "", "", "",
2933 #endif
2934 		"torrent_removed", "read_piece", "file_completed",
2935 		"file_renamed", "file_rename_failed", "performance",
2936 		"state_changed", "tracker_error", "tracker_warning",
2937 		"scrape_reply", "scrape_failed", "tracker_reply",
2938 		"dht_reply", "tracker_announce", "hash_failed",
2939 		"peer_ban", "peer_unsnubbed", "peer_snubbed",
2940 		"peer_error", "peer_connect", "peer_disconnected",
2941 		"invalid_request", "torrent_finished", "piece_finished",
2942 		"request_dropped", "block_timeout", "block_finished",
2943 		"block_downloading", "unwanted_block", "storage_moved",
2944 		"storage_moved_failed", "torrent_deleted",
2945 		"torrent_delete_failed", "save_resume_data",
2946 		"save_resume_data_failed", "torrent_paused",
2947 		"torrent_resumed", "torrent_checked", "url_seed",
2948 		"file_error", "metadata_failed", "metadata_received",
2949 		"udp_error", "external_ip", "listen_failed",
2950 		"listen_succeeded", "portmap_error", "portmap",
2951 		"portmap_log", "fastresume_rejected", "peer_blocked",
2952 		"dht_announce", "dht_get_peers", "stats",
2953 		"cache_flushed", "anonymous_mode", "lsd_peer",
2954 		"trackerid", "dht_bootstrap", "", "torrent_error",
2955 		"torrent_need_cert", "incoming_connection",
2956 		"add_torrent", "state_update",
2957 #if TORRENT_ABI_VERSION == 1
2958 		"mmap_cache",
2959 #else
2960 		"",
2961 #endif
2962 		"session_stats",
2963 #if TORRENT_ABI_VERSION == 1
2964 		"torrent_update",
2965 #else
2966 		"",
2967 #endif
2968 		"", "dht_error", "dht_immutable_item", "dht_mutable_item",
2969 		"dht_put", "i2p", "dht_outgoing_get_peers", "log",
2970 		"torrent_log", "peer_log", "lsd_error",
2971 		"dht_stats", "incoming_request", "dht_log",
2972 		"dht_pkt", "dht_get_peers_reply", "dht_direct_response",
2973 		"picker_log", "session_error", "dht_live_nodes",
2974 		"session_stats_header", "dht_sample_infohashes",
2975 		"block_uploaded", "alerts_dropped", "socks5"
2976 		}};
2977 
2978 		TORRENT_ASSERT(alert_type >= 0);
2979 		TORRENT_ASSERT(alert_type < num_alert_types);
2980 		return names[std::size_t(alert_type)];
2981 	}
2982 
message() const2983 	std::string alerts_dropped_alert::message() const
2984 	{
2985 #ifdef TORRENT_DISABLE_ALERT_MSG
2986 		return {};
2987 #else
2988 		std::string ret = "dropped alerts: ";
2989 
2990 		TORRENT_ASSERT(int(dropped_alerts.size()) == num_alert_types);
2991 		for (int idx = 0; idx < num_alert_types; ++idx)
2992 		{
2993 			if (!dropped_alerts.test(std::size_t(idx))) continue;
2994 			ret += alert_name(idx);
2995 			ret += ' ';
2996 		}
2997 
2998 		return ret;
2999 #endif
3000 	}
3001 
socks5_alert(aux::stack_allocator &,tcp::endpoint const & ep,operation_t operation,error_code const & ec)3002 	socks5_alert::socks5_alert(aux::stack_allocator&
3003 		, tcp::endpoint const& ep, operation_t operation, error_code const& ec)
3004 		: error(ec)
3005 		, op(operation)
3006 		, ip(ep)
3007 	{}
3008 
message() const3009 	std::string socks5_alert::message() const
3010 	{
3011 #ifdef TORRENT_DISABLE_ALERT_MSG
3012 		return {};
3013 #else
3014 		char buf[512];
3015 		std::snprintf(buf, sizeof(buf), "SOCKS5 error. op: %s ec: %s ep: %s"
3016 			, operation_name(op), error.message().c_str(), print_endpoint(ip).c_str());
3017 		return buf;
3018 #endif
3019 	}
3020 
3021 	// this will no longer be necessary in C++17
3022 	constexpr alert_category_t torrent_removed_alert::static_category;
3023 	constexpr alert_category_t read_piece_alert::static_category;
3024 	constexpr alert_category_t file_completed_alert::static_category;
3025 	constexpr alert_category_t file_renamed_alert::static_category;
3026 	constexpr alert_category_t file_rename_failed_alert::static_category;
3027 	constexpr alert_category_t performance_alert::static_category;
3028 	constexpr alert_category_t state_changed_alert::static_category;
3029 	constexpr alert_category_t tracker_error_alert::static_category;
3030 	constexpr alert_category_t tracker_warning_alert::static_category;
3031 	constexpr alert_category_t scrape_reply_alert::static_category;
3032 	constexpr alert_category_t scrape_failed_alert::static_category;
3033 	constexpr alert_category_t tracker_reply_alert::static_category;
3034 	constexpr alert_category_t dht_reply_alert::static_category;
3035 	constexpr alert_category_t tracker_announce_alert::static_category;
3036 	constexpr alert_category_t hash_failed_alert::static_category;
3037 	constexpr alert_category_t peer_ban_alert::static_category;
3038 	constexpr alert_category_t peer_unsnubbed_alert::static_category;
3039 	constexpr alert_category_t peer_snubbed_alert::static_category;
3040 	constexpr alert_category_t peer_error_alert::static_category;
3041 	constexpr alert_category_t peer_connect_alert::static_category;
3042 	constexpr alert_category_t peer_disconnected_alert::static_category;
3043 	constexpr alert_category_t invalid_request_alert::static_category;
3044 	constexpr alert_category_t torrent_finished_alert::static_category;
3045 	constexpr alert_category_t piece_finished_alert::static_category;
3046 	constexpr alert_category_t request_dropped_alert::static_category;
3047 	constexpr alert_category_t block_timeout_alert::static_category;
3048 	constexpr alert_category_t block_finished_alert::static_category;
3049 	constexpr alert_category_t block_downloading_alert::static_category;
3050 	constexpr alert_category_t unwanted_block_alert::static_category;
3051 	constexpr alert_category_t storage_moved_alert::static_category;
3052 	constexpr alert_category_t storage_moved_failed_alert::static_category;
3053 	constexpr alert_category_t torrent_deleted_alert::static_category;
3054 	constexpr alert_category_t torrent_delete_failed_alert::static_category;
3055 	constexpr alert_category_t save_resume_data_alert::static_category;
3056 	constexpr alert_category_t save_resume_data_failed_alert::static_category;
3057 	constexpr alert_category_t torrent_paused_alert::static_category;
3058 	constexpr alert_category_t torrent_resumed_alert::static_category;
3059 	constexpr alert_category_t torrent_checked_alert::static_category;
3060 	constexpr alert_category_t url_seed_alert::static_category;
3061 	constexpr alert_category_t file_error_alert::static_category;
3062 	constexpr alert_category_t metadata_failed_alert::static_category;
3063 	constexpr alert_category_t metadata_received_alert::static_category;
3064 	constexpr alert_category_t udp_error_alert::static_category;
3065 	constexpr alert_category_t external_ip_alert::static_category;
3066 	constexpr alert_category_t listen_failed_alert::static_category;
3067 	constexpr alert_category_t listen_succeeded_alert::static_category;
3068 	constexpr alert_category_t portmap_error_alert::static_category;
3069 	constexpr alert_category_t portmap_alert::static_category;
3070 	constexpr alert_category_t portmap_log_alert::static_category;
3071 	constexpr alert_category_t fastresume_rejected_alert::static_category;
3072 	constexpr alert_category_t peer_blocked_alert::static_category;
3073 	constexpr alert_category_t dht_announce_alert::static_category;
3074 	constexpr alert_category_t dht_get_peers_alert::static_category;
3075 	constexpr alert_category_t stats_alert::static_category;
3076 	constexpr alert_category_t cache_flushed_alert::static_category;
3077 	constexpr alert_category_t lsd_peer_alert::static_category;
3078 	constexpr alert_category_t trackerid_alert::static_category;
3079 	constexpr alert_category_t dht_bootstrap_alert::static_category;
3080 	constexpr alert_category_t torrent_error_alert::static_category;
3081 	constexpr alert_category_t torrent_need_cert_alert::static_category;
3082 	constexpr alert_category_t incoming_connection_alert::static_category;
3083 	constexpr alert_category_t add_torrent_alert::static_category;
3084 	constexpr alert_category_t state_update_alert::static_category;
3085 	constexpr alert_category_t session_stats_alert::static_category;
3086 	constexpr alert_category_t dht_error_alert::static_category;
3087 	constexpr alert_category_t dht_immutable_item_alert::static_category;
3088 	constexpr alert_category_t dht_mutable_item_alert::static_category;
3089 	constexpr alert_category_t dht_put_alert::static_category;
3090 	constexpr alert_category_t i2p_alert::static_category;
3091 	constexpr alert_category_t dht_outgoing_get_peers_alert::static_category;
3092 	constexpr alert_category_t log_alert::static_category;
3093 	constexpr alert_category_t torrent_log_alert::static_category;
3094 	constexpr alert_category_t peer_log_alert::static_category;
3095 	constexpr alert_category_t lsd_error_alert::static_category;
3096 	constexpr alert_category_t dht_stats_alert::static_category;
3097 	constexpr alert_category_t incoming_request_alert::static_category;
3098 	constexpr alert_category_t dht_log_alert::static_category;
3099 	constexpr alert_category_t dht_pkt_alert::static_category;
3100 	constexpr alert_category_t dht_get_peers_reply_alert::static_category;
3101 	constexpr alert_category_t dht_direct_response_alert::static_category;
3102 	constexpr alert_category_t picker_log_alert::static_category;
3103 	constexpr alert_category_t session_error_alert::static_category;
3104 	constexpr alert_category_t dht_live_nodes_alert::static_category;
3105 	constexpr alert_category_t session_stats_header_alert::static_category;
3106 	constexpr alert_category_t dht_sample_infohashes_alert::static_category;
3107 	constexpr alert_category_t block_uploaded_alert::static_category;
3108 	constexpr alert_category_t alerts_dropped_alert::static_category;
3109 	constexpr alert_category_t socks5_alert::static_category;
3110 #if TORRENT_ABI_VERSION == 1
3111 	constexpr alert_category_t anonymous_mode_alert::static_category;
3112 	constexpr alert_category_t mmap_cache_alert::static_category;
3113 	constexpr alert_category_t torrent_added_alert::static_category;
3114 	constexpr alert_category_t torrent_update_alert::static_category;
3115 #endif
3116 
3117 } // namespace libtorrent
3118