@@ -501,6 +501,38 @@ impl ScanScheduler {
501501 ) -> Result < Vec < ScanResult > > {
502502 info ! ( "Starting scan with host discovery" ) ;
503503
504+ // Publish ScanStarted event for TUI
505+ if let Some ( ref event_bus) = self . config . scan . event_bus {
506+ use prtip_core:: events:: { ScanEvent , ScanStage } ;
507+ use std:: time:: SystemTime ;
508+ use uuid:: Uuid ;
509+
510+ let scan_id = Uuid :: new_v4 ( ) ;
511+ let timestamp = SystemTime :: now ( ) ;
512+
513+ event_bus
514+ . publish ( ScanEvent :: ScanStarted {
515+ scan_id,
516+ scan_type : self . config . scan . scan_type ,
517+ target_count : targets. len ( ) ,
518+ port_count : 0 , // Will be determined after discovery
519+ timestamp,
520+ } )
521+ . await ;
522+
523+ // Transition to DiscoveringHosts stage
524+ event_bus
525+ . publish ( ScanEvent :: StageChanged {
526+ scan_id,
527+ timestamp,
528+ from_stage : ScanStage :: Initializing ,
529+ to_stage : ScanStage :: DiscoveringHosts ,
530+ } )
531+ . await ;
532+
533+ debug ! ( "Published ScanStarted and StageChanged (DiscoveringHosts) events" ) ;
534+ }
535+
504536 // Expand all targets to individual IPs
505537 let mut original_ips = Vec :: new ( ) ;
506538 for target in & targets {
@@ -580,6 +612,27 @@ impl ScanScheduler {
580612 . filter_map ( |ip| ScanTarget :: parse ( & ip. to_string ( ) ) . ok ( ) )
581613 . collect ( ) ;
582614
615+ // Transition to ScanningPorts stage after discovery
616+ if let Some ( ref event_bus) = self . config . scan . event_bus {
617+ use prtip_core:: events:: { ScanEvent , ScanStage } ;
618+ use std:: time:: SystemTime ;
619+ use uuid:: Uuid ;
620+
621+ let scan_id = Uuid :: new_v4 ( ) ;
622+ let timestamp = SystemTime :: now ( ) ;
623+
624+ event_bus
625+ . publish ( ScanEvent :: StageChanged {
626+ scan_id,
627+ timestamp,
628+ from_stage : ScanStage :: DiscoveringHosts ,
629+ to_stage : ScanStage :: ScanningPorts ,
630+ } )
631+ . await ;
632+
633+ debug ! ( "Published StageChanged (ScanningPorts) event after discovery" ) ;
634+ }
635+
583636 // Execute normal scan on live hosts
584637 self . execute_scan ( live_targets, pcapng_writer) . await
585638 }
@@ -614,12 +667,47 @@ impl ScanScheduler {
614667 targets : Vec < ScanTarget > ,
615668 ports : & PortRange ,
616669 ) -> Result < Vec < ScanResult > > {
670+ // Store target count before vector is consumed
671+ let target_count = targets. len ( ) ;
672+
617673 info ! (
618674 "Starting port scan: {} targets, {} ports" ,
619- targets . len ( ) ,
675+ target_count ,
620676 ports. count( )
621677 ) ;
622678
679+ // Publish ScanStarted event for TUI
680+ if let Some ( ref event_bus) = self . config . scan . event_bus {
681+ use prtip_core:: events:: { ScanEvent , ScanStage } ;
682+ use std:: time:: SystemTime ;
683+ use uuid:: Uuid ;
684+
685+ let scan_id = Uuid :: new_v4 ( ) ;
686+ let timestamp = SystemTime :: now ( ) ;
687+
688+ event_bus
689+ . publish ( ScanEvent :: ScanStarted {
690+ scan_id,
691+ scan_type : self . config . scan . scan_type ,
692+ target_count,
693+ port_count : ports. count ( ) ,
694+ timestamp,
695+ } )
696+ . await ;
697+
698+ // Transition to ScanningPorts stage
699+ event_bus
700+ . publish ( ScanEvent :: StageChanged {
701+ scan_id,
702+ timestamp,
703+ from_stage : ScanStage :: Initializing ,
704+ to_stage : ScanStage :: ScanningPorts ,
705+ } )
706+ . await ;
707+
708+ debug ! ( "Published ScanStarted and StageChanged events" ) ;
709+ }
710+
623711 let ports_vec: Vec < u16 > = ports. iter ( ) . collect ( ) ;
624712
625713 // Calculate estimated hosts for progress bar and buffer sizing
@@ -940,6 +1028,56 @@ impl ScanScheduler {
9401028 // Complete progress bar
9411029 progress. finish ( "Scan complete" ) ;
9421030
1031+ // Publish ScanCompleted event for TUI
1032+ if let Some ( ref event_bus) = self . config . scan . event_bus {
1033+ use prtip_core:: events:: { ScanEvent , ScanStage } ;
1034+ use std:: time:: { Duration , SystemTime } ;
1035+ use uuid:: Uuid ;
1036+
1037+ let scan_id = Uuid :: new_v4 ( ) ;
1038+ let timestamp = SystemTime :: now ( ) ;
1039+
1040+ // Calculate port counts
1041+ let open_count = all_results
1042+ . iter ( )
1043+ . filter ( |r| r. state == PortState :: Open )
1044+ . count ( ) ;
1045+ let closed_count = all_results
1046+ . iter ( )
1047+ . filter ( |r| r. state == PortState :: Closed )
1048+ . count ( ) ;
1049+ let filtered_count = all_results
1050+ . iter ( )
1051+ . filter ( |r| r. state == PortState :: Filtered )
1052+ . count ( ) ;
1053+ let detected_services = all_results. iter ( ) . filter ( |r| r. service . is_some ( ) ) . count ( ) ;
1054+
1055+ // Transition to Completed stage
1056+ event_bus
1057+ . publish ( ScanEvent :: StageChanged {
1058+ scan_id,
1059+ timestamp,
1060+ from_stage : ScanStage :: ScanningPorts ,
1061+ to_stage : ScanStage :: Completed ,
1062+ } )
1063+ . await ;
1064+
1065+ event_bus
1066+ . publish ( ScanEvent :: ScanCompleted {
1067+ scan_id,
1068+ duration : Duration :: from_secs ( 0 ) , // TODO: Track actual scan duration
1069+ total_targets : target_count,
1070+ open_ports : open_count,
1071+ closed_ports : closed_count,
1072+ filtered_ports : filtered_count,
1073+ detected_services,
1074+ timestamp,
1075+ } )
1076+ . await ;
1077+
1078+ debug ! ( "Published ScanCompleted event" ) ;
1079+ }
1080+
9431081 info ! ( "Port scan complete: {} results" , all_results. len( ) ) ;
9441082 Ok ( all_results)
9451083 }
0 commit comments