20 #include <freerdp/config.h>
26 #include <winpr/wtypes.h>
27 #include <winpr/assert.h>
28 #include <winpr/file.h>
29 #include <winpr/crt.h>
30 #include <winpr/sysinfo.h>
32 #include <freerdp/types.h>
33 #include <freerdp/utils/pcap.h>
35 #define PCAP_MAGIC 0xA1B2C3D4
50 static BOOL pcap_read_header(rdpPcap* pcap,
pcap_header* header)
55 return fread(header,
sizeof(
pcap_header), 1, pcap->fp) == 1;
58 static BOOL pcap_write_header(rdpPcap* pcap,
const pcap_header* header)
63 return fwrite(header,
sizeof(
pcap_header), 1, pcap->fp) == 1;
82 static 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)
104 static 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);
113 BOOL 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;
153 BOOL pcap_has_next_record(
const rdpPcap* pcap)
157 if (pcap->file_size - (_ftelli64(pcap->fp)) <= 16)
163 BOOL 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;
177 BOOL 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;
185 BOOL 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);
193 rdpPcap* pcap_open(
const char* name, BOOL write)
195 rdpPcap* pcap = NULL;
199 pcap = (rdpPcap*)calloc(1,
sizeof(rdpPcap));
203 pcap->name = _strdup(name);
205 pcap->record_count = 0;
206 pcap->fp = winpr_fopen(name, write ?
"w+b" :
"rb");
208 if (pcap->fp == NULL)
213 pcap->header.magic_number = PCAP_MAGIC;
214 pcap->header.version_major = 2;
215 pcap->header.version_minor = 4;
216 pcap->header.thiszone = 0;
217 pcap->header.sigfigs = 0;
218 pcap->header.snaplen = UINT32_MAX;
219 pcap->header.network = 0;
220 if (!pcap_write_header(pcap, &pcap->header))
225 (void)_fseeki64(pcap->fp, 0, SEEK_END);
226 pcap->file_size = _ftelli64(pcap->fp);
227 (void)_fseeki64(pcap->fp, 0, SEEK_SET);
228 if (!pcap_read_header(pcap, &pcap->header))
239 void pcap_flush(rdpPcap* pcap)
243 while (pcap->record != NULL)
245 pcap_write_record(pcap, pcap->record);
246 pcap->record = pcap->record->next;
249 if (pcap->fp != NULL)
250 (void)fflush(pcap->fp);
253 void pcap_close(rdpPcap* pcap)
260 if (pcap->fp != NULL)
261 (void)fclose(pcap->fp);