summaryrefslogtreecommitdiff
path: root/filter.c
blob: 880edca619811277455f4850cf8c5642985e70cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "common.h"

//#include <unistd.h>
//#include <fcntl.h>
//#include <sys/types.h>
//#include <sys/socket.h>


cPvrSectionFilter::cPvrSectionFilter(u_short Pid, u_char Tid, u_char Mask)
{
  filterData.pid = Pid;
  filterData.tid = Tid;
  filterData.mask = Mask;

  handle[0] = handle[1] = -1;
  if (socketpair(AF_UNIX, SOCK_DGRAM, 0, handle) != 0) {
    log(pvrERROR, "cPvrSectionFilter(): can't open socketpair");
    Close();
    }
  else if ((fcntl(handle[0], F_SETFL, O_NONBLOCK) != 0) || (fcntl(handle[1], F_SETFL, O_NONBLOCK) != 0)) {
    log(pvrERROR, "cPvrSectionFilter(): can't switch socketpair to unblocked mode");
    Close();
    }
}

cPvrSectionFilter::~cPvrSectionFilter(void)
{
 Close();
}

void cPvrSectionFilter::Close(void)
{
  int tmp = handle[1];
  handle[1] = -1;
  if (tmp >= 0)
     close(tmp);
  tmp = handle[0];
  handle[0] = -1;
  if (tmp >= 0)
     close(tmp);
}

int  cPvrSectionFilter::GetHandle() const
{
  return handle[0];
}

cPvrSectionHandler::cPvrSectionHandler()
{
}

cPvrSectionHandler::~cPvrSectionHandler()
{
  filters.Clear();
}

int   cPvrSectionHandler::AddFilter(u_short Pid, u_char Tid, u_char Mask)
{
  cPvrSectionFilter *filter = new cPvrSectionFilter(Pid, Tid, Mask);
  int handle = filter->GetHandle();
  if (handle < 0)
    delete filter;
  else
    filters.Add(filter);
  return handle;
}

void  cPvrSectionHandler::RemoveFilter(int Handle)
{
  cPvrSectionFilter  *filter = filters.First();
  while (filter) {
    if (filter->GetHandle() == Handle) {
      filters.Del(filter, true);
      break;
      }
    filter = filters.Next(filter);
  }
}

void  cPvrSectionHandler::ProcessTSPacket(const u_char *Data)
{
  if ((filters.Count() == 0) || (Data == 0))
    return;
  uint8_t section_len = ((Data[7] & 0x0F) << 8) + Data[7];
  if (section_len == 0)
    return;
  if ((Data[1] & 0x40) == 0)
    return;
  u_short pid = ((Data[1] & 0x1F) << 8) + Data[2];
  u_char  tid = Data[5];
  size_t  written = 0;
  uint8_t section_start = Data[4] + 5;
  section_len += 3;
  cPvrSectionFilter  *filter = filters.First();
  while (filter) {
    if (filter->filterData.Matches(pid, tid)) {
      //log(pvrDEBUG2, "cPvrSectionHandler::ProcessTSPacket(): pid = %d, tid = %d, len = %d, start = %d",
      //    pid, tid, section_len, section_start);
      written = write(filter->handle[1], Data + section_start, section_len);
      if (written != section_len)
        log(pvrERROR, "cPvrSectionHandler::ProcessTSPacket(): written only %d instead of %d", written, section_len);
      }
    filter = filters.Next(filter);
  }
}