netkitty
Version:
Network tools kit
99 lines (85 loc) • 3.25 kB
text/typescript
import EventEmitter from 'events'
import {createWriteStream, existsSync, statSync, WriteStream} from 'node:fs'
import {GeneratePCAPData, GeneratePCAPHeader} from './PCAPGenerator'
import {IPcapPacketInfo} from './interfaces/IPcapPacketInfo'
export interface IPcapWriterOptions {
filename: string
}
export class PcapWriter extends EventEmitter {
public readonly filename: string
protected readonly writeStream: WriteStream
protected closed: boolean = false
protected index: number = 0
protected offset: number = 0
public get wroteCount(): number {
return this.index
}
constructor(options: IPcapWriterOptions) {
super()
this.filename = options.filename
if (!existsSync(this.filename)) {
this.writeStream = createWriteStream(this.filename, {autoClose: false, flags: 'w'})
const header: Buffer = GeneratePCAPHeader()
this.writeStream.write(header)
this.offset += header.length
} else {
this.writeStream = createWriteStream(this.filename, {autoClose: false, flags: 'a'})
this.offset += statSync(this.filename).size
}
}
/**
* Write packet to pcap file
* @param packet
* @param seconds
* @param microseconds
*/
public write(packet: Buffer, seconds: number, microseconds: number): void {
if (this.closed) return
this.index += 1
const startOffset: number = this.offset
const packetLength: number = packet.length
const pcapData: Buffer = GeneratePCAPData({
buffer: packet,
timestamp: Date.now(),
microsecond: {
seconds: seconds,
microseconds: microseconds
}
})
this.offset += pcapData.length
const packetOffset: number = this.offset - packetLength
const recordHeaderLength: number = packetOffset - startOffset
const wrotePacketInfo: IPcapPacketInfo = {
index: this.index,
offset: startOffset,
length: pcapData.length,
recordHeaderOffset: startOffset,
recordHeaderLength: recordHeaderLength,
packetOffset: packetOffset,
packetLength: packetLength,
seconds: seconds,
microseconds: microseconds,
packet: packet.toString('base64')
}
this.writeStream.write(pcapData, (): boolean => this.emit('packet', wrotePacketInfo))
}
/**
* Close pcap writer
*/
public async close(): Promise<void> {
this.closed = true
return new Promise((resolve, reject): void => {
this.writeStream.close(err => err ? reject(err) : resolve())
})
}
public on(eventName: 'packet', listener: (wrotePacketInfo: IPcapPacketInfo) => void): this
public on(eventName: string, listener: (...args: any[]) => void): this {
super.on(eventName, listener)
return this
}
public once(eventName: 'packet', listener: (wrotePacketInfo: IPcapPacketInfo) => void): this
public once(eventName: string, listener: (...args: any[]) => void): this {
super.once(eventName, listener)
return this
}
}