20#include <freerdp/config.h>
26#include <winpr/wtypes.h>
27#include <winpr/assert.h>
28#include <winpr/file.h>
30#include <winpr/sysinfo.h>
32#include <freerdp/types.h>
33#include <freerdp/utils/pcap.h>
35#define PCAP_MAGIC 0xA1B2C3D4
50static BOOL pcap_read_header(rdpPcap* pcap,
pcap_header* header)
55 return fread(header,
sizeof(
pcap_header), 1, pcap->fp) == 1;
58static BOOL pcap_write_header(rdpPcap* pcap,
const pcap_header* header)
63 return fwrite(header,
sizeof(
pcap_header), 1, pcap->fp) == 1;
82static BOOL pcap_read_record(rdpPcap* pcap, pcap_record* record)
87 if (!pcap_read_record_header(pcap, &record->header))
90 record->length = record->header.incl_len;
91 record->data = malloc(record->length);
95 if (fread(record->data, record->length, 1, pcap->fp) != 1)
104static BOOL pcap_write_record(rdpPcap* pcap,
const pcap_record* record)
107 WINPR_ASSERT(record);
109 return pcap_write_record_header(pcap, &record->header) &&
110 (fwrite(record->cdata, record->length, 1, pcap->fp) == 1);
113BOOL pcap_add_record(rdpPcap* pcap,
const void* data,
size_t length)
116 WINPR_ASSERT(data || (length == 0));
117 WINPR_ASSERT(length <= UINT32_MAX);
119 pcap_record* record = (pcap_record*)calloc(1,
sizeof(pcap_record));
123 record->cdata = data;
124 record->length = (UINT32)length;
125 record->header.incl_len = (UINT32)length;
126 record->header.orig_len = (UINT32)length;
128 const UINT64 ns = winpr_GetUnixTimeNS();
130 record->header.ts_sec = (UINT32)WINPR_TIME_NS_TO_S(ns);
131 record->header.ts_usec = (UINT32)WINPR_TIME_NS_REM_US(ns);
133 if (pcap->tail == NULL)
139 pcap->head = pcap->tail;
143 record->next = pcap->tail;
147 if (pcap->record == NULL)
148 pcap->record = record;
153BOOL pcap_has_next_record(
const rdpPcap* pcap)
157 if (pcap->file_size - (_ftelli64(pcap->fp)) <= 16)
163BOOL pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record)
166 WINPR_ASSERT(record);
168 if (pcap_has_next_record(pcap) != TRUE)
171 pcap_read_record_header(pcap, &record->header);
172 record->length = record->header.incl_len;
177BOOL pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record)
180 WINPR_ASSERT(record);
182 return fread(record->data, record->length, 1, pcap->fp) == 1;
185BOOL pcap_get_next_record(rdpPcap* pcap, pcap_record* record)
188 WINPR_ASSERT(record);
190 return pcap_has_next_record(pcap) && pcap_read_record(pcap, record);
193rdpPcap* pcap_open(
const char* name, BOOL write)
197 rdpPcap* pcap = (rdpPcap*)calloc(1,
sizeof(rdpPcap));
201 pcap->name = _strdup(name);
203 pcap->record_count = 0;
204 pcap->fp = winpr_fopen(name, write ?
"w+b" :
"rb");
206 if (pcap->fp == NULL)
211 pcap->header.magic_number = PCAP_MAGIC;
212 pcap->header.version_major = 2;
213 pcap->header.version_minor = 4;
214 pcap->header.thiszone = 0;
215 pcap->header.sigfigs = 0;
216 pcap->header.snaplen = UINT32_MAX;
217 pcap->header.network = 0;
218 if (!pcap_write_header(pcap, &pcap->header))
223 (void)_fseeki64(pcap->fp, 0, SEEK_END);
224 pcap->file_size = _ftelli64(pcap->fp);
225 (void)_fseeki64(pcap->fp, 0, SEEK_SET);
226 if (!pcap_read_header(pcap, &pcap->header))
237void pcap_flush(rdpPcap* pcap)
241 while (pcap->record != NULL)
243 (void)pcap_write_record(pcap, pcap->record);
244 pcap->record = pcap->record->next;
247 if (pcap->fp != NULL)
248 (void)fflush(pcap->fp);
251void pcap_close(rdpPcap* pcap)
258 if (pcap->fp != NULL)
259 (void)fclose(pcap->fp);