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