-
Notifications
You must be signed in to change notification settings - Fork 1
/
filter.c
97 lines (87 loc) · 2.33 KB
/
filter.c
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
#include "common.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)) {
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);
}
}