roPcap
roPcap is used to analyze PCAP files for UDP traffic flows, prepare them for replay (optionally filtering and rewriting headers), replay them onto a network interface with drift-free pacing, and extract raw UDP payload streams from PCAP captures. It is available as of BOS 9.1.143.
If a message port is set via SetPort(), the object posts roPcapEvent messages for replay lifecycle events (started, stopped, looped, underrun, dropped).
Only one roPcap instance may exist at a time. CreateObject("roPcap") returns Invalid if another instance is already alive.
If using tmp:/ you need to be mindful of how big the PCAP is. If its large, it won’t fit into a RAM-based tmp:/ and you should use local storage instead (for example, sd:/)
ifPcap
Analyze(filename As String) As Object
Scans all packets in filename and returns a roArray of roAssociativeArray, one entry per UDP flow found. Flows are sorted by packet count in descending order. Returns an empty array if the file cannot be opened or contains no UDP flows.
Each entry in the returned array contains the following keys:
Key | Type | Description |
|---|---|---|
src_ip | String | Source IPv4 address |
src_port | Integer | Source UDP port |
dst_ip | String | Destination IPv4 address |
dst_port | Integer | Destination UDP port |
packet_count | Integer | Number of UDP packets in the flow |
Prepare(params As roAssociativeArray) As Integer
Filters packets from the input PCAP and writes a replay-ready output PCAP, optionally rewriting destination IP and UDP port headers. The source MAC address and source IP address in every output packet are always rewritten to the values of the specified network interface.
If RewriteOutputDestAddress is a multicast address, the destination MAC is derived using the RFC 1112 formula. If it is a unicast address, the destination MAC is resolved via the kernel ARP cache; the destination must already be reachable (e.g. via a prior ping) before calling Prepare().
Returns a PcapEngineError integer code; 0 on success. See Error Codes.
Required parameters:
Key | Type | Description |
|---|---|---|
InputFile | String | Path to the source PCAP file |
OutputFile | String | Path to write the prepared PCAP (must differ from InputFile) |
Interface | String | Network interface name used to resolve the source MAC and IP (e.g. "eth0") |
Optional filter parameters:
Key | Type | Description |
|---|---|---|
FilterInputSourceAddress | String | Keep only packets with this IPv4 source address |
FilterInputSourcePort | Integer | Keep only UDP packets from this source port (1024–65535) |
FilterInputDestAddress | String | Keep only packets with this IPv4 destination address |
FilterInputDestPort | Integer | Keep only UDP packets to this destination port (1024–65535) |
AutoFlowSelect | Boolean | See note below |
Optional rewrite parameters:
Key | Type | Description |
|---|---|---|
RewriteOutputDestAddress | String | Rewrite the destination IP address (unicast or multicast) |
RewriteOutputDestPort | Integer | Rewrite the UDP destination port (1024–65535) |
AutoFlowSelect default behavior: When no FilterInput* keys are supplied, AutoFlowSelect defaults to true: the flow with the highest packet count is selected automatically. When any FilterInput* key is present, AutoFlowSelect defaults to false: if the filter criteria match more than one flow, Prepare() returns PCAP_ERR_AMBIGUOUS_FLOW (-7) instead of picking one. An explicit AutoFlowSelect key always overrides the default.
ExtractStream(params As roAssociativeArray) As Integer
Concatenates the raw UDP payload bytes of every matching packet in InputFile and writes them to OutputFile. No prior Prepare() call is required. This is useful for recovering the original byte stream from a UDP capture — for example, extracting an MPEG-TS file from a TS-over-UDP recording.
The filter criteria must resolve to exactly one UDP flow. Use AutoFlowSelect to select the highest-count flow automatically when the filter is broad.
Returns a PcapEngineError integer code; 0 on success. See Error Codes. May return PCAP_ERR_READ_FAILED (-8) if the input file is corrupt or truncated.
Required parameters:
Key | Type | Description |
|---|---|---|
InputFile | String | Path to the source PCAP file |
OutputFile | String | Path to write the extracted stream; created or truncated |
Optional filter parameters:
Same as Prepare(): FilterInputSourceAddress, FilterInputSourcePort, FilterInputDestAddress, FilterInputDestPort, AutoFlowSelect (same default logic as Prepare()).
Start(params As roAssociativeArray) As Boolean
Starts replaying the prepared PCAP file on the specified network interface. Packets are paced at their original inter-packet intervals using absolute monotonic timestamps so timing overshoot on one packet cannot accumulate into drift over subsequent packets.
Blocks until the sender thread has started or failed to start. Posts a roPcapEvent with type 1 (Started) to the message port on success.
Returns True on success; False if the sender thread could not be started.
Required parameters:
Key | Type | Description |
|---|---|---|
Filename | String | Path to the prepared PCAP file to replay |
Interface | String | Network interface name to send on (e.g. "eth0") |
Optional parameters:
Key | Type | Description |
|---|---|---|
LoopCount | Integer | Number of times to loop through the file; 0 (default) loops forever |
PreloadIntoMemory | Boolean | If True, loads the entire file into RAM before replay begins (capped at 50% of total system RAM). Use this when deterministic per-packet timing is required and the file fits comfortably in memory. Default is streaming mode, which reads from disk with a 20 MiB readahead buffer and is suitable for any file size. |
Stop() As Void
Returns True while the sender thread is executing the replay loop. Returns False once the loop count is exhausted, Stop() is called, or a fatal error occurs after Start() returned True.
GetStats() As roAssociativeArray
Returns a snapshot of replay statistics. Safe to call at any time, including while replay is running.
Key | Type | Description |
|---|---|---|
packets_sent | Integer | Frames successfully transmitted since the last Start() |
packets_dropped | Integer | Frames dropped due to no buffer space / busy, since the last Start() |
loops_completed | Integer | Full loop passes that have finished cleanly |
underruns | Integer | Times the streaming readahead buffer was empty; always 0 when PreloadIntoMemory is True |
elapsed_ms | Integer | Wall-clock milliseconds since the last Start() or ResetStats() call; 0 when stopped |
timing_sample_count | Integer | Number of packets contributing to the timing fields below |
timing_mean_us | Integer | Mean timing error in microseconds; positive means the packet went out late, negative means early |
timing_min_us | Integer | Minimum (most-early) timing error in microseconds |
timing_max_us | Integer | Maximum (most-late) timing error in microseconds |
timing_stddev_us | Integer | Sample standard deviation of timing error in microseconds |
Timing fields are 0 until at least one packet has been sent.
ResetStats() As Void
Resets all replay statistics to zero. Safe to call while replay is running. Counters updated by the replay thread after the call reflect only activity since the reset.
ifMessagePort
SetPort(port As roMessagePort)
Posts messages of type roPcapEvent to the attached message port.
ifUserData
SetUserData(user_data As Object)
Sets the user data that will be returned when events are raised.
GetUserData() As Object
Returns the user data previously set via SetUserData(). Returns Invalid if no data has been set.
roPcapEvent
roPcapEvent is posted to the message port set on roPcap whenever a replay lifecycle event occurs.
ifPcapEvent
GetInt() As Integer
Returns the event type code:
Value | Name | Description |
|---|---|---|
1 | Started | Replay thread started and is sending packets |
2 | Stopped | Replay thread stopped (loop count exhausted, Stop() called, or fatal error) |
3 | Looped | One full pass completed; GetData() returns the 1-indexed loop number |
4 | Underrun | Streaming readahead buffer was empty; replay timing may have been affected |
5 | Dropped | A packet was dropped; GetData() returns the cumulative drop count at the time of the drop |
GetData() As Integer
Returns event-specific data. See the table above. Returns 0 for events where no additional data applies.
Error Codes
Prepare() and ExtractStream() return one of the following integer codes:
Value | Name | Description |
|---|---|---|
0 | PCAP_OK | Success |
-1 | PCAP_ERR_FILE_NOT_FOUND | InputFile does not exist or cannot be opened |
-2 | PCAP_ERR_INVALID_FLOW_PORT | A port value is outside the valid range [1024, 65535] |
-3 | PCAP_ERR_WRITE_FAILED | OutputFile could not be written |
-4 | PCAP_ERR_INVALID_INTERFACE | The interface name is invalid or not found on the system |
-5 | PCAP_ERR_INVALID_PARAM | An invalid parameter was supplied: bad IP address format, InputFile and OutputFile are the same path, or a unicast RewriteOutputDestAddress could not be resolved to a MAC via ARP |
-6 | PCAP_ERR_NO_MATCHING_FLOW | The filter criteria matched no flows; supply a less restrictive filter or verify the input file contains the expected traffic |
-7 | PCAP_ERR_AMBIGUOUS_FLOW | The filter criteria matched more than one distinct flow; tighten the filter to select exactly one, or set AutoFlowSelect: True to pick the highest-count flow automatically |
-8 | PCAP_ERR_READ_FAILED | ExtractStream() only: the input file is corrupt or truncated |
Examples
Analyze a PCAP File
Print all UDP flows found in a capture file:
pcap = CreateObject("roPcap")
flows = pcap.Analyze("SD:/capture.pcap")
for each flow in flows
print flow.src_ip + ":" + flow.src_port.ToStr() + " -> " + _
flow.dst_ip + ":" + flow.dst_port.ToStr() + _
" packets=" + flow.packet_count.ToStr()
end forPrepare and Replay with Event Handling
Select a flow, rewrite it to a local multicast group, and replay it three times while monitoring events:
pcap = CreateObject("roPcap")
port = CreateObject("roMessagePort")
pcap.SetPort(port)
' Step 1 — inspect the capture to find the flow
flows = pcap.Analyze("SD:/source.pcap")
if flows.Count() = 0
print "No UDP flows found"
stop
end if
' Step 2 — prepare: filter to the largest flow, rewrite destination
params = CreateObject("roAssociativeArray")
params.InputFile = "SD:/source.pcap"
params.OutputFile = "tmp:/prepared.pcap"
params.Interface = "eth0"
' AutoFlowSelect defaults to true when no FilterInput* keys are given,
' so the highest-count flow is selected automatically.
params.RewriteOutputDestAddress = "239.1.2.3"
params.RewriteOutputDestPort = 1234
result = pcap.Prepare(params)
if result <> 0
print "Prepare failed: " + result.ToStr()
stop
end if
' Step 3 — replay three times
startParams = CreateObject("roAssociativeArray")
startParams.Filename = "tmp:/prepared.pcap"
startParams.Interface = "eth0"
startParams.LoopCount = 3
if not pcap.Start(startParams)
print "Start failed"
stop
end if
' Step 4 — event loop
while True
msg = Wait(0, port)
if type(msg) = "roPcapEvent"
select case msg.GetInt()
case 3 ' Looped
print "Completed loop " + msg.GetData().ToStr()
case 5 ' Dropped
print "Drop count: " + msg.GetData().ToStr()
case 2 ' Stopped
print "Replay finished"
exit while
end select
end if
end while
stats = pcap.GetStats()
print "Sent=" + stats.packets_sent.ToStr() + _
" Dropped=" + stats.packets_dropped.ToStr() + _
" Underruns=" + stats.underruns.ToStr()Extract a Raw Stream from a PCAP
Recover an MPEG-TS file from a TS-over-UDP capture. No Prepare() or network interface is needed:
pcap = CreateObject("roPcap")
params = CreateObject("roAssociativeArray")
params.InputFile = "SD:/recording.pcap"
params.OutputFile = "SD:/extracted.ts"
' AutoFlowSelect defaults to true when no FilterInput* keys are given.
' Set explicit filter keys to target a specific flow in a multi-flow capture.
params.FilterInputDestAddress = "239.10.20.30"
params.FilterInputDestPort = 1234
' AutoFlowSelect defaults to false because FilterInput* keys are present;
' set it explicitly to true to auto-pick if the filter still matches multiple flows.
params.AutoFlowSelect = True
result = pcap.ExtractStream(params)
if result = 0
print "Stream extracted successfully"
else
print "ExtractStream failed: " + result.ToStr()
end if