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)
98 record->data =
nullptr;
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 ==
nullptr)
139 pcap->head = pcap->tail;
143 record->next = pcap->tail;
147 if (pcap->record ==
nullptr)
148 pcap->record = record;
153BOOL pcap_has_next_record(
const rdpPcap* pcap)
157 return (pcap->file_size - (_ftelli64(pcap->fp)) > 16);
160BOOL pcap_get_next_record_header(rdpPcap* pcap, pcap_record* record)
163 WINPR_ASSERT(record);
165 if (pcap_has_next_record(pcap) != TRUE)
168 pcap_read_record_header(pcap, &record->header);
169 record->length = record->header.incl_len;
174BOOL pcap_get_next_record_content(rdpPcap* pcap, pcap_record* record)
177 WINPR_ASSERT(record);
179 return fread(record->data, record->length, 1, pcap->fp) == 1;
182BOOL pcap_get_next_record(rdpPcap* pcap, pcap_record* record)
185 WINPR_ASSERT(record);
187 return pcap_has_next_record(pcap) && pcap_read_record(pcap, record);
190rdpPcap* pcap_open(
const char* name, BOOL write)
194 rdpPcap* pcap = (rdpPcap*)calloc(1,
sizeof(rdpPcap));
198 pcap->name = _strdup(name);
200 pcap->record_count = 0;
201 pcap->fp = winpr_fopen(name, write ?
"w+b" :
"rb");
203 if (pcap->fp ==
nullptr)
208 pcap->header.magic_number = PCAP_MAGIC;
209 pcap->header.version_major = 2;
210 pcap->header.version_minor = 4;
211 pcap->header.thiszone = 0;
212 pcap->header.sigfigs = 0;
213 pcap->header.snaplen = UINT32_MAX;
214 pcap->header.network = 0;
215 if (!pcap_write_header(pcap, &pcap->header))
220 (void)_fseeki64(pcap->fp, 0, SEEK_END);
221 pcap->file_size = _ftelli64(pcap->fp);
222 (void)_fseeki64(pcap->fp, 0, SEEK_SET);
223 if (!pcap_read_header(pcap, &pcap->header))
234void pcap_flush(rdpPcap* pcap)
238 while (pcap->record !=
nullptr)
240 (void)pcap_write_record(pcap, pcap->record);
241 pcap->record = pcap->record->next;
244 if (pcap->fp !=
nullptr)
245 (void)fflush(pcap->fp);
248void pcap_close(rdpPcap* pcap)
255 if (pcap->fp !=
nullptr)
256 (void)fclose(pcap->fp);