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);