1use crate::events::ParsedEvent;
65use crate::{Error, EventType};
66
67use super::ControlMessage;
68
69pub use crate::events::{Event, ParsedEvent as EventEnum};
70
71pub fn parse_event(message: &ControlMessage) -> Result<ParsedEvent, Error> {
122 let content = message.content();
123 if content.is_empty() {
124 return Err(Error::Protocol("Empty event message".to_string()));
125 }
126
127 let (code, _, first_line) = &content[0];
128
129 if code != "650" {
130 return Err(Error::Protocol(format!(
131 "Expected event status code 650, got {}",
132 code
133 )));
134 }
135
136 let event_type = first_line
137 .split_whitespace()
138 .next()
139 .ok_or_else(|| Error::Protocol("Empty event content".to_string()))?;
140
141 let event_content = first_line
142 .strip_prefix(event_type)
143 .map(|s| s.trim_start())
144 .unwrap_or("");
145
146 let lines: Vec<String> = if content.len() > 1 {
147 content[1..]
148 .iter()
149 .filter(|(_, _, line)| !line.is_empty() && line != "OK")
150 .map(|(_, _, line)| line.clone())
151 .collect()
152 } else {
153 Vec::new()
154 };
155
156 ParsedEvent::parse(event_type, event_content, Some(&lines))
157}
158
159pub fn event_type_to_class(event_type: &str) -> Option<EventType> {
189 match event_type.to_uppercase().as_str() {
190 "ADDRMAP" => Some(EventType::AddrMap),
191 "BUILDTIMEOUT_SET" => Some(EventType::BuildTimeoutSet),
192 "BW" => Some(EventType::Bw),
193 "CELL_STATS" => Some(EventType::CellStats),
194 "CIRC" => Some(EventType::Circ),
195 "CIRC_BW" => Some(EventType::CircBw),
196 "CIRC_MINOR" => Some(EventType::CircMinor),
197 "CLIENTS_SEEN" => Some(EventType::ClientsSeen),
198 "CONF_CHANGED" => Some(EventType::ConfChanged),
199 "CONN_BW" => Some(EventType::ConnBw),
200 "DEBUG" => Some(EventType::Debug),
201 "DESCCHANGED" => Some(EventType::DescChanged),
202 "ERR" => Some(EventType::Err),
203 "GUARD" => Some(EventType::Guard),
204 "HS_DESC" => Some(EventType::HsDesc),
205 "HS_DESC_CONTENT" => Some(EventType::HsDescContent),
206 "INFO" => Some(EventType::Info),
207 "NETWORK_LIVENESS" => Some(EventType::NetworkLiveness),
208 "NEWCONSENSUS" => Some(EventType::NewConsensus),
209 "NEWDESC" => Some(EventType::NewDesc),
210 "NOTICE" => Some(EventType::Notice),
211 "NS" => Some(EventType::Ns),
212 "ORCONN" => Some(EventType::OrConn),
213 "SIGNAL" => Some(EventType::Signal),
214 "STATUS_CLIENT" | "STATUS_GENERAL" | "STATUS_SERVER" => Some(EventType::Status),
215 "STREAM" => Some(EventType::Stream),
216 "STREAM_BW" => Some(EventType::StreamBw),
217 "TRANSPORT_LAUNCHED" => Some(EventType::TransportLaunched),
218 "WARN" => Some(EventType::Warn),
219 _ => None,
220 }
221}
222
223pub fn is_known_event_type(event_type: &str) -> bool {
247 event_type_to_class(event_type).is_some()
248}
249
250#[cfg(test)]
251mod tests {
252 use super::*;
253 use crate::Runlevel;
254
255 #[test]
256 fn test_parse_bandwidth_event() {
257 let msg = ControlMessage::from_str("650 BW 100 200", None, true).unwrap();
258 let event = parse_event(&msg).unwrap();
259 match event {
260 ParsedEvent::Bandwidth(bw) => {
261 assert_eq!(bw.read, 100);
262 assert_eq!(bw.written, 200);
263 }
264 _ => panic!("Expected bandwidth event"),
265 }
266 }
267
268 #[test]
269 fn test_parse_bandwidth_event_zero() {
270 let msg = ControlMessage::from_str("650 BW 0 0", None, true).unwrap();
271 let event = parse_event(&msg).unwrap();
272 match event {
273 ParsedEvent::Bandwidth(bw) => {
274 assert_eq!(bw.read, 0);
275 assert_eq!(bw.written, 0);
276 }
277 _ => panic!("Expected bandwidth event"),
278 }
279 }
280
281 #[test]
282 fn test_parse_circuit_event() {
283 let msg = ControlMessage::from_str("650 CIRC 1 BUILT", None, true).unwrap();
284 let event = parse_event(&msg).unwrap();
285 match event {
286 ParsedEvent::Circuit(circ) => {
287 assert_eq!(circ.id.0, "1");
288 }
289 _ => panic!("Expected circuit event"),
290 }
291 }
292
293 #[test]
294 fn test_parse_circuit_launched() {
295 let msg = ControlMessage::from_str("650 CIRC 7 LAUNCHED", None, true).unwrap();
296 let event = parse_event(&msg).unwrap();
297 match event {
298 ParsedEvent::Circuit(circ) => {
299 assert_eq!(circ.id.0, "7");
300 }
301 _ => panic!("Expected circuit event"),
302 }
303 }
304
305 #[test]
306 fn test_parse_log_event() {
307 let msg = ControlMessage::from_str("650 NOTICE test message", None, true).unwrap();
308 let event = parse_event(&msg).unwrap();
309 match event {
310 ParsedEvent::Log(log) => {
311 assert_eq!(log.runlevel, Runlevel::Notice);
312 assert_eq!(log.message, "test message");
313 }
314 _ => panic!("Expected log event"),
315 }
316 }
317
318 #[test]
319 fn test_parse_debug_log_event() {
320 let msg = ControlMessage::from_str(
321 "650 DEBUG connection_edge_process_relay_cell(): Got an extended cell! Yay.",
322 None,
323 true,
324 )
325 .unwrap();
326 let event = parse_event(&msg).unwrap();
327 match event {
328 ParsedEvent::Log(log) => {
329 assert_eq!(log.runlevel, Runlevel::Debug);
330 assert_eq!(
331 log.message,
332 "connection_edge_process_relay_cell(): Got an extended cell! Yay."
333 );
334 }
335 _ => panic!("Expected log event"),
336 }
337 }
338
339 #[test]
340 fn test_parse_info_log_event() {
341 let msg = ControlMessage::from_str(
342 "650 INFO circuit_finish_handshake(): Finished building circuit hop:",
343 None,
344 true,
345 )
346 .unwrap();
347 let event = parse_event(&msg).unwrap();
348 match event {
349 ParsedEvent::Log(log) => {
350 assert_eq!(log.runlevel, Runlevel::Info);
351 assert_eq!(
352 log.message,
353 "circuit_finish_handshake(): Finished building circuit hop:"
354 );
355 }
356 _ => panic!("Expected log event"),
357 }
358 }
359
360 #[test]
361 fn test_parse_stream_event_new() {
362 let msg = ControlMessage::from_str(
363 "650 STREAM 18 NEW 0 encrypted.google.com:443 SOURCE_ADDR=127.0.0.1:47849 PURPOSE=USER",
364 None,
365 true,
366 )
367 .unwrap();
368 let event = parse_event(&msg).unwrap();
369 match event {
370 ParsedEvent::Stream(stream) => {
371 assert_eq!(stream.id.0, "18");
372 assert_eq!(stream.target_host, "encrypted.google.com");
373 assert_eq!(stream.target_port, 443);
374 }
375 _ => panic!("Expected stream event"),
376 }
377 }
378
379 #[test]
380 fn test_parse_stream_event_succeeded() {
381 let msg =
382 ControlMessage::from_str("650 STREAM 18 SUCCEEDED 26 74.125.227.129:443", None, true)
383 .unwrap();
384 let event = parse_event(&msg).unwrap();
385 match event {
386 ParsedEvent::Stream(stream) => {
387 assert_eq!(stream.id.0, "18");
388 assert_eq!(stream.target_host, "74.125.227.129");
389 assert_eq!(stream.target_port, 443);
390 }
391 _ => panic!("Expected stream event"),
392 }
393 }
394
395 #[test]
396 fn test_event_type_mapping() {
397 assert_eq!(event_type_to_class("BW"), Some(EventType::Bw));
398 assert_eq!(event_type_to_class("CIRC"), Some(EventType::Circ));
399 assert_eq!(event_type_to_class("STREAM"), Some(EventType::Stream));
400 assert_eq!(event_type_to_class("UNKNOWN"), None);
401 }
402
403 #[test]
404 fn test_event_type_mapping_all_types() {
405 assert_eq!(event_type_to_class("ADDRMAP"), Some(EventType::AddrMap));
406 assert_eq!(
407 event_type_to_class("BUILDTIMEOUT_SET"),
408 Some(EventType::BuildTimeoutSet)
409 );
410 assert_eq!(event_type_to_class("BW"), Some(EventType::Bw));
411 assert_eq!(
412 event_type_to_class("CELL_STATS"),
413 Some(EventType::CellStats)
414 );
415 assert_eq!(event_type_to_class("CIRC"), Some(EventType::Circ));
416 assert_eq!(event_type_to_class("CIRC_BW"), Some(EventType::CircBw));
417 assert_eq!(
418 event_type_to_class("CIRC_MINOR"),
419 Some(EventType::CircMinor)
420 );
421 assert_eq!(
422 event_type_to_class("CLIENTS_SEEN"),
423 Some(EventType::ClientsSeen)
424 );
425 assert_eq!(
426 event_type_to_class("CONF_CHANGED"),
427 Some(EventType::ConfChanged)
428 );
429 assert_eq!(event_type_to_class("CONN_BW"), Some(EventType::ConnBw));
430 assert_eq!(event_type_to_class("DEBUG"), Some(EventType::Debug));
431 assert_eq!(
432 event_type_to_class("DESCCHANGED"),
433 Some(EventType::DescChanged)
434 );
435 assert_eq!(event_type_to_class("ERR"), Some(EventType::Err));
436 assert_eq!(event_type_to_class("GUARD"), Some(EventType::Guard));
437 assert_eq!(event_type_to_class("HS_DESC"), Some(EventType::HsDesc));
438 assert_eq!(
439 event_type_to_class("HS_DESC_CONTENT"),
440 Some(EventType::HsDescContent)
441 );
442 assert_eq!(event_type_to_class("INFO"), Some(EventType::Info));
443 assert_eq!(
444 event_type_to_class("NETWORK_LIVENESS"),
445 Some(EventType::NetworkLiveness)
446 );
447 assert_eq!(
448 event_type_to_class("NEWCONSENSUS"),
449 Some(EventType::NewConsensus)
450 );
451 assert_eq!(event_type_to_class("NEWDESC"), Some(EventType::NewDesc));
452 assert_eq!(event_type_to_class("NOTICE"), Some(EventType::Notice));
453 assert_eq!(event_type_to_class("NS"), Some(EventType::Ns));
454 assert_eq!(event_type_to_class("ORCONN"), Some(EventType::OrConn));
455 assert_eq!(event_type_to_class("SIGNAL"), Some(EventType::Signal));
456 assert_eq!(
457 event_type_to_class("STATUS_CLIENT"),
458 Some(EventType::Status)
459 );
460 assert_eq!(
461 event_type_to_class("STATUS_GENERAL"),
462 Some(EventType::Status)
463 );
464 assert_eq!(
465 event_type_to_class("STATUS_SERVER"),
466 Some(EventType::Status)
467 );
468 assert_eq!(event_type_to_class("STREAM"), Some(EventType::Stream));
469 assert_eq!(event_type_to_class("STREAM_BW"), Some(EventType::StreamBw));
470 assert_eq!(
471 event_type_to_class("TRANSPORT_LAUNCHED"),
472 Some(EventType::TransportLaunched)
473 );
474 assert_eq!(event_type_to_class("WARN"), Some(EventType::Warn));
475 }
476
477 #[test]
478 fn test_event_type_mapping_case_insensitive() {
479 assert_eq!(event_type_to_class("bw"), Some(EventType::Bw));
480 assert_eq!(event_type_to_class("Bw"), Some(EventType::Bw));
481 assert_eq!(event_type_to_class("circ"), Some(EventType::Circ));
482 assert_eq!(event_type_to_class("Circ"), Some(EventType::Circ));
483 }
484
485 #[test]
486 fn test_is_known_event_type() {
487 assert!(is_known_event_type("BW"));
488 assert!(is_known_event_type("CIRC"));
489 assert!(is_known_event_type("STREAM"));
490 assert!(!is_known_event_type("UNKNOWN_EVENT"));
491 }
492
493 #[test]
494 fn test_is_known_event_type_case_insensitive() {
495 assert!(is_known_event_type("bw"));
496 assert!(is_known_event_type("circ"));
497 assert!(is_known_event_type("stream"));
498 }
499
500 #[test]
501 fn test_parse_event_wrong_status_code() {
502 let msg = ControlMessage::from_str("250 OK", None, true).unwrap();
503 let result = parse_event(&msg);
504 assert!(result.is_err());
505 let err = result.unwrap_err();
506 assert!(err.to_string().contains("Expected event status code 650"));
507 }
508
509 #[test]
510 fn test_parse_signal_event() {
511 let msg = ControlMessage::from_str("650 SIGNAL NEWNYM", None, true).unwrap();
512 let event = parse_event(&msg).unwrap();
513 match event {
514 ParsedEvent::Signal(sig) => {
515 assert!(matches!(sig.signal, crate::Signal::Newnym));
516 }
517 _ => panic!("Expected signal event"),
518 }
519 }
520
521 #[test]
522 fn test_parse_network_liveness_up() {
523 let msg = ControlMessage::from_str("650 NETWORK_LIVENESS UP", None, true).unwrap();
524 let event = parse_event(&msg).unwrap();
525 match event {
526 ParsedEvent::NetworkLiveness(nl) => {
527 assert_eq!(nl.status, "UP");
528 }
529 _ => panic!("Expected network liveness event"),
530 }
531 }
532
533 #[test]
534 fn test_parse_network_liveness_down() {
535 let msg = ControlMessage::from_str("650 NETWORK_LIVENESS DOWN", None, true).unwrap();
536 let event = parse_event(&msg).unwrap();
537 match event {
538 ParsedEvent::NetworkLiveness(nl) => {
539 assert_eq!(nl.status, "DOWN");
540 }
541 _ => panic!("Expected network liveness event"),
542 }
543 }
544
545 #[test]
546 fn test_parse_guard_event_new() {
547 let msg = ControlMessage::from_str(
548 "650 GUARD ENTRY $36B5DBA788246E8369DBAF58577C6BC044A9A374 NEW",
549 None,
550 true,
551 )
552 .unwrap();
553 let event = parse_event(&msg).unwrap();
554 match event {
555 ParsedEvent::Guard(guard) => {
556 assert_eq!(
557 guard.endpoint_fingerprint,
558 "36B5DBA788246E8369DBAF58577C6BC044A9A374"
559 );
560 }
561 _ => panic!("Expected guard event"),
562 }
563 }
564
565 #[test]
566 fn test_parse_newdesc_single() {
567 let msg = ControlMessage::from_str(
568 "650 NEWDESC $B3FA3110CC6F42443F039220C134CBD2FC4F0493=Sakura",
569 None,
570 true,
571 )
572 .unwrap();
573 let event = parse_event(&msg).unwrap();
574 match event {
575 ParsedEvent::NewDesc(nd) => {
576 assert!(!nd.relays.is_empty());
577 }
578 _ => panic!("Expected newdesc event"),
579 }
580 }
581
582 #[test]
583 fn test_parse_status_general_event() {
584 let msg =
585 ControlMessage::from_str("650 STATUS_GENERAL NOTICE CONSENSUS_ARRIVED", None, true)
586 .unwrap();
587 let event = parse_event(&msg).unwrap();
588 match event {
589 ParsedEvent::Status(status) => {
590 assert_eq!(status.runlevel, Runlevel::Notice);
591 assert_eq!(status.action, "CONSENSUS_ARRIVED");
592 }
593 _ => panic!("Expected status event"),
594 }
595 }
596
597 #[test]
598 fn test_parse_status_client_event() {
599 let msg = ControlMessage::from_str("650 STATUS_CLIENT NOTICE ENOUGH_DIR_INFO", None, true)
600 .unwrap();
601 let event = parse_event(&msg).unwrap();
602 match event {
603 ParsedEvent::Status(status) => {
604 assert_eq!(status.runlevel, Runlevel::Notice);
605 assert_eq!(status.action, "ENOUGH_DIR_INFO");
606 }
607 _ => panic!("Expected status event"),
608 }
609 }
610
611 #[test]
612 fn test_parse_status_client_circuit_established() {
613 let msg =
614 ControlMessage::from_str("650 STATUS_CLIENT NOTICE CIRCUIT_ESTABLISHED", None, true)
615 .unwrap();
616 let event = parse_event(&msg).unwrap();
617 match event {
618 ParsedEvent::Status(status) => {
619 assert_eq!(status.runlevel, Runlevel::Notice);
620 assert_eq!(status.action, "CIRCUIT_ESTABLISHED");
621 }
622 _ => panic!("Expected status event"),
623 }
624 }
625
626 #[test]
627 fn test_parse_circ_bw_event() {
628 let msg =
629 ControlMessage::from_str("650 CIRC_BW ID=11 READ=272 WRITTEN=817", None, true).unwrap();
630 let event = parse_event(&msg).unwrap();
631 match event {
632 ParsedEvent::CircuitBandwidth(cb) => {
633 assert_eq!(cb.id.0, "11");
634 assert_eq!(cb.read, 272);
635 assert_eq!(cb.written, 817);
636 }
637 _ => panic!("Expected circuit bandwidth event"),
638 }
639 }
640
641 #[test]
642 fn test_parse_conn_bw_event() {
643 let msg = ControlMessage::from_str(
644 "650 CONN_BW ID=11 TYPE=DIR READ=272 WRITTEN=817",
645 None,
646 true,
647 )
648 .unwrap();
649 let event = parse_event(&msg).unwrap();
650 match event {
651 ParsedEvent::ConnectionBandwidth(cb) => {
652 assert_eq!(cb.id, "11");
653 assert_eq!(cb.read, 272);
654 assert_eq!(cb.written, 817);
655 }
656 _ => panic!("Expected connection bandwidth event"),
657 }
658 }
659
660 #[test]
661 fn test_parse_orconn_closed() {
662 let msg = ControlMessage::from_str(
663 "650 ORCONN $A1130635A0CDA6F60C276FBF6994EFBD4ECADAB1~tama CLOSED REASON=DONE",
664 None,
665 true,
666 )
667 .unwrap();
668 let event = parse_event(&msg).unwrap();
669 match event {
670 ParsedEvent::OrConn(orconn) => {
671 assert_eq!(
672 orconn.target,
673 "$A1130635A0CDA6F60C276FBF6994EFBD4ECADAB1~tama"
674 );
675 }
676 _ => panic!("Expected orconn event"),
677 }
678 }
679
680 #[test]
681 fn test_parse_orconn_connected() {
682 let msg = ControlMessage::from_str(
683 "650 ORCONN 127.0.0.1:9000 CONNECTED NCIRCS=20 ID=18",
684 None,
685 true,
686 )
687 .unwrap();
688 let event = parse_event(&msg).unwrap();
689 match event {
690 ParsedEvent::OrConn(orconn) => {
691 assert_eq!(orconn.target, "127.0.0.1:9000");
692 assert_eq!(orconn.num_circuits, Some(20));
693 assert_eq!(orconn.id, Some("18".to_string()));
694 }
695 _ => panic!("Expected orconn event"),
696 }
697 }
698
699 #[test]
700 fn test_parse_orconn_launched() {
701 let msg = ControlMessage::from_str(
702 "650 ORCONN $7ED90E2833EE38A75795BA9237B0A4560E51E1A0=GreenDragon LAUNCHED",
703 None,
704 true,
705 )
706 .unwrap();
707 let event = parse_event(&msg).unwrap();
708 match event {
709 ParsedEvent::OrConn(orconn) => {
710 assert_eq!(
711 orconn.target,
712 "$7ED90E2833EE38A75795BA9237B0A4560E51E1A0=GreenDragon"
713 );
714 }
715 _ => panic!("Expected orconn event"),
716 }
717 }
718
719 #[test]
720 fn test_parse_unknown_event() {
721 let msg = ControlMessage::from_str("650 UNKNOWN_EVENT some content", None, true).unwrap();
722 let event = parse_event(&msg).unwrap();
723 match event {
724 ParsedEvent::Unknown {
725 event_type,
726 content,
727 } => {
728 assert_eq!(event_type, "UNKNOWN_EVENT");
729 assert_eq!(content, "some content");
730 }
731 _ => panic!("Expected unknown event"),
732 }
733 }
734
735 #[test]
736 fn test_parse_addrmap_event() {
737 let msg =
738 ControlMessage::from_str("650 ADDRMAP www.example.com 192.0.2.1 NEVER", None, true)
739 .unwrap();
740 let event = parse_event(&msg).unwrap();
741 match event {
742 ParsedEvent::AddrMap(am) => {
743 assert_eq!(am.hostname, "www.example.com");
744 assert_eq!(am.destination, Some("192.0.2.1".to_string()));
745 }
746 _ => panic!("Expected addrmap event"),
747 }
748 }
749
750 #[test]
751 fn test_parse_hs_desc_event() {
752 let msg = ControlMessage::from_str(
753 "650 HS_DESC REQUESTED ajhb7kljbiru65qo NO_AUTH $67B2BDA4264D8A189D9270E28B1D30A262838243=europa1 b3oeducbhjmbqmgw2i3jtz4fekkrinwj",
754 None,
755 true,
756 )
757 .unwrap();
758 let event = parse_event(&msg).unwrap();
759 match event {
760 ParsedEvent::HsDesc(hsd) => {
761 assert_eq!(hsd.address, "ajhb7kljbiru65qo");
762 }
763 _ => panic!("Expected hs_desc event"),
764 }
765 }
766}