fix memory leak when reloading the application
[dvblast.git] / mrtg-cnt.c
blob12a5c79c36ad78d3922212a9bb1bb714a7098e0c
1 /*****************************************************************************
2 * mrtg-cnt.c Handle dvb TS packets and count them for MRTG
3 *****************************************************************************
4 * Copyright Tripleplay service 2004,2005,2011
6 * Author: Andy Lindsay <a.lindsay@tripleplay-services.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /* vim: set shiftwidth=4 tabstop=4 expandtab autoindent : */
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdbool.h>
30 #include <sys/types.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <sys/time.h>
36 #include "dvblast.h"
38 // File handle
39 static FILE *mrtg_fh = NULL;
41 // Counts
42 static long long l_mrtg_packets = 0; // Packets received
43 static long long l_mrtg_seq_err_packets = 0; // Out of sequence packets received
44 static long long l_mrtg_error_packets = 0; // Packets received with the error flag set
45 static long long l_mrtg_scram_packets = 0; // Scrambled Packets received
47 // Reporting timer
48 #if defined( WIN32 )
49 static LARGE_INTEGER mrtg_time;
50 static LARGE_INTEGER mrtg_inc;
51 #else
52 static struct timeval mrtg_time = { 0, 0 };
53 #endif
55 // Define the dump period in seconds
56 #define MRTG_INTERVAL 10
58 // Pid sequence numbers
59 #define PIDS 0x2000
60 static signed char i_pid_seq[PIDS];
62 // Report the mrtg counters: bytes received, error packets & sequence errors
63 static void dumpCounts()
65 unsigned int multiplier = 1; //MRTG_INTERVAL;
66 if(mrtg_fh) {
67 rewind(mrtg_fh);
68 fprintf(mrtg_fh, "%lld %lld %lld %lld\n",
69 l_mrtg_packets * 188 * multiplier,
70 l_mrtg_error_packets * multiplier,
71 l_mrtg_seq_err_packets * multiplier,
72 l_mrtg_scram_packets * multiplier);
73 fflush(mrtg_fh);
77 // analyse the input block counting packets and errors
78 // The input is a pointer to a block_t structure, which might be a linked list
79 // of blocks. Each block has one TS packet.
80 void mrtgAnalyse(block_t * p_ts)
82 unsigned int i_pid;
83 block_t *p_block = p_ts;
85 if (mrtg_fh == NULL) return;
87 while (p_block != NULL) {
88 uint8_t *ts_packet = p_block->p_ts;
90 char i_seq, i_last_seq;
91 l_mrtg_packets++;
93 if (ts_packet[0] != 0x47) {
94 l_mrtg_error_packets++;
95 p_block = p_block->p_next;
96 continue;
99 if (ts_packet[1] & 0x80) {
100 l_mrtg_error_packets++;
101 p_block = p_block->p_next;
102 continue;
105 i_pid = (ts_packet[1] & 0x1f) << 8 | ts_packet[2];
107 // Just count null packets - don't check the sequence numbering
108 if (i_pid == 0x1fff) {
109 p_block = p_block->p_next;
110 continue;
113 if (ts_packet[3] & 0xc0) {
114 l_mrtg_scram_packets++;
116 // Check the sequence numbering
117 i_seq = ts_packet[3] & 0xf;
118 i_last_seq = i_pid_seq[i_pid];
120 if (i_last_seq == -1) {
121 // First packet - ignore the sequence
122 } else if (ts_packet[3] & 0x10) {
123 // Packet contains payload - sequence should be up by one
124 if (i_seq != ((i_last_seq + 1) & 0x0f)) {
125 l_mrtg_seq_err_packets++;
127 } else {
128 // Packet contains no payload - sequence should be unchanged
129 if (i_seq != i_last_seq) {
130 l_mrtg_seq_err_packets++;
133 i_pid_seq[i_pid] = i_seq;
135 // Look at next block
136 p_block = p_block->p_next;
139 // All blocks processed. See if we need to dump the stats
140 struct timeval now;
141 gettimeofday(&now, NULL);
142 if (timercmp(&now, &mrtg_time, >)) {
143 // Time to report the mrtg counters
144 dumpCounts();
146 // Set the timer for next time
148 // Normally we add the interval to the previous time so that if one
149 // dump is a bit late, the next one still occurs at the correct time.
150 // However, if there is a long gap (e.g. because the channel has
151 // stopped for some time), then just rebase the timing to the current
152 // time. I've chosen MRTG_INTERVAL as the long gap - this is arbitary
153 if ((now.tv_sec - mrtg_time.tv_sec) > MRTG_INTERVAL) {
154 msg_Dbg(NULL, "Dump is %d seconds late - reset timing\n",
155 (int) (now.tv_sec - mrtg_time.tv_sec));
156 mrtg_time = now;
158 mrtg_time.tv_sec += MRTG_INTERVAL;
162 int mrtgInit(char *mrtg_file)
164 if ( !mrtg_file )
165 return -1;
167 /* Open MRTG file */
168 msg_Dbg(NULL, "Opening mrtg file %s.\n", mrtg_file);
169 if ((mrtg_fh = fopen(mrtg_file, "wb")) == NULL) {
170 msg_Err(NULL, "unable to open mrtg file");
171 return -1;
173 // Initialise the file
174 fprintf(mrtg_fh, "0 0 0 0\n");
175 fflush(mrtg_fh);
177 // Initialise the sequence numbering
178 memset(&i_pid_seq[0], -1, sizeof(signed char) * PIDS);
180 // Set the reporting timer
181 gettimeofday(&mrtg_time, NULL);
182 mrtg_time.tv_sec += MRTG_INTERVAL;
184 return 0;
187 void mrtgClose()
189 // This is only for testing when using filetest.
190 if (mrtg_fh) {
191 dumpCounts();
192 fclose(mrtg_fh);
193 mrtg_fh = NULL;