@@ -75,14 +75,35 @@ pub fn extract_flows_with_config(
7575 packets : & [ CapturedPacket ] ,
7676 config : FlowConfig ,
7777) -> Result < Vec < ConversationState > , FlowError > {
78+ let verbose = config. verbose ;
79+ let total = packets. len ( ) ;
7880 let table = ConversationTable :: new ( config) ;
7981
82+ if verbose {
83+ eprintln ! ( "[stackforge] Starting flow extraction ({total} packets)..." ) ;
84+ }
85+
8086 for ( index, captured) in packets. iter ( ) . enumerate ( ) {
8187 let timestamp = captured. metadata . timestamp ;
8288 table. ingest_packet ( & captured. packet , timestamp, index) ?;
89+
90+ if verbose && ( index + 1 ) % 10_000 == 0 {
91+ eprintln ! (
92+ "[stackforge] Processed {}/{total} packets ({} flows so far)" ,
93+ index + 1 ,
94+ table. conversation_count( ) ,
95+ ) ;
96+ }
8397 }
8498
85- Ok ( table. into_conversations ( ) )
99+ let conversations = table. into_conversations ( ) ;
100+ if verbose {
101+ eprintln ! (
102+ "[stackforge] Flow extraction complete: {total} packets -> {} conversations" ,
103+ conversations. len( ) ,
104+ ) ;
105+ }
106+ Ok ( conversations)
86107}
87108
88109/// Extract flows from a streaming packet source (iterator).
@@ -100,16 +121,36 @@ pub fn extract_flows_streaming<I>(
100121where
101122 I : Iterator < Item = Result < CapturedPacket , PacketError > > ,
102123{
124+ let verbose = config. verbose ;
103125 let table = ConversationTable :: new ( config) ;
104126
127+ if verbose {
128+ eprintln ! ( "[stackforge] Starting streaming flow extraction..." ) ;
129+ }
130+
105131 for ( index, result) in packets. enumerate ( ) {
106132 let captured = result. map_err ( FlowError :: PacketError ) ?;
107133 let timestamp = captured. metadata . timestamp ;
108134 table. ingest_packet ( & captured. packet , timestamp, index) ?;
109135 // `captured` is dropped here — packet memory freed immediately
136+
137+ if verbose && ( index + 1 ) % 10_000 == 0 {
138+ eprintln ! (
139+ "[stackforge] Processed {} packets ({} flows so far)" ,
140+ index + 1 ,
141+ table. conversation_count( ) ,
142+ ) ;
143+ }
110144 }
111145
112- Ok ( table. into_conversations ( ) )
146+ let conversations = table. into_conversations ( ) ;
147+ if verbose {
148+ eprintln ! (
149+ "[stackforge] Flow extraction complete: {} conversations" ,
150+ conversations. len( ) ,
151+ ) ;
152+ }
153+ Ok ( conversations)
113154}
114155
115156/// Extract flows directly from a capture file (PCAP or PcapNG).
@@ -120,6 +161,13 @@ pub fn extract_flows_from_file(
120161 path : impl AsRef < Path > ,
121162 config : FlowConfig ,
122163) -> Result < Vec < ConversationState > , FlowError > {
164+ let verbose = config. verbose ;
165+ if verbose {
166+ eprintln ! (
167+ "[stackforge] Opening capture file: {}" ,
168+ path. as_ref( ) . display( ) ,
169+ ) ;
170+ }
123171 let iter = CaptureIterator :: open ( path) . map_err ( FlowError :: PacketError ) ?;
124172 extract_flows_streaming ( iter, config)
125173}
0 commit comments