lt_rs/alerts/
mod.rs

1use crate::{
2    alerts::{peer_alert::PeerAlert, tracker_alert::TrackerAlert},
3    ffi::ffi::{self},
4};
5
6pub mod implementations;
7pub mod operation;
8pub mod peer_alert;
9pub mod performance_warning;
10pub mod protocol_version;
11pub mod torrent_alert;
12pub mod torrent_state;
13pub mod tracker_alert;
14pub mod types;
15
16pub use torrent_alert::TorrentAlert;
17pub use torrent_state::TorrentState;
18
19use peer_alert::PeerAlertRaw;
20use torrent_alert::TorrentAlertRaw;
21use tracker_alert::TrackerAlertRaw;
22
23macro_rules! define_alerts {
24[
25    $(
26        $variant:ident = $value:expr
27    ),* $(,)?
28] => {
29    paste::paste! {
30        $(
31            pub struct [<$variant Alert>] (pub(super) *mut ffi::[<$variant:snake _alert>]);
32            impl [<$variant Alert>] {
33
34            }
35        )*
36
37        // Sadly this macro does not work with CXX, so we have to manually
38        // copy and paste the types...
39        // macro_rules! define_alert_enum {
40            // () => {
41                // enum AlertType {
42                    // $(
43                        // $variant = $value,
44                    // )*
45
46                    // Unknown,
47                // }
48            // };
49        // }
50        //};
51    }
52}
53}
54
55define_alerts![
56    //TorrentAdded = 3,
57    TorrentRemoved = 4,
58    ReadPiece = 5,
59    FileCompleted = 6,
60    FileRenamed = 7,
61    FileRenameFailed = 8,
62    Performance = 9,
63    StateChanged = 10,
64    TrackerError = 11,
65    TrackerWarning = 12,
66    ScrapeReply = 13,
67    ScrapeFailed = 14,
68    TrackerReply = 15,
69    DhtReply = 16,
70    TrackerAnnounce = 17,
71    HashFailed = 18,
72    PeerBan = 19,
73    PeerUnsnubbed = 20,
74    PeerSnubbed = 21,
75    PeerError = 22,
76    PeerConnect = 23,
77    PeerDisconnected = 24,
78    InvalidRequest = 25,
79    TorrentFinished = 26,
80    PieceFinished = 27,
81    RequestDropped = 28,
82    BlockTimeout = 29,
83    BlockFinished = 30,
84    BlockDownloading = 31,
85    UnwantedBlock = 32,
86    StorageMoved = 33,
87    StorageMovedFailed = 34,
88    TorrentDeleted = 35,
89    TorrentDeleteFailed = 36,
90    SaveResumeData = 37,
91    SaveResumeDataFailed = 38,
92    TorrentPaused = 39,
93    TorrentResumed = 40,
94    TorrentChecked = 41,
95    UrlSeed = 42,
96    FileError = 43,
97    MetadataFailed = 44,
98    MetadataReceived = 45,
99    UdpError = 46,
100    ExternalIp = 47,
101    ListenFailed = 48,
102    ListenSucceeded = 49,
103    PortmapError = 50,
104    Portmap = 51,
105    PortmapLog = 52,
106    FastresumeRejected = 53,
107    PeerBlocked = 54,
108    DhtAnnounce = 55,
109    DhtGetPeers = 56,
110    // Stats = 57,
111    CacheFlushed = 58,
112    // AnonymousMode = 59,
113    LsdPeer = 60,
114    Trackerid = 61,
115    DhtBootstrap = 62,
116    TorrentError = 64,
117    TorrentNeedCert = 65,
118    IncomingConnection = 66,
119    AddTorrent = 67,
120    StateUpdate = 68,
121    // MmapCache = 69,
122    SessionStats = 70,
123    DhtError = 73,
124    DhtImmutableItem = 74,
125    DhtMutableItem = 75,
126    DhtPut = 76,
127    I2p = 77,
128    DhtOutgoingGetPeers = 78,
129    Log = 79,
130    TorrentLog = 80,
131    PeerLog = 81,
132    LsdError = 82,
133    DhtStats = 83,
134    IncomingRequest = 84,
135    DhtLog = 85,
136    DhtPkt = 86,
137    DhtGetPeersReply = 87,
138    DhtDirectResponse = 88,
139    PickerLog = 89,
140    SessionError = 90,
141    DhtLiveNodes = 91,
142    SessionStatsHeader = 92,
143    DhtSampleInfohashes = 93,
144    BlockUploaded = 94,
145    AlertsDropped = 95,
146    Socks5 = 96,
147    FilePrio = 97,
148    OversizedFile = 98,
149    TorrentConflict = 99,
150    PeerInfo = 100,
151    FileProgress = 101,
152    PieceInfo = 102,
153    PieceAvailability = 103,
154    TrackerList = 104,
155];
156
157type UserData = String;
158
159/// Struct to hold information about a single DHT routing table bucket
160struct DhtRoutingBucket {
161    /// Total number of nodes in the routing table
162    num_nodes: i32,
163
164    /// Total number of replacement nodes in the routing table
165    num_replacements: i32,
166
167    /// Number of seconds since last activity
168    last_active: i32,
169}
170
171/// The [`LtSession::pop_alerts()`] function on session is the main interface for retrieving alerts
172/// (warnings, messages and errors from libtorrent).
173/// If no alerts have been posted by libtorrent [`LtSession::pop_alerts()`] will return an empty list.
174///
175/// By default, only errors are reported. [`SettingsPack::set_alert_mask()`] can be used to specify
176/// which kinds of events should be reported. The alert mask is a combination of the [`AlertCategory`] flags.
177///
178/// Every alert belongs to one or more category. There is a cost associated with posting alerts.
179/// Only alerts that belong to an enabled category are posted. Setting the alert bitmask to 0 will disable all alerts
180/// (except those that are non-discardable).
181/// Alerts that are responses to API calls such as save_resume_data() and post_session_stats() are //TODO function reference
182/// non-discardable and will be posted even if their category is disabled.
183///
184/// There are other alert base classes that some alerts derive from, all the alerts that are
185/// generated for a specific torrent are derived from [`TorrentAlert`],
186/// and tracker events derive from [`TrackerAlert`].
187///
188/// Alerts returned by [`LtSession::pop_alerts()`] are only valid until the next call to [`LtSession::pop_alerts()`].
189/// You may not copy an alert object to access it after the next call to [`LtSession::pop_alerts()`].
190/// Internal members of alerts also become invalid once [`LtSession::pop_alerts()`] is called again.
191// ! Alerts should only exist inside sessions so lifetimes are
192// ! easier to manage
193pub enum Alert {
194    NotImplemented,
195    /// This alert is posted when there is an error on a UDP socket. The
196    /// UDP sockets are used for all uTP, DHT and UDP tracker traffic. They are
197    /// global to the session.
198    ///
199    /// ## Alert Category
200    /// [`AlertCategory::Error`]
201    /// ## Alert Priority
202    /// [`AlertPriority::Normal`]
203    UdpError(UdpErrorAlert),
204    /// Whenever libtorrent learns about the machines external IP, this alert is
205    /// generated. The external IP address can be acquired from the tracker (if it
206    /// supports that) or from peers that supports the extension protocol.
207    /// The address can be accessed through the ``external_address`` member.
208    ///
209    /// ## Alert Category
210    /// [`AlertCategory::Status`]
211    /// ## Alert Priority
212    /// [`AlertPriority::Normal`]
213    ExternalIp(ExternalIpAlert),
214    /// This alert is generated when none of the ports, given in the port range, to
215    /// session can be opened for listening. The ``listen_interface`` member is the
216    /// interface that failed, ``error`` is the error code describing the failure.
217    ///
218    /// In the case an endpoint was created before generating the alert, it is
219    /// represented by ``address`` and ``port``. The combinations of socket type
220    /// and operation in which such address and port are not valid are:
221    /// accept  - i2p
222    /// accept  - socks5
223    /// enum_if - tcp
224    ///
225    /// libtorrent may sometimes try to listen on port 0, if all other ports failed.
226    /// Port 0 asks the operating system to pick a port that's free). If that fails
227    /// you may see a [`Alert::ListenFailed`] with port 0 even if you didn't ask to
228    /// listen on it.
229    ///
230    /// ## Alert Category
231    /// [`AlertCategory::Status`] | [`AlertCategory::Error`]
232    /// ## Alert Priority
233    /// [`AlertPriority::Critical`]
234    ListenFailed(ListenFailedAlert),
235    /// This alert is posted when the listen port succeeds to be opened on a
236    /// particular interface. ``address`` and ``port`` is the endpoint that
237    /// successfully was opened for listening.
238    ///
239    /// ## Alert Category
240    /// [`AlertCategory::Status`]
241    /// ## Alert Priority
242    /// [`AlertPriority::Critical`]
243    ListenSucceeded(ListenSucceededAlert),
244    /// This alert is generated when a NAT router was successfully found but some
245    /// part of the port mapping request failed. It contains a text message that
246    /// may help the user figure out what is wrong. This alert is not generated in
247    /// case it appears the client is not running on a NAT:ed network or if it
248    /// appears there is no NAT router that can be remote controlled to add port
249    /// mappings.
250    ///
251    /// ## Alert Category
252    /// [`AlertCategory::PortMapping`] | [`AlertCategory::Error`]
253    /// ## Alert Priority
254    /// [`AlertPriority::Normal`]
255    PortmapError(PortmapErrorAlert),
256    /// This alert is generated when a NAT router was successfully found and
257    /// a port was successfully mapped on it. On a NAT:ed network with a NAT-PMP
258    /// capable router, this is typically generated once when mapping the TCP
259    /// port and, if DHT is enabled, when the UDP port is mapped.
260    ///
261    /// ## Alert Category
262    /// [`AlertCategory::PortMapping`]
263    /// ## Alert Priority
264    /// [`AlertPriority::Normal`]
265    Portmap(PortmapAlert),
266    /// This alert is generated to log informational events related to either
267    /// UPnP or NAT-PMP. They contain a log line and the type (0 = NAT-PMP
268    /// and 1 = UPnP). Displaying these messages to an end user is only useful
269    /// for debugging the UPnP or NAT-PMP implementation. This alert is only
270    /// posted if the alert_category::port_mapping_log flag is enabled in
271    /// the alert mask.
272    ///
273    /// ## Alert Category
274    /// [`AlertCategory::PortMappingLog`]
275    /// ## Alert Priority
276    /// [`AlertPriority::Normal`]
277    PortmapLog(PortmapLogAlert),
278    /// This alert is generated when a DHT node announces to an info-hash on our
279    /// DHT node.
280    ///
281    /// ## Alert Category
282    /// [`AlertCategory::Dht`]
283    /// ## Alert Priority
284    /// [`AlertPriority::Normal`]
285    DhtAnnounce(DhtAnnounceAlert),
286    /// This alert is generated when a DHT node sends a ``get_peers`` message to
287    /// our DHT node.
288    ///
289    /// ## Alert Category
290    /// [`AlertCategory::Dht`]
291    /// ## Alert Priority
292    /// [`AlertPriority::Normal`]
293    DhtGetPeers(DhtGetPeersAlert),
294    /// This alert is posted when the initial DHT bootstrap is done.
295    ///
296    /// ## Alert Category
297    /// [`AlertCategory::Dht`]
298    /// ## Alert Priority
299    /// [`AlertPriority::Normal`]
300    DhtBootstrap(DhtBootstrapAlert),
301    /// The incoming connection alert is posted every time we successfully accept
302    /// an incoming connection, through any mean. The most straight-forward ways
303    /// of accepting incoming connections are through the TCP listen socket and
304    /// the UDP listen socket for uTP sockets. However, connections may also be
305    /// accepted through a Socks5 or i2p listen socket, or via an SSL listen
306    /// socket.
307    ///
308    /// ## Alert Category
309    /// [`AlertCategory::Status`]
310    /// ## Alert Priority
311    /// [`AlertPriority::Peer`]
312    IncomingConnection(IncomingConnectionAlert),
313    /// This alert is only posted when requested by the user, by calling [`LtSession::post_torrent_updates()`] on the session.
314    /// It contains the torrent status of all torrents that changed since last time this message was posted.
315    /// Its category is [`AlertCategory::Status`], but it's not subject to filtering, since it's only manually posted anyway.
316    ///
317    /// ## Alert Category
318    /// [`AlertCategory::Status`]
319    /// ## Alert Priority
320    /// [`AlertPriority::High`]
321    StateUpdate(StateUpdateAlert),
322    /// The [`Alert::SessionStats`] is posted when the user requests session statistics by
323    /// calling post_session_stats() on the session object. This alert does not
324    /// have a category, since it's only posted in response to an API call. It
325    /// is not subject to the alert_mask filter.
326    ///
327    /// the ``message()`` member function returns a string representation of the values that
328    /// properly match the line returned in ``session_stats_header_alert::message()``.
329    ///
330    /// this specific output is parsed by tools/parse_session_stats.py
331    /// if this is changed, that parser should also be changed
332    ///
333    /// ## Alert Category
334    /// ## Alert Priority
335    /// [`AlertPriority::Critical`]
336    // Erm what the sigma? Why is there no category?
337    // I don't even think this is actually used but only the alert prio
338    // is removed with conditional TORRENT_ABI_VERSION ¯\_(ツ)_/¯
339    SessionStats(SessionStatsAlert),
340    /// Posted when something fails in the DHT. This is not necessarily a fatal
341    /// error, but it could prevent proper operation
342    ///
343    /// ## Alert Category
344    /// [`AlertCategory::Dht`] [`AlertCategory::Error`]
345    /// ## Alert Priority
346    /// [`AlertPriority::Normal`]
347    DhtError(DhtErrorAlert),
348    /// This alert is posted as a response to a call to [`LtSession::get_item()`],
349    /// specifically the overload for looking up immutable items in the DHT.
350    ///
351    /// ## Alert Category
352    /// [`AlertCategory::Dht`]
353    /// ## Alert Priority
354    /// [`AlertPriority::Critical`]
355    DhtImmutableItem(DhtImmutableItemAlert),
356    /// This alert is posted as a response to a call to [`LtSession::get_item()`],
357    /// specifically the overload for looking up mutable items in the DHT.
358    ///
359    /// ## Alert Category
360    /// [`AlertCategory::Dht`]
361    /// ## Alert Priority
362    /// [`AlertPriority::Critical`]
363    DhtMutableItem(DhtMutableItemAlert),
364    /// This is posted when a DHT put operation completes. This is useful if the
365    /// client is waiting for a put to complete before shutting down for instance.
366    ///
367    /// ## Alert Category
368    /// [`AlertCategory::Dht`]
369    /// ## Alert Priority
370    /// [`AlertPriority::Normal`]
371    DhtPut(DhtPutAlert),
372    /// This alert is used to report errors in the i2p SAM connection
373    ///
374    /// ## Alert Category
375    /// [`AlertCategory::Error`]
376    /// ## Alert Priority
377    /// [`AlertPriority::Normal`]
378    I2p(I2pAlert),
379    /// This alert is generated when we send a get_peers request
380    ///
381    /// ## Alert Category
382    /// [`AlertCategory::Dht`]
383    /// ## Alert Priority
384    /// [`AlertPriority::Normal`]
385    DhtOutgoingGetPeers(DhtOutgoingGetPeersAlert),
386    /// This alert is posted by some session wide event. Its main purpose is
387    /// trouble shooting and debugging. It's not enabled by the default alert
388    /// mask and is enabled by the [`AlertCategory::SessionLog`] bit.
389    /// Furthermore, it's by default disabled as a build configuration.
390    ///
391    /// ## Alert Category
392    /// [`AlertCategory::SessionLog`]
393    /// ## Alert Priority
394    /// [`AlertPriority::Normal`]
395    Log(LogAlert),
396    /// Posted if the local service discovery socket fails to start properly.
397    ///
398    /// ## Alert Category
399    /// [`AlertCategory::Error`]
400    /// ## Alert Priority
401    /// [`AlertPriority::Normal`]
402    LsdError(LsdErrorAlert),
403    /// Contains current DHT state. Posted in response to [`LtSession::post_dht_stats()`].
404    ///
405    /// ## Alert Category
406    /// ## Alert Priority
407    /// [`AlertPriority::Normal`]
408    // No category, no idea why ¯\_(ツ)_/¯
409    DhtStats(DhtStatsAlert),
410    /// Debug logging of the DHT when [`AlertCategory::DhtLog`] is set in the alert
411    /// mask.
412    ///
413    /// ## Alert Category
414    /// [`AlertCategory::DhtLog`]
415    /// ## Alert Priority
416    /// [`AlertPriority::Normal`]
417    DhtLog(DhtLogAlert),
418    /// This alert is posted every time a DHT message is sent or received. It is
419    /// only posted if the [`AlertCategory::DhtLog`] alert category is
420    /// enabled. It contains a verbatim copy of the message.
421    ///
422    /// ## Alert Category
423    /// [`AlertCategory::DhtLog`]
424    /// ## Alert Priority
425    /// [`AlertPriority::Normal`]
426    DhtPkt(DhtPktAlert),
427    /// Posted when we receive a response to a DHT get_peers request.
428    ///
429    /// ## Alert Category
430    /// [`AlertCategory::DhtOperation`]
431    /// ## Alert Priority
432    /// [`AlertPriority::Normal`]
433    DhtGetPeersReply(DhtGetPeersReplyAlert),
434    /// This is posted exactly once for every call to session_handle::dht_direct_request.
435    /// If the request failed, response() will return a default constructed bdecode_node.
436    ///
437    /// ## Alert Category
438    /// [`AlertCategory::DhtOperation`]
439    /// ## Alert Priority
440    /// [`AlertPriority::Normal`]
441    DhtDirectResponse(DhtDirectResponseAlert),
442    /// This alert is posted when the session encounters a serious error,
443    /// potentially fatal
444    ///
445    /// ## Alert Category
446    /// [`AlertCategory::Error`]
447    /// ## Alert Priority
448    /// [`AlertPriority::Normal`]
449    SessionError(SessionErrorAlert),
450    /// Posted in response to a call to [`LtSession::dht_live_nodes()`]. It contains the
451    /// live nodes from the DHT routing table of one of the DHT nodes running
452    /// locally.
453    ///
454    /// ## Alert Category
455    /// [`AlertCategory::Dht`]
456    /// ## Alert Priority
457    /// [`AlertPriority::Normal`]
458    DhtLiveNodes(DhtLiveNodesAlert),
459    /// The session_stats_header alert is posted the first time
460    /// post_session_stats() is called
461    ///
462    /// the ``message()`` member function returns a string representation of the
463    /// header that properly match the stats values string returned in
464    /// ``session_stats_alert::message()``.
465    ///
466    /// ## Alert Category
467    /// ## Alert Priority
468    /// [`AlertPriority::Normal`]
469    SessionStatsHeader(SessionStatsHeaderAlert),
470    /// Posted as a response to a call to [`LtSession::dht_sample_infohashes()`] with
471    /// the information from the DHT response message.
472    ///
473    /// ## Alert Category
474    /// [`AlertCategory::DhtOperation`]
475    /// ## Alert Priority
476    /// [`AlertPriority::Normal`]
477    DhtSampleInfohashes(DhtSampleInfohashesAlert),
478    /// This alert is posted to indicate to the client that some alerts were
479    /// dropped. Dropped meaning that the alert failed to be delivered to the
480    /// client. The most common cause of such failure is that the internal alert
481    /// queue grew too big (controlled by alert_queue_size).
482    ///
483    /// ## Alert Category
484    /// [`AlertCategory::Error`]
485    /// ## Alert Priority
486    /// [`AlertPriority::Meta`]
487    AlertsDropped(AlertsDroppedAlert),
488    /// This alert is posted with SOCKS5 related errors, when a SOCKS5 proxy is
489    /// configured. It's enabled with the AlertCategory::Error alert category.
490    ///
491    /// ## Alert Category
492    /// [`AlertCategory::Error`]
493    /// ## Alert Priority
494    /// [`AlertPriority::Normal`]
495    Socks5(Socks5Alert),
496
497    /// This is a base variant for alerts that are associated with a specific torrent. It contains a handle to the torrent.
498    ///
499    /// Note that by the time the client receives a TorrentAlert, its handle member may be invalid.
500    TorrentAlert(TorrentAlert),
501}
502
503macro_rules! type_match_int {
504    {
505        $value:ident,
506        $(
507            $name:ident : [$first:ident $(, $rest:ident)*]
508        ),* $(,)?
509    } => {
510        match $value.type_ {
511            $(
512                ffi::AlertType::$name => {
513                    type_match_int!(@wrap $name, $value; $first $(, $rest)*)
514                }
515            )*
516            ffi::AlertType::Unknown => Alert::NotImplemented,
517            _ => Alert::NotImplemented,
518        }
519    };
520
521    (@wrap $name:ident, $value:ident; $wrapper:ident, $next:ident $(, $rest:ident)*) => {
522        $wrapper::$next(
523            type_match_int!(@wrap $name, $value; $next $(, $rest)*)
524        )
525    };
526
527    (@wrap $name:ident, $value:ident; $wrapper:ident) => {
528        $wrapper::$name(
529            paste::paste! {
530                [<$name Alert>]($value.alert.cast())
531            }
532        )
533    };
534}
535
536macro_rules! type_match {
537    {
538        $(
539            $name:ident : [ $( $rest:ident ),* ]
540        ),* $(,)?
541    } => {
542        impl From<ffi::CastAlertRaw> for Alert {
543            fn from(value: ffi::CastAlertRaw) -> Self {
544                type_match_int! {
545                    value,
546                    $(
547                        $name: [Alert $(, $rest)*],
548                    )*
549                }
550            }
551        }
552        paste::paste! {
553            $(
554                impl [<$name Alert>] {
555                    $(
556                        fn [<as_ $rest:snake>]<'a>(&'a self) -> [<$rest Raw>]<'a> {
557                            [<$rest Raw>]::new(self.0.cast())
558                        }
559                    )*
560                }
561            )*
562        }
563    };
564}
565
566type_match! {
567    TorrentRemoved: [TorrentAlert],
568    ReadPiece: [TorrentAlert],
569    FileCompleted: [TorrentAlert],
570    FileRenamed: [TorrentAlert],
571    FileRenameFailed: [TorrentAlert],
572    Performance: [TorrentAlert],
573    StateChanged: [TorrentAlert],
574    TrackerError: [TorrentAlert, TrackerAlert],
575    TrackerWarning: [TorrentAlert, TrackerAlert],
576    ScrapeReply: [TorrentAlert, TrackerAlert],
577    ScrapeFailed: [TorrentAlert, TrackerAlert],
578    TrackerReply: [TorrentAlert, TrackerAlert],
579    DhtReply: [TorrentAlert, TrackerAlert],
580    TrackerAnnounce: [TorrentAlert, TrackerAlert],
581    HashFailed: [TorrentAlert],
582    PeerBan: [TorrentAlert, PeerAlert],
583    PeerUnsnubbed: [TorrentAlert, PeerAlert],
584    PeerSnubbed: [TorrentAlert, PeerAlert],
585    PeerError: [TorrentAlert, PeerAlert],
586    PeerConnect: [TorrentAlert, PeerAlert],
587    PeerDisconnected: [TorrentAlert, PeerAlert],
588    InvalidRequest: [TorrentAlert, PeerAlert],
589    TorrentFinished: [TorrentAlert],
590    PieceFinished: [TorrentAlert],
591    RequestDropped: [TorrentAlert, PeerAlert],
592    BlockTimeout: [TorrentAlert, PeerAlert],
593    BlockFinished: [TorrentAlert, PeerAlert],
594    BlockDownloading: [TorrentAlert, PeerAlert],
595    UnwantedBlock: [TorrentAlert, PeerAlert],
596    StorageMoved: [TorrentAlert],
597    StorageMovedFailed: [TorrentAlert],
598    TorrentDeleted: [TorrentAlert],
599    TorrentDeleteFailed: [TorrentAlert],
600    SaveResumeData: [TorrentAlert],
601    SaveResumeDataFailed: [TorrentAlert],
602    TorrentPaused: [TorrentAlert],
603    TorrentResumed: [TorrentAlert],
604    TorrentChecked: [TorrentAlert],
605    UrlSeed: [TorrentAlert],
606    FileError: [TorrentAlert],
607    MetadataFailed: [TorrentAlert],
608    MetadataReceived: [TorrentAlert],
609    UdpError: [],
610    ExternalIp: [],
611    ListenFailed: [],
612    ListenSucceeded: [],
613    PortmapError: [],
614    Portmap: [],
615    PortmapLog: [],
616    FastresumeRejected: [TorrentAlert],
617    PeerBlocked: [TorrentAlert, PeerAlert],
618    DhtAnnounce: [],
619    DhtGetPeers: [],
620    CacheFlushed: [TorrentAlert],
621    LsdPeer: [TorrentAlert, PeerAlert],
622    Trackerid: [TorrentAlert, TrackerAlert],
623    DhtBootstrap: [],
624    TorrentError: [TorrentAlert],
625    TorrentNeedCert: [TorrentAlert],
626    IncomingConnection: [],
627    AddTorrent: [TorrentAlert],
628    StateUpdate: [],
629    SessionStats: [],
630    DhtError: [],
631    DhtImmutableItem: [],
632    DhtMutableItem: [],
633    DhtPut: [],
634    I2p: [],
635    DhtOutgoingGetPeers: [],
636    Log: [],
637    TorrentLog: [TorrentAlert],
638    PeerLog: [TorrentAlert, PeerAlert],
639    LsdError: [],
640    DhtStats: [],
641    IncomingRequest: [TorrentAlert, PeerAlert],
642    DhtLog: [],
643    DhtPkt: [],
644    DhtGetPeersReply: [],
645    DhtDirectResponse: [],
646    PickerLog: [TorrentAlert, PeerAlert],
647    SessionError: [],
648    DhtLiveNodes: [],
649    SessionStatsHeader: [],
650    DhtSampleInfohashes: [],
651    BlockUploaded: [TorrentAlert, PeerAlert],
652    AlertsDropped: [],
653    Socks5: [],
654    FilePrio: [TorrentAlert],
655    OversizedFile: [TorrentAlert],
656    TorrentConflict: [TorrentAlert],
657    PeerInfo: [TorrentAlert],
658    FileProgress: [TorrentAlert],
659    PieceInfo: [TorrentAlert],
660    PieceAvailability: [TorrentAlert],
661    TrackerList: [TorrentAlert],
662}
663
664impl Alert {
665    // pub fn category(&self) -> AlertCategory {
666    //     match self {
667    //         Alert::TorrentAlert(alert) => match alert {
668    //             TorrentAlert::TorrentRemoved(_) => AlertCategory::Status,
669    //             TorrentAlert::ReadPiece(_) => AlertCategory::Storage,
670    //             TorrentAlert::FileCompleted(_) => AlertCategory::FileProgress,
671    //             TorrentAlert::FileRenamed(_) => AlertCategory::Storage,
672    //             TorrentAlert::FileRenameFailed(_) => AlertCategory::Storage,
673    //             TorrentAlert::Performance(_) => AlertCategory::PerformanceWarning,
674    //             TorrentAlert::StateChanged(_) => AlertCategory::Status,
675    //             TorrentAlert::HashFailed(_) => AlertCategory::Status,
676
677    //             TorrentAlert::AddTorrent(_) => AlertCategory::Status,
678    //             TorrentAlert::TorrentFinished(_) => AlertCategory::Status,
679    //             TorrentAlert::SaveResumeData(_) => AlertCategory::Storage,
680    //             TorrentAlert::SaveResumeDataFailed(_) => {
681    //                 AlertCategory::Storage | AlertCategory::Error
682    //             }
683
684    //             TorrentAlert::PeerAlert(alert) => match alert {
685    //                 PeerAlert::PeerBan(_) => AlertCategory::Peer,
686    //             },
687    //             TorrentAlert::TrackerAlert(alert) => match alert {
688    //                 TrackerAlert::TrackerError(_) => AlertCategory::Tracker | AlertCategory::Error,
689    //                 TrackerAlert::TrackerWarning(_) => {
690    //                     AlertCategory::Tracker | AlertCategory::Error
691    //                 }
692    //                 TrackerAlert::ScrapeReply(_) => AlertCategory::Tracker,
693    //                 TrackerAlert::ScrapeFailed(_) => AlertCategory::Tracker | AlertCategory::Error,
694    //                 TrackerAlert::TrackerReply(_) => AlertCategory::Tracker,
695    //                 TrackerAlert::DhtReply(_) => AlertCategory::Dht | AlertCategory::Tracker,
696    //                 TrackerAlert::TrackerAnnounce(_) => AlertCategory::Tracker,
697    //             },
698    //         },
699    //         Alert::StateUpdate(_) => AlertCategory::Status,
700    //         Alert::NotImplemented => AlertCategory::empty(),
701    //     }
702    // }
703}
704
705pub enum AlertPriority {
706    Normal = 0,
707    High,
708    Critical,
709    Meta,
710}
711
712bitflags::bitflags! {
713    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
714    pub struct AlertCategory: u32 {
715        const Error = 1 << 0;
716        const Peer = 1 << 1;
717        const PortMapping = 1 << 2;
718        const Storage = 1 << 3;
719        const Tracker = 1 << 4;
720        const Connect = 1 << 5;
721        const Status = 1 << 6;
722        #[deprecated(note = "used only for libtorrent < 1.2")]
723        const Progress = 1 << 7;
724        const IpBlock = 1 << 8;
725        const PerformanceWarning = 1 << 9;
726        const Dht = 1 << 10;
727        #[deprecated(note = "used only for libtorrent < 2.0")]
728        const Stats = 1 << 11;
729        const SessionLog = 1 << 13;
730        const TorrentLog = 1 << 14;
731        const PeerLog = 1 << 15;
732        const IncomingRequest = 1 << 16;
733        const DhtLog = 1 << 17;
734        const DhtOperation = 1 << 18;
735        const PortMappingLog = 1 << 19;
736        const PickerLog = 1 << 20;
737        const FileProgress = 1 << 21;
738        const PieceProgress = 1 << 22;
739        const Upload = 1 << 23;
740        const BlockProgress = 1 << 24;
741    }
742}