stackforge 0.6.1__tar.gz → 0.6.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. {stackforge-0.6.1 → stackforge-0.6.3}/Cargo.lock +3 -3
  2. {stackforge-0.6.1 → stackforge-0.6.3}/Cargo.toml +1 -1
  3. {stackforge-0.6.1 → stackforge-0.6.3}/PKG-INFO +17 -1
  4. {stackforge-0.6.1 → stackforge-0.6.3}/README.md +16 -0
  5. stackforge-0.6.3/crates/stackforge-core/src/.DS_Store +0 -0
  6. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/config.rs +3 -0
  7. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/mod.rs +50 -2
  8. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/spill.rs +24 -7
  9. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/table.rs +14 -10
  10. {stackforge-0.6.1 → stackforge-0.6.3}/src/lib.rs +19 -5
  11. {stackforge-0.6.1 → stackforge-0.6.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  12. {stackforge-0.6.1 → stackforge-0.6.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  13. {stackforge-0.6.1 → stackforge-0.6.3}/.github/workflows/release.yml +0 -0
  14. {stackforge-0.6.1 → stackforge-0.6.3}/.github/workflows/test.yml +0 -0
  15. {stackforge-0.6.1 → stackforge-0.6.3}/.gitignore +0 -0
  16. {stackforge-0.6.1 → stackforge-0.6.3}/.pre-commit-config.yaml +0 -0
  17. {stackforge-0.6.1 → stackforge-0.6.3}/.python-version +0 -0
  18. {stackforge-0.6.1 → stackforge-0.6.3}/CLAUDE.md +0 -0
  19. {stackforge-0.6.1 → stackforge-0.6.3}/CODE_OF_CONDUCT.md +0 -0
  20. {stackforge-0.6.1 → stackforge-0.6.3}/CONTRIBUTING.md +0 -0
  21. {stackforge-0.6.1 → stackforge-0.6.3}/LICENSE +0 -0
  22. {stackforge-0.6.1 → stackforge-0.6.3}/cliff.toml +0 -0
  23. {stackforge-0.6.1 → stackforge-0.6.3}/cog.toml +0 -0
  24. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-automata/Cargo.toml +0 -0
  25. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-automata/src/lib.rs +0 -0
  26. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/Cargo.toml +0 -0
  27. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/error.rs +0 -0
  28. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/error.rs +0 -0
  29. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/icmp_state.rs +0 -0
  30. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/key.rs +0 -0
  31. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/state.rs +0 -0
  32. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/tcp_reassembly.rs +0 -0
  33. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/tcp_state.rs +0 -0
  34. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/flow/udp_state.rs +0 -0
  35. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/arp.rs +0 -0
  36. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/bindings.rs +0 -0
  37. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/bitmap.rs +0 -0
  38. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/builder.rs +0 -0
  39. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/edns.rs +0 -0
  40. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/header.rs +0 -0
  41. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/mod.rs +0 -0
  42. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/query.rs +0 -0
  43. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/rdata.rs +0 -0
  44. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/rr.rs +0 -0
  45. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/svcb.rs +0 -0
  46. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dns/types.rs +0 -0
  47. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/builder.rs +0 -0
  48. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/control.rs +0 -0
  49. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/data.rs +0 -0
  50. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/ie.rs +0 -0
  51. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/management.rs +0 -0
  52. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/mod.rs +0 -0
  53. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/radiotap.rs +0 -0
  54. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/security.rs +0 -0
  55. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot11/types.rs +0 -0
  56. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot15d4/beacon.rs +0 -0
  57. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot15d4/builder.rs +0 -0
  58. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot15d4/command.rs +0 -0
  59. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot15d4/crc.rs +0 -0
  60. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot15d4/mod.rs +0 -0
  61. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot15d4/security.rs +0 -0
  62. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/dot15d4/types.rs +0 -0
  63. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ethernet.rs +0 -0
  64. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/field.rs +0 -0
  65. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/field_ext.rs +0 -0
  66. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ftp/builder.rs +0 -0
  67. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ftp/mod.rs +0 -0
  68. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/generic/builder.rs +0 -0
  69. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/generic/mod.rs +0 -0
  70. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http/builder.rs +0 -0
  71. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http/detection.rs +0 -0
  72. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http/mod.rs +0 -0
  73. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http/request.rs +0 -0
  74. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http/response.rs +0 -0
  75. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http2/builder.rs +0 -0
  76. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http2/frames.rs +0 -0
  77. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http2/hpack.rs +0 -0
  78. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/http2/mod.rs +0 -0
  79. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmp/builder.rs +0 -0
  80. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmp/checksum.rs +0 -0
  81. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmp/error.rs +0 -0
  82. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmp/extensions.rs +0 -0
  83. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmp/mod.rs +0 -0
  84. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmp/types.rs +0 -0
  85. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmpv6/builder.rs +0 -0
  86. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/icmpv6/mod.rs +0 -0
  87. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/imap/builder.rs +0 -0
  88. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/imap/mod.rs +0 -0
  89. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/builder.rs +0 -0
  90. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/checksum.rs +0 -0
  91. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/fragmentation.rs +0 -0
  92. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/header.rs +0 -0
  93. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/mod.rs +0 -0
  94. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/options.rs +0 -0
  95. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/protocol.rs +0 -0
  96. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/routing.rs +0 -0
  97. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv4/ttl.rs +0 -0
  98. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv6/builder.rs +0 -0
  99. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv6/ext_headers.rs +0 -0
  100. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ipv6/mod.rs +0 -0
  101. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/l2tp/builder.rs +0 -0
  102. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/l2tp/mod.rs +0 -0
  103. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/mod.rs +0 -0
  104. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/modbus/builder.rs +0 -0
  105. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/modbus/crc.rs +0 -0
  106. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/modbus/mod.rs +0 -0
  107. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/mqtt/builder.rs +0 -0
  108. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/mqtt/mod.rs +0 -0
  109. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/mqttsn/builder.rs +0 -0
  110. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/mqttsn/mod.rs +0 -0
  111. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/neighbor.rs +0 -0
  112. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/pop3/builder.rs +0 -0
  113. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/pop3/mod.rs +0 -0
  114. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/quic/builder.rs +0 -0
  115. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/quic/frames.rs +0 -0
  116. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/quic/headers.rs +0 -0
  117. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/quic/mod.rs +0 -0
  118. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/quic/varint.rs +0 -0
  119. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/raw.rs +0 -0
  120. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/smtp/builder.rs +0 -0
  121. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/smtp/mod.rs +0 -0
  122. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ssh/builder.rs +0 -0
  123. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/ssh/mod.rs +0 -0
  124. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/stack.rs +0 -0
  125. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tcp/builder.rs +0 -0
  126. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tcp/checksum.rs +0 -0
  127. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tcp/flags.rs +0 -0
  128. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tcp/header.rs +0 -0
  129. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tcp/mod.rs +0 -0
  130. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tcp/options.rs +0 -0
  131. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tcp/services.rs +0 -0
  132. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tftp/builder.rs +0 -0
  133. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tftp/mod.rs +0 -0
  134. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/builder.rs +0 -0
  135. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/cert.rs +0 -0
  136. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/cipher_aead.rs +0 -0
  137. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/cipher_block.rs +0 -0
  138. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/cipher_stream.rs +0 -0
  139. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/compression.rs +0 -0
  140. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/groups.rs +0 -0
  141. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/hash.rs +0 -0
  142. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/hkdf_tls13.rs +0 -0
  143. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/hmac_tls.rs +0 -0
  144. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/mod.rs +0 -0
  145. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/prf.rs +0 -0
  146. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/crypto/suites.rs +0 -0
  147. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/extensions/common.rs +0 -0
  148. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/extensions/key_share.rs +0 -0
  149. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/extensions/mod.rs +0 -0
  150. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/extensions/signature_algorithms.rs +0 -0
  151. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/extensions/sni.rs +0 -0
  152. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/extensions/supported_versions.rs +0 -0
  153. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/handshake/certificate.rs +0 -0
  154. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/handshake/client_hello.rs +0 -0
  155. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/handshake/finished.rs +0 -0
  156. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/handshake/key_exchange.rs +0 -0
  157. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/handshake/mod.rs +0 -0
  158. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/handshake/server_hello.rs +0 -0
  159. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/keyexchange/ecdhe.rs +0 -0
  160. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/keyexchange/mod.rs +0 -0
  161. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/mod.rs +0 -0
  162. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/record.rs +0 -0
  163. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/session.rs +0 -0
  164. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/sslv2/handshake.rs +0 -0
  165. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/sslv2/mod.rs +0 -0
  166. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/sslv2/record.rs +0 -0
  167. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/tls/types.rs +0 -0
  168. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/udp/builder.rs +0 -0
  169. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/udp/checksum.rs +0 -0
  170. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/udp/mod.rs +0 -0
  171. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/zwave/builder.rs +0 -0
  172. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/layer/zwave/mod.rs +0 -0
  173. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/lib.rs +0 -0
  174. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/packet.rs +0 -0
  175. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/pcap/mod.rs +0 -0
  176. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/pcap/reader.rs +0 -0
  177. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/pcap/writer.rs +0 -0
  178. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/utils/bits.rs +0 -0
  179. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/utils/checksum.rs +0 -0
  180. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/utils/compare.rs +0 -0
  181. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/utils/hex.rs +0 -0
  182. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/utils/mod.rs +0 -0
  183. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/utils/padding.rs +0 -0
  184. {stackforge-0.6.1 → stackforge-0.6.3}/crates/stackforge-core/src/utils/random.rs +0 -0
  185. {stackforge-0.6.1 → stackforge-0.6.3}/pyproject.toml +0 -0
  186. {stackforge-0.6.1 → stackforge-0.6.3}/python/stackforge/__init__.py +0 -0
  187. {stackforge-0.6.1 → stackforge-0.6.3}/python/stackforge/custom.py +0 -0
  188. {stackforge-0.6.1 → stackforge-0.6.3}/rust-toolchain.toml +0 -0
  189. {stackforge-0.6.1 → stackforge-0.6.3}/rustfmt.toml +0 -0
  190. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/arp.rs +0 -0
  191. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/arp_compat.rs +0 -0
  192. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/ethernet_compat.rs +0 -0
  193. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/icmp_compat.rs +0 -0
  194. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/ipv4_compat.rs +0 -0
  195. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/mod.rs +0 -0
  196. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/ssh_compat.rs +0 -0
  197. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/tcp_compat.rs +0 -0
  198. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/tls_compat.rs +0 -0
  199. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/compat_tests/udp_compat.rs +0 -0
  200. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/dns.rs +0 -0
  201. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/dot11.rs +0 -0
  202. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/dot15d4.rs +0 -0
  203. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/ethernet.rs +0 -0
  204. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/field.rs +0 -0
  205. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/ftp.rs +0 -0
  206. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/http.rs +0 -0
  207. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/http2.rs +0 -0
  208. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/icmpv6.rs +0 -0
  209. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/imap.rs +0 -0
  210. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/ipv6.rs +0 -0
  211. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/layer.rs +0 -0
  212. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/main.rs +0 -0
  213. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/modbus.rs +0 -0
  214. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/mqtt.rs +0 -0
  215. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/packet.rs +0 -0
  216. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/pop3.rs +0 -0
  217. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/quic.rs +0 -0
  218. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/smtp.rs +0 -0
  219. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/ssh.rs +0 -0
  220. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/tftp.rs +0 -0
  221. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/tls.rs +0 -0
  222. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/util.rs +0 -0
  223. {stackforge-0.6.1 → stackforge-0.6.3}/tests/integration/zwave.rs +0 -0
  224. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/__init__.py +0 -0
  225. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/conftest.py +0 -0
  226. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_arp_compat.py +0 -0
  227. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_checksums_compat.py +0 -0
  228. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_edge_cases_compat.py +0 -0
  229. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_ethernet_compat.py +0 -0
  230. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_icmp_compat.py +0 -0
  231. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_ipv4_compat.py +0 -0
  232. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_pcap_compat.py +0 -0
  233. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_stacking_compat.py +0 -0
  234. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_tcp_compat.py +0 -0
  235. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_udp_compat.py +0 -0
  236. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/scapy_compat/test_uts_integration.py +0 -0
  237. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_core.py +0 -0
  238. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_custom.py +0 -0
  239. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_dns.py +0 -0
  240. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_dot11.py +0 -0
  241. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_dot15d4.py +0 -0
  242. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_flow.py +0 -0
  243. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_ftp.py +0 -0
  244. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_http.py +0 -0
  245. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_icmpv6.py +0 -0
  246. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_imap.py +0 -0
  247. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_ipv6.py +0 -0
  248. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_l2tp.py +0 -0
  249. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_max_packet_flow_len.py +0 -0
  250. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_modbus.py +0 -0
  251. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_mqtt.py +0 -0
  252. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_mqttsn.py +0 -0
  253. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_pcap.py +0 -0
  254. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_pcapng.py +0 -0
  255. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_pop3.py +0 -0
  256. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_quic.py +0 -0
  257. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_smtp.py +0 -0
  258. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_ssh.py +0 -0
  259. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_streaming_flows.py +0 -0
  260. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_tftp.py +0 -0
  261. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_tls.py +0 -0
  262. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_udp_icmp.py +0 -0
  263. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_ftp.py +0 -0
  264. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_http.py +0 -0
  265. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_http2.py +0 -0
  266. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_imap.py +0 -0
  267. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_ipv6.py +0 -0
  268. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_l2tp.py +0 -0
  269. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_modbus.py +0 -0
  270. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_mqtt.py +0 -0
  271. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_mqttsn.py +0 -0
  272. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_pop3.py +0 -0
  273. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_quic.py +0 -0
  274. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_smtp.py +0 -0
  275. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_tftp.py +0 -0
  276. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_uts_zwave.py +0 -0
  277. {stackforge-0.6.1 → stackforge-0.6.3}/tests/python/test_zwave.py +0 -0
  278. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http2_h2c.pcap +0 -0
  279. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http_chunk.pcap +0 -0
  280. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http_compressed-brotli.pcap +0 -0
  281. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http_compressed-zstd.pcap +0 -0
  282. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http_compressed.pcap +0 -0
  283. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http_content_length.pcap +0 -0
  284. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http_head.pcapng +0 -0
  285. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/http_tcp_psh.pcap +0 -0
  286. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/ssh_ed25519.pcap +0 -0
  287. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/tcprelay/PCAP.md +0 -0
  288. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/tcprelay/smallFlows.pcap +0 -0
  289. {stackforge-0.6.1 → stackforge-0.6.3}/tests/sample_pcap/tcprelay/test.pcap +0 -0
  290. {stackforge-0.6.1 → stackforge-0.6.3}/tests/scripts/compare_packets.py +0 -0
  291. {stackforge-0.6.1 → stackforge-0.6.3}/tests/scripts/generate_scapy_fixtures.py +0 -0
  292. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/dns.uts +0 -0
  293. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/dns_dnssec.uts +0 -0
  294. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/dns_edns0.uts +0 -0
  295. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/dot11.uts +0 -0
  296. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/dot15d4.uts +0 -0
  297. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/fields.uts +0 -0
  298. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/ftp.uts +0 -0
  299. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/http.uts +0 -0
  300. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/http2.uts +0 -0
  301. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/imap.uts +0 -0
  302. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/inet.uts +0 -0
  303. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/inet6 copy.uts +0 -0
  304. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/inet6.uts +0 -0
  305. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/l2.uts +0 -0
  306. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/l2tp.uts +0 -0
  307. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/modbus.uts +0 -0
  308. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/mqtt.uts +0 -0
  309. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/mqttsn.uts +0 -0
  310. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/pop3.uts +0 -0
  311. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/quic.uts +0 -0
  312. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/smtp.uts +0 -0
  313. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/ssh.uts +0 -0
  314. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tftp.uts +0 -0
  315. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/__init__.py +0 -0
  316. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/cert.uts +0 -0
  317. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/example_client.py +0 -0
  318. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/example_server.py +0 -0
  319. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/README.md +0 -0
  320. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/ca_cert.pem +0 -0
  321. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/ca_key.pem +0 -0
  322. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/cli_cert.pem +0 -0
  323. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/cli_key.pem +0 -0
  324. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/srv_cert.pem +0 -0
  325. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/srv_cert_ed25519.pem +0 -0
  326. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/srv_key.pem +0 -0
  327. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/pki/srv_key_ed25519.pem +0 -0
  328. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/sslv2.uts +0 -0
  329. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/tls.uts +0 -0
  330. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/tls13.uts +0 -0
  331. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/tls/tlsclientserver.uts +0 -0
  332. {stackforge-0.6.1 → stackforge-0.6.3}/tests/uts/zwave.uts +0 -0
  333. {stackforge-0.6.1 → stackforge-0.6.3}/uv.lock +0 -0
@@ -1074,7 +1074,7 @@ dependencies = [
1074
1074
 
1075
1075
  [[package]]
1076
1076
  name = "stackforge"
1077
- version = "0.6.1"
1077
+ version = "0.6.3"
1078
1078
  dependencies = [
1079
1079
  "pyo3",
1080
1080
  "stackforge-automata",
@@ -1083,7 +1083,7 @@ dependencies = [
1083
1083
 
1084
1084
  [[package]]
1085
1085
  name = "stackforge-automata"
1086
- version = "0.6.1"
1086
+ version = "0.6.3"
1087
1087
  dependencies = [
1088
1088
  "bytes",
1089
1089
  "stackforge-core",
@@ -1091,7 +1091,7 @@ dependencies = [
1091
1091
 
1092
1092
  [[package]]
1093
1093
  name = "stackforge-core"
1094
- version = "0.6.1"
1094
+ version = "0.6.3"
1095
1095
  dependencies = [
1096
1096
  "aes",
1097
1097
  "aes-gcm",
@@ -21,7 +21,7 @@ shared-version = true
21
21
  tag-name = "v{{version}}"
22
22
 
23
23
  [workspace.package]
24
- version = "0.6.1"
24
+ version = "0.6.3"
25
25
  edition = "2024"
26
26
  license = "GPL-3.0-only"
27
27
  authors = ["Stackforge Contributors"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stackforge
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Intended Audience :: System Administrators
@@ -354,6 +354,22 @@ packets = rdpcap("capture.pcap")
354
354
  conversations = extract_flows_from_packets(packets)
355
355
  ```
356
356
 
357
+ Enable verbose mode to see progress feedback on stderr during extraction:
358
+
359
+ ```python
360
+ # Quick verbose flag on the function call
361
+ conversations = extract_flows("capture.pcap", verbose=True)
362
+ # [stackforge] Opening capture file: capture.pcap
363
+ # [stackforge] Starting streaming flow extraction...
364
+ # [stackforge] Processed 10000 packets (342 flows so far)
365
+ # [stackforge] Processed 20000 packets (587 flows so far)
366
+ # [stackforge] Flow extraction complete: 612 conversations
367
+
368
+ # Or via FlowConfig
369
+ config = FlowConfig(verbose=True)
370
+ conversations = extract_flows("capture.pcap", config=config)
371
+ ```
372
+
357
373
  Customize timeouts, buffer limits, and memory budget with `FlowConfig`:
358
374
 
359
375
  ```python
@@ -330,6 +330,22 @@ packets = rdpcap("capture.pcap")
330
330
  conversations = extract_flows_from_packets(packets)
331
331
  ```
332
332
 
333
+ Enable verbose mode to see progress feedback on stderr during extraction:
334
+
335
+ ```python
336
+ # Quick verbose flag on the function call
337
+ conversations = extract_flows("capture.pcap", verbose=True)
338
+ # [stackforge] Opening capture file: capture.pcap
339
+ # [stackforge] Starting streaming flow extraction...
340
+ # [stackforge] Processed 10000 packets (342 flows so far)
341
+ # [stackforge] Processed 20000 packets (587 flows so far)
342
+ # [stackforge] Flow extraction complete: 612 conversations
343
+
344
+ # Or via FlowConfig
345
+ config = FlowConfig(verbose=True)
346
+ conversations = extract_flows("capture.pcap", config=config)
347
+ ```
348
+
333
349
  Customize timeouts, buffer limits, and memory budget with `FlowConfig`:
334
350
 
335
351
  ```python
@@ -30,6 +30,8 @@ pub struct FlowConfig {
30
30
  pub memory_budget: Option<usize>,
31
31
  /// Directory for spill files (None = system temp dir).
32
32
  pub spill_dir: Option<PathBuf>,
33
+ /// Print progress feedback to stderr during flow extraction (default: false).
34
+ pub verbose: bool,
33
35
  }
34
36
 
35
37
  impl Default for FlowConfig {
@@ -46,6 +48,7 @@ impl Default for FlowConfig {
46
48
  track_max_flow_len: false,
47
49
  memory_budget: None,
48
50
  spill_dir: None,
51
+ verbose: false,
49
52
  }
50
53
  }
51
54
  }
@@ -75,14 +75,35 @@ pub fn extract_flows_with_config(
75
75
  packets: &[CapturedPacket],
76
76
  config: FlowConfig,
77
77
  ) -> Result<Vec<ConversationState>, FlowError> {
78
+ let verbose = config.verbose;
79
+ let total = packets.len();
78
80
  let table = ConversationTable::new(config);
79
81
 
82
+ if verbose {
83
+ eprintln!("[stackforge] Starting flow extraction ({total} packets)...");
84
+ }
85
+
80
86
  for (index, captured) in packets.iter().enumerate() {
81
87
  let timestamp = captured.metadata.timestamp;
82
88
  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
+ }
83
97
  }
84
98
 
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)
86
107
  }
87
108
 
88
109
  /// Extract flows from a streaming packet source (iterator).
@@ -100,16 +121,36 @@ pub fn extract_flows_streaming<I>(
100
121
  where
101
122
  I: Iterator<Item = Result<CapturedPacket, PacketError>>,
102
123
  {
124
+ let verbose = config.verbose;
103
125
  let table = ConversationTable::new(config);
104
126
 
127
+ if verbose {
128
+ eprintln!("[stackforge] Starting streaming flow extraction...");
129
+ }
130
+
105
131
  for (index, result) in packets.enumerate() {
106
132
  let captured = result.map_err(FlowError::PacketError)?;
107
133
  let timestamp = captured.metadata.timestamp;
108
134
  table.ingest_packet(&captured.packet, timestamp, index)?;
109
135
  // `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
+ }
110
144
  }
111
145
 
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)
113
154
  }
114
155
 
115
156
  /// Extract flows directly from a capture file (PCAP or PcapNG).
@@ -120,6 +161,13 @@ pub fn extract_flows_from_file(
120
161
  path: impl AsRef<Path>,
121
162
  config: FlowConfig,
122
163
  ) -> 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
+ }
123
171
  let iter = CaptureIterator::open(path).map_err(FlowError::PacketError)?;
124
172
  extract_flows_streaming(iter, config)
125
173
  }
@@ -43,17 +43,18 @@ impl ReassemblyStorage {
43
43
  self.len() == 0
44
44
  }
45
45
 
46
- /// Append data. Only valid when `InMemory`.
46
+ /// Append data. Works for both in-memory and on-disk storage.
47
47
  ///
48
- /// # Panics
49
- /// Panics if storage has been spilled to disk. Callers must ensure data
50
- /// is not appended after a spill (in practice, spilling only happens
51
- /// for completed/idle flows).
48
+ /// When in-memory, appends to the `Vec`. When on-disk, appends to the
49
+ /// temporary file and updates the tracked length.
52
50
  pub fn extend_from_slice(&mut self, data: &[u8]) {
53
51
  match self {
54
52
  Self::InMemory(v) => v.extend_from_slice(data),
55
- Self::OnDisk { .. } => {
56
- panic!("cannot extend spilled storage; data already on disk");
53
+ Self::OnDisk { file, len } => {
54
+ file.write_all(data)
55
+ .expect("failed to append to spill file");
56
+ file.flush().expect("failed to flush spill file");
57
+ *len += data.len();
57
58
  },
58
59
  }
59
60
  }
@@ -258,6 +259,22 @@ mod tests {
258
259
  assert!(s.is_empty());
259
260
  }
260
261
 
262
+ #[test]
263
+ fn test_reassembly_storage_extend_after_spill() {
264
+ let mut s = ReassemblyStorage::new();
265
+ s.extend_from_slice(b"hello ");
266
+ s.spill_to_disk(None).unwrap();
267
+ assert!(s.is_spilled());
268
+
269
+ // Appending after spill should work (writes to file)
270
+ s.extend_from_slice(b"world");
271
+ assert_eq!(s.len(), 11);
272
+ assert!(s.is_spilled());
273
+
274
+ let data = s.read_all().unwrap();
275
+ assert_eq!(data, b"hello world");
276
+ }
277
+
261
278
  #[test]
262
279
  fn test_reassembly_storage_drain_spilled() {
263
280
  let mut s = ReassemblyStorage::new();
@@ -125,17 +125,21 @@ impl ConversationTable {
125
125
  // Update conversation status from protocol state
126
126
  conv.update_status();
127
127
 
128
- // Track memory for TCP reassembly buffers
128
+ // Track memory for TCP reassembly buffers (only for in-memory data)
129
129
  if self.memory_tracker.has_budget() {
130
- if matches!(conv.protocol_state, ProtocolState::Tcp(_)) {
131
- // Track bytes that TCP payload may have added
132
- let tcp_payload_len = packet.tcp().map_or(0, |tcp| {
133
- let data_offset = tcp.data_offset(buf).unwrap_or(5) as usize * 4;
134
- let payload_start = tcp.index.start + data_offset;
135
- buf.len().saturating_sub(payload_start)
136
- });
137
- if tcp_payload_len > 0 {
138
- self.memory_tracker.add(tcp_payload_len);
130
+ if let ProtocolState::Tcp(ref tcp_state) = conv.protocol_state {
131
+ // Only track if at least one reassembler is still in memory
132
+ let fwd_spilled = tcp_state.reassembler_fwd.is_spilled();
133
+ let rev_spilled = tcp_state.reassembler_rev.is_spilled();
134
+ if !fwd_spilled || !rev_spilled {
135
+ let tcp_payload_len = packet.tcp().map_or(0, |tcp| {
136
+ let data_offset = tcp.data_offset(buf).unwrap_or(5) as usize * 4;
137
+ let payload_start = tcp.index.start + data_offset;
138
+ buf.len().saturating_sub(payload_start)
139
+ });
140
+ if tcp_payload_len > 0 {
141
+ self.memory_tracker.add(tcp_payload_len);
142
+ }
139
143
  }
140
144
  }
141
145
  }
@@ -4076,6 +4076,7 @@ impl PyFlowConfig {
4076
4076
  track_max_flow_len=false,
4077
4077
  memory_budget=None,
4078
4078
  spill_dir=None,
4079
+ verbose=false,
4079
4080
  ))]
4080
4081
  #[allow(clippy::too_many_arguments)]
4081
4082
  fn new(
@@ -4089,6 +4090,7 @@ impl PyFlowConfig {
4089
4090
  track_max_flow_len: bool,
4090
4091
  memory_budget: Option<usize>,
4091
4092
  spill_dir: Option<String>,
4093
+ verbose: bool,
4092
4094
  ) -> Self {
4093
4095
  Self {
4094
4096
  inner: stackforge_core::FlowConfig {
@@ -4104,6 +4106,7 @@ impl PyFlowConfig {
4104
4106
  track_max_flow_len,
4105
4107
  memory_budget,
4106
4108
  spill_dir: spill_dir.map(std::path::PathBuf::from),
4109
+ verbose,
4107
4110
  ..stackforge_core::FlowConfig::default()
4108
4111
  },
4109
4112
  }
@@ -4451,9 +4454,16 @@ impl PyConversation {
4451
4454
  /// Returns:
4452
4455
  /// List of Conversation objects sorted by start time.
4453
4456
  #[pyfunction]
4454
- #[pyo3(signature = (pcap_path, config=None))]
4455
- fn extract_flows(pcap_path: &str, config: Option<PyFlowConfig>) -> PyResult<Vec<PyConversation>> {
4456
- let flow_config = config.map(|c| c.inner).unwrap_or_default();
4457
+ #[pyo3(signature = (pcap_path, config=None, verbose=false))]
4458
+ fn extract_flows(
4459
+ pcap_path: &str,
4460
+ config: Option<PyFlowConfig>,
4461
+ verbose: bool,
4462
+ ) -> PyResult<Vec<PyConversation>> {
4463
+ let mut flow_config = config.map(|c| c.inner).unwrap_or_default();
4464
+ if verbose {
4465
+ flow_config.verbose = true;
4466
+ }
4457
4467
 
4458
4468
  // Use streaming extraction — never loads all packets into memory at once
4459
4469
  let conversations =
@@ -4484,10 +4494,11 @@ fn extract_flows(pcap_path: &str, config: Option<PyFlowConfig>) -> PyResult<Vec<
4484
4494
  /// Returns:
4485
4495
  /// List of Conversation objects sorted by start time.
4486
4496
  #[pyfunction]
4487
- #[pyo3(signature = (packets, config=None))]
4497
+ #[pyo3(signature = (packets, config=None, verbose=false))]
4488
4498
  fn extract_flows_from_packets(
4489
4499
  packets: Vec<PyRef<'_, PyPacket>>,
4490
4500
  config: Option<PyFlowConfig>,
4501
+ verbose: bool,
4491
4502
  ) -> PyResult<Vec<PyConversation>> {
4492
4503
  let captured: Vec<stackforge_core::CapturedPacket> = packets
4493
4504
  .iter()
@@ -4502,7 +4513,10 @@ fn extract_flows_from_packets(
4502
4513
  })
4503
4514
  .collect();
4504
4515
 
4505
- let flow_config = config.map(|c| c.inner).unwrap_or_default();
4516
+ let mut flow_config = config.map(|c| c.inner).unwrap_or_default();
4517
+ if verbose {
4518
+ flow_config.verbose = true;
4519
+ }
4506
4520
 
4507
4521
  let conversations = stackforge_core::extract_flows_with_config(&captured, flow_config)
4508
4522
  .map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("{e}")))?;
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes