File: tdt_desc.c

package info (click to toggle)
tsdecrypt 8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 1,084 kB
  • sloc: ansic: 13,568; makefile: 248; sh: 183
file content (175 lines) | stat: -rw-r--r-- 5,762 bytes parent folder | download | duplicates (5)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
 * TDT/TOT descriptors generator
 * Copyright (C) 2010-2011 Unix Solutions Ltd.
 *
 * Released under MIT license.
 * See LICENSE-MIT.txt for license terms.
 */
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "tsfuncs.h"

static void ts_tdt_regenerate_packet_data(struct ts_tdt *tdt) {
	uint8_t *ts_packets;
	int num_packets;
	ts_tdt_generate(tdt, &ts_packets, &num_packets);
	memcpy(tdt->section_header->packet_data, ts_packets, num_packets * TS_PACKET_SIZE);
	tdt->section_header->num_packets = num_packets;
	free(ts_packets);
}

static struct ts_tdt *ts_tdt_init_empty(struct ts_tdt *tdt, time_t ts, int tot) {
	tdt->ts_header.pid            = 0x14;
	tdt->ts_header.pusi           = 1;
	tdt->ts_header.payload_field  = 1;
	tdt->ts_header.payload_offset = 4;

	tdt->section_header->table_id                 = 0x70;
	tdt->section_header->section_syntax_indicator = 0;
	tdt->section_header->private_indicator        = 1;
	tdt->section_header->reserved1                = 3;
	tdt->section_header->section_length           = 5; // 5 bytes UTC_time

	ts_time_encode_mjd(&tdt->mjd, &tdt->bcd, &ts, NULL);
	tdt->utc = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tdt->tm);

	if (tot) {
		tdt->section_header->table_id             = 0x73;
		tdt->section_header->section_length       = 5 + 2 + 4;	// 5 bytes UTC_time, 2 bytes reserved & descripts_size, 4 bytes CRC
		tdt->reserved_3           = 0xf;
		tdt->descriptors_size     = 0;
	}

	tdt->initialized = 1;
	ts_tdt_regenerate_packet_data(tdt);

	return tdt;
}

struct ts_tdt *ts_tdt_init(struct ts_tdt *tdt, time_t ts) {
	return ts_tdt_init_empty(tdt, ts, 0);
}

struct ts_tdt *ts_tot_init(struct ts_tdt *tot, time_t ts) {
	return ts_tdt_init_empty(tot, ts, 1);
}

struct ts_tdt *ts_tdt_alloc_init(time_t ts) {
	return ts_tdt_init_empty(ts_tdt_alloc(), ts, 0);
}

struct ts_tdt *ts_tot_alloc_init(time_t ts) {
	return ts_tdt_init_empty(ts_tdt_alloc(), ts, 1);
}

void ts_tdt_set_time(struct ts_tdt *tdt, time_t now) {
	ts_time_encode_mjd(&tdt->mjd, &tdt->bcd, &now, NULL);
	tdt->utc = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tdt->tm);
	ts_tdt_regenerate_packet_data(tdt);
}

void ts_tot_set_localtime_offset(struct ts_tdt *tdt, time_t now, time_t change_time, uint8_t polarity, uint16_t ofs, uint16_t ofs_next) {
	if (tdt->section_header->table_id != 0x73)
		return;

	ts_time_encode_mjd(&tdt->mjd, &tdt->bcd, &now, NULL);
	tdt->utc = ts_time_decode_mjd(tdt->mjd, tdt->bcd, &tdt->tm);

	uint16_t mjd = 0;
	uint32_t bcd = 0;
	ts_time_encode_mjd(&mjd, &bcd, &change_time, NULL);

	uint8_t *lto; // Local time offset
	if (tdt->descriptors_size == 0) {
		tdt->descriptors_size = 15;
		tdt->descriptors = calloc(1, tdt->descriptors_size);
		tdt->section_header->section_length += tdt->descriptors_size;
	}
	lto = tdt->descriptors;
	lto[0     ]  = 0x58;		// Descriptor tag
	lto[1     ]  = 13;			// 13 octets
	lto[2 +  0]  = 'B';			// Country code
	lto[2 +  1]  = 'U';
	lto[2 +  2]  = 'L';
	lto[2 +  3]  = 0;			// 111111xx (Country region,   6 bit)
	lto[2 +  3] |= bit_2;		// xxxxxx1x (Reserved,         1 bit) !!!!
	lto[2 +  3] |= polarity;	// xxxxxxx1 (Polarity,         1 bit, 0 +utc, 1 -utc) !!!!

	lto[2 +  4]  = ofs >> 8;	// (LocalTime offset  16 bits, bcd)
	lto[2 +  5]  = ofs &~ 0xff00;

	lto[2 +  6]  = mjd >> 8;	// Time of change (40 bcd)
	lto[2 +  7]  = mjd &~ 0xff00;
	lto[2 +  8]  = bcd >> 16;
	lto[2 +  9]  = bcd >> 8;
	lto[2 + 10]  = bcd &~ 0xffff00;

	lto[2 + 11]  = ofs_next >> 8; // Next time offset (16 bits, bcd)
	lto[2 + 12]  = ofs_next &~ 0xff00;

	ts_tdt_regenerate_packet_data(tdt);
}

// Calculate change time for European summer time, see:
// http://en.wikipedia.org/wiki/European_Summer_Time
static time_t euro_dst_start(int year) {
	struct tm tm;
	int dst_start_date;
	memset(&tm, 0, sizeof(struct tm));
	tm.tm_year = year - 1900;
	tm.tm_mon  = 2; // March
	tm.tm_mday = (31 - (5 * year / 4 + 4) % 7); // Sunday DST_START March   at 01:00 GMT
	tm.tm_hour = 1;
	dst_start_date = timegm(&tm);
	//ts_LOGf("year: %d ts: %d dst_start: %s", year, dst_start_date, asctime(&tm));
	return dst_start_date;
}

static time_t euro_dst_end(int year) {
	struct tm tm;
	int dst_end_date;
	memset(&tm, 0, sizeof(struct tm));
	tm.tm_year = year - 1900;
	tm.tm_mon  = 9; // October
	tm.tm_mday = (31 - (5 * year / 4 + 1) % 7); // Sunday DST_END   October at 01:00 GMT
	tm.tm_hour = 1;
	dst_end_date = timegm(&tm);
	//ts_LOGf("year: %d ts: %d dst_end: %s", year, dst_end_date, asctime(&tm));
	return dst_end_date;
}

void ts_tot_set_localtime_offset_sofia(struct ts_tdt *tdt, time_t now) {
	uint8_t  polarity = 0;	// 0 == UTC + offset, 1 == UTC - offset
	time_t   change_time;	// When the next DST change will be
	uint16_t current_offset;
	uint16_t next_offset;
	struct tm tm;

	gmtime_r(&now, &tm);
	//ts_LOGf("nowts: %d now: %s", now, asctime(&tm));
	int curyear  = tm.tm_year + 1900;
	int dst_start_date = euro_dst_start(curyear);
	int dst_end_date   = euro_dst_end(curyear);
	if (now < dst_start_date) {
		current_offset = 0x0200; // We are in winter time now
		next_offset    = 0x0300; // Next is the summer
		change_time    = dst_start_date;
	} else {
		if (now >= dst_start_date && now < dst_end_date) {
			current_offset = 0x0300; // We are in summer time time
			next_offset    = 0x0200; // Next time it should be winter
			change_time    = dst_end_date;
		} else {
			current_offset = 0x0200; // We are in winter time
			next_offset    = 0x0300; // Next time it should be summer
			change_time    = euro_dst_start(curyear + 1);
		}
	}
	//ts_LOGf("curofs: %04x next_ofs: %04x change_time:%d\n", current_offset, next_offset, change_time);
	ts_tot_set_localtime_offset(tdt, now, change_time, polarity, current_offset, next_offset);
}