Browse Source

Add struct io and use it for input and output

Georgi Chorbadzhiyski 13 years ago
parent
commit
51991dbfae
5 changed files with 117 additions and 54 deletions
  1. 9
    3
      data.c
  2. 19
    7
      data.h
  3. 78
    33
      tsdecrypt.c
  4. 10
    10
      udp.c
  5. 1
    1
      udp.h

+ 9
- 3
data.c View File

@@ -42,10 +42,13 @@ void data_init(struct ts *ts) {
42 42
 	ts->req_CA_sys  = CA_CONNAX;
43 43
 	ts->emm_send    = 1;
44 44
 	ts->pid_filter  = 0;
45
-	ts->output_ttl  = 1;
46 45
 
47
-	ts->input_fd    = 0; // stdin
48
-	ts->output_fd   = 1; // stdout
46
+	ts->input.fd    = 0; // STDIN
47
+	ts->input.type  = FILE_IO;
48
+
49
+	ts->output.fd   = 1; // STDOUT
50
+	ts->output.type = FILE_IO;
51
+	ts->output.ttl  = 1;
49 52
 }
50 53
 
51 54
 void data_free(struct ts *ts) {
@@ -62,4 +65,7 @@ void data_free(struct ts *ts) {
62 65
 
63 66
 	dvbcsa_key_free(ts->key.csakey[0]);
64 67
 	dvbcsa_key_free(ts->key.csakey[1]);
68
+
69
+	FREE(ts->input.fname);
70
+	FREE(ts->output.fname);
65 71
 }

+ 19
- 7
data.h View File

@@ -35,6 +35,23 @@ struct camd35 {
35 35
 	struct key		*key;
36 36
 };
37 37
 
38
+enum io_type {
39
+	FILE_IO,
40
+	NET_IO,
41
+	WTF_IO
42
+};
43
+
44
+struct io {
45
+	int					fd;
46
+	enum io_type		type;
47
+	char				*fname;
48
+	struct in_addr		addr;
49
+	unsigned int		port;
50
+	// Used only for output
51
+	int					ttl;
52
+	struct in_addr		intf;
53
+};
54
+
38 55
 struct ts {
39 56
 	// Stream handling
40 57
 	struct ts_pat		*pat, *curpat;
@@ -59,13 +76,8 @@ struct ts {
59 76
 	int					emm_send;
60 77
 	int					pid_filter;
61 78
 
62
-	struct in_addr		output_addr;
63
-	unsigned int		output_port;
64
-	int					output_ttl;
65
-	struct in_addr		output_intf;
66
-
67
-	int					input_fd;
68
-	int					output_fd;
79
+	struct io			input;
80
+	struct io			output;
69 81
 
70 82
 	int					debug_level;
71 83
 };

+ 78
- 33
tsdecrypt.c View File

@@ -2,6 +2,10 @@
2 2
 #include <stdlib.h>
3 3
 #include <unistd.h>
4 4
 #include <string.h>
5
+#include <sys/types.h>
6
+#include <sys/stat.h>
7
+#include <fcntl.h>
8
+#include <errno.h>
5 9
 
6 10
 #include <dvbcsa/dvbcsa.h>
7 11
 
@@ -25,24 +29,33 @@ void LOG_func(const char *msg) {
25 29
 }
26 30
 
27 31
 void show_help(struct ts *ts) {
28
-	printf("ts v1.0\n");
32
+	printf("tsdecrypt v1.0\n");
29 33
 	printf("Copyright (c) 2011 Unix Solutions Ltd.\n");
30 34
 	printf("\n");
31
-	printf("	Usage: ts [opts] < mpeg_ts\n");
35
+	printf("	Usage: tsdecrypt [opts]\n");
36
+	printf("\n");
37
+	printf("  Input options:\n");
38
+	printf("    -I input       | Where to read from. Supports files and multicast\n");
39
+	printf("                   |    -I 224.0.0.1:5000 (multicast receive)\n");
40
+	printf("                   |    -I file.ts        (read from file)\n");
41
+	printf("                   |    -I -              (read from STDIN, the default)\n");
32 42
 	printf("\n");
33
-	printf("  Options:\n");
34 43
 	printf("    -c ca_system   | default: %s valid: IRDETO, CONNAX, CRYPTOWORKS\n", ts_get_CA_sys_txt(ts->req_CA_sys));
35 44
 	printf("\n");
45
+	printf("  Output options:\n");
46
+	printf("    -O output      | Where to send output. Supports files and multicast\n");
47
+	printf("                   |    -O 239.0.0.1:5000 (multicast send)\n");
48
+	printf("                   |    -O file.ts        (write to file)\n");
49
+	printf("                   |    -O -              (write to STDOUT, the default)\n");
50
+	printf("\n");
51
+	printf("    -i output_intf | default: %s\n", inet_ntoa(ts->output.intf));
52
+	printf("    -t output_ttl  | default: %d\n", ts->output.ttl);
53
+	printf("\n");
36 54
 	printf("  CAMD35 server options:\n");
37 55
 	printf("    -s server_addr | default: disabled (format 1.2.3.4:2233)\n");
38 56
 	printf("    -U server_user | default: %s\n", ts->camd35.user);
39 57
 	printf("    -P server_pass | default: %s\n", ts->camd35.pass);
40 58
 	printf("\n");
41
-	printf("  Output options (if output is disabled stdout is used for output):\n");
42
-	printf("    -o output_addr | default: disabled (format: 239.78.78.78:5000)\n");
43
-	printf("    -i output_intf | default: %s\n", inet_ntoa(ts->output_intf));
44
-	printf("    -t output_ttl  | default: %d\n", ts->output_ttl);
45
-	printf("\n");
46 59
 	printf("  Filtering options:\n");
47 60
 	printf("    -e             | EMM send (default: %s).\n", ts->emm_send ? "enabled" : "disabled");
48 61
 	printf("                   | - Send EMMs to CAMD server for processing.\n");
@@ -51,7 +64,7 @@ void show_help(struct ts *ts) {
51 64
 	printf("                   | - When PID filter is enabled only PAT/PMT/SDT/data\n");
52 65
 	printf("                   | - packets are left in the output.\n");
53 66
 	printf("\n");
54
-	printf("    -D debug_level | Message debug level. Bigger levels includes the levels bellow.\n");
67
+	printf("    -D debug_level | Message debug level.\n");
55 68
 	printf("                   |    0 - default messages\n");
56 69
 	printf("                   |    1 - show PSI tables\n");
57 70
 	printf("                   |    2 - show EMMs\n");
@@ -60,9 +73,32 @@ void show_help(struct ts *ts) {
60 73
 	printf("\n");
61 74
 }
62 75
 
76
+static int parse_io_param(struct io *io, char *opt, int open_flags, mode_t open_mode) {
77
+	io->type = WTF_IO;
78
+	char *p = strrchr(opt, ':');
79
+	if (!p) {
80
+		io->type = FILE_IO;
81
+		if (strcmp(opt, "-") != 0) {
82
+			io->fd = open(opt, open_flags, open_mode);
83
+			if (io->fd < 0) {
84
+				fprintf(stderr, "ERROR: Can not open file (%s): %s\n", opt, strerror(errno));
85
+				exit(1);
86
+			}
87
+		}
88
+		io->fname = strdup(opt);
89
+		return 0;
90
+	}
91
+	*p = 0x00;
92
+	io->type = NET_IO;
93
+	io->port = atoi(p + 1);
94
+	if (inet_aton(opt, &io->addr) == 0)
95
+		return 1;
96
+	return 0;
97
+}
98
+
63 99
 void parse_options(struct ts *ts, int argc, char **argv) {
64
-	int j, ca_err = 0, server_err = 1, output_addr_err = 0, output_intf_err = 0;
65
-	while ((j = getopt(argc, argv, "cFs:o:i:t:U:P:epD:h")) != -1) {
100
+	int j, ca_err = 0, server_err = 1, input_addr_err = 0, output_addr_err = 0, output_intf_err = 0;
101
+	while ((j = getopt(argc, argv, "cFs:I:O:i:t:U:P:epD:h")) != -1) {
66 102
 		char *p = NULL;
67 103
 		switch (j) {
68 104
 			case 'c':
@@ -88,21 +124,21 @@ void parse_options(struct ts *ts, int argc, char **argv) {
88 124
 					server_err = 0;
89 125
 				break;
90 126
 
91
-			case 'o':
92
-				p = strrchr(optarg, ':');
93
-				if (p) {
94
-					*p = 0x00;
95
-					ts->output_port = atoi(p + 1);
96
-				}
97
-				if (inet_aton(optarg, &ts->output_addr) == 0)
98
-					output_addr_err = 1;
127
+			case 'I':
128
+				input_addr_err = parse_io_param(&ts->input, optarg, O_RDONLY, 0);
99 129
 				break;
130
+			case 'O':
131
+				output_addr_err = parse_io_param(&ts->output, optarg,
132
+					O_CREAT | O_WRONLY | O_TRUNC,
133
+					S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
134
+				break;
135
+
100 136
 			case 'i':
101
-				if (inet_aton(optarg, &ts->output_intf) == 0)
137
+				if (inet_aton(optarg, &ts->output.intf) == 0)
102 138
 					output_intf_err = 1;
103 139
 				break;
104 140
 			case 't':
105
-				ts->output_ttl = atoi(optarg);
141
+				ts->output.ttl = atoi(optarg);
106 142
 				break;
107 143
 
108 144
 			case 'U':
@@ -130,12 +166,14 @@ void parse_options(struct ts *ts, int argc, char **argv) {
130 166
 				exit(0);
131 167
 		}
132 168
 	}
133
-	if (ca_err || server_err) {
169
+	if (ca_err || server_err || input_addr_err || output_addr_err || ts->input.type == WTF_IO || ts->output.type == WTF_IO) {
134 170
 		show_help(ts);
135 171
 		if (ca_err)
136 172
 			fprintf(stderr, "ERROR: Requested CA system is unsupported.\n");
137 173
 		if (server_err)
138 174
 			fprintf(stderr, "ERROR: Server IP address is not set or it is invalid.\n");
175
+		if (input_addr_err)
176
+			fprintf(stderr, "ERROR: Input IP address is invalid.\n");
139 177
 		if (output_addr_err)
140 178
 			fprintf(stderr, "ERROR: Output IP address is invalid.\n");
141 179
 		if (output_intf_err)
@@ -143,14 +181,21 @@ void parse_options(struct ts *ts, int argc, char **argv) {
143 181
 		exit(1);
144 182
 	}
145 183
 	ts_LOGf("CA System  : %s\n", ts_get_CA_sys_txt(ts->req_CA_sys));
146
-	ts_LOGf("Server addr: %s:%u\n", inet_ntoa(ts->camd35.server_addr), ts->camd35.server_port);
184
+	if (ts->input.type == NET_IO) {
185
+		ts_LOGf("Input addr : udp://%s:%u/\n", inet_ntoa(ts->input.addr), ts->input.port);
186
+	} else if (ts->input.type == FILE_IO) {
187
+		ts_LOGf("Input file : %s\n", ts->input.fd == 0 ? "STDIN" : ts->input.fname);
188
+	}
189
+	if (ts->output.type == NET_IO) {
190
+		ts_LOGf("Output addr: udp://%s:%u/\n", inet_ntoa(ts->output.addr), ts->output.port);
191
+		ts_LOGf("Output intf: %s\n", inet_ntoa(ts->output.intf));
192
+		ts_LOGf("Output ttl : %d\n", ts->output.ttl);
193
+	} else if (ts->output.type == FILE_IO) {
194
+		ts_LOGf("Output file: %s\n", ts->output.fd == 1 ? "STDOUT" : ts->output.fname);
195
+	}
196
+	ts_LOGf("Server addr: tcp://%s:%u/\n", inet_ntoa(ts->camd35.server_addr), ts->camd35.server_port);
147 197
 	ts_LOGf("Server user: %s\n", ts->camd35.user);
148 198
 	ts_LOGf("Server pass: %s\n", ts->camd35.pass);
149
-	if (ts->output_port) {
150
-		ts_LOGf("Output addr: %s:%u\n", inet_ntoa(ts->output_addr), ts->output_port);
151
-		ts_LOGf("Output intf: %s\n", inet_ntoa(ts->output_intf));
152
-		ts_LOGf("Output ttl : %d\n", ts->output_ttl);
153
-	}
154 199
 	ts_LOGf("EMM send   : %s\n", ts->emm_send   ? "enabled" : "disabled");
155 200
 	ts_LOGf("PID filter : %s\n", ts->pid_filter ? "enabled" : "disabled");
156 201
 }
@@ -228,9 +273,9 @@ void ts_write_packets(struct ts *ts, uint8_t *data, ssize_t data_len) {
228 273
 		uint16_t pid = ts_packet_get_pid(ts_packet);
229 274
 		if (ts->pid_filter) {
230 275
 			if (pidmap_get(&ts->pidmap, pid)) // PAT or allowed PIDs
231
-				write(ts->output_fd, ts_packet, 188);
276
+				write(ts->output.fd, ts_packet, 188);
232 277
 		} else {
233
-			write(ts->output_fd, ts_packet, 188);
278
+			write(ts->output.fd, ts_packet, 188);
234 279
 		}
235 280
 	}
236 281
 }
@@ -249,12 +294,12 @@ int main(int argc, char **argv) {
249 294
 	parse_options(&ts, argc, argv);
250 295
 
251 296
 	camd35_connect(&ts.camd35);
252
-	if (ts.output_port)
253
-		if (udp_connect_output(&ts) < 1)
297
+	if (ts.output.type == NET_IO)
298
+		if (udp_connect_output(&ts.output) < 1)
254 299
 			goto EXIT;
255 300
 
256 301
 	do {
257
-		readen = read(ts.input_fd, ts_packet, FRAME_SIZE);
302
+		readen = read(ts.input.fd, ts_packet, FRAME_SIZE);
258 303
 		if (readen > 0) {
259 304
 			ts_process_packets(&ts, ts_packet, readen);
260 305
 			ts_write_packets(&ts, ts_packet, readen);

+ 10
- 10
udp.c View File

@@ -18,7 +18,7 @@ static void set_sock_nonblock(int sockfd) {
18 18
 	fcntl(sockfd, F_SETFL, arg);
19 19
 }
20 20
 
21
-int udp_connect_output(struct ts *ts) {
21
+int udp_connect_output(struct io *io) {
22 22
 	int sock = socket(AF_INET, SOCK_DGRAM, 0);
23 23
 	if (sock < 0) {
24 24
 		ts_LOGf("socket(SOCK_DGRAM): %s\n", strerror(errno));
@@ -26,22 +26,22 @@ int udp_connect_output(struct ts *ts) {
26 26
 	}
27 27
 
28 28
 	ts_LOGf("Connecting output to udp://%s:%d ttl:%d\n",
29
-		inet_ntoa(ts->output_addr), ts->output_port, ts->output_ttl);
29
+		inet_ntoa(io->addr), io->port, io->ttl);
30 30
 
31 31
 	int on = 1;
32 32
 	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
33 33
 	set_sock_nonblock(sock);
34 34
 
35 35
 	// subscribe to multicast group
36
-	if (IN_MULTICAST(ntohl(ts->output_addr.s_addr))) {
37
-		int ttl = ts->output_ttl;
36
+	if (IN_MULTICAST(ntohl(io->addr.s_addr))) {
37
+		int ttl = io->ttl;
38 38
 		if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
39 39
 			ts_LOGf("setsockopt(IP_MUTICAST_TTL): %s\n", strerror(errno));
40 40
 			close(sock);
41 41
 			return -1;
42 42
 		}
43
-		if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &ts->output_intf, sizeof(ts->output_intf)) < 0) {
44
-			ts_LOGf("setsockopt(IP_MUTICAST_IF %s): %s\n", inet_ntoa(ts->output_intf), strerror(errno));
43
+		if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &io->intf, sizeof(io->intf)) < 0) {
44
+			ts_LOGf("setsockopt(IP_MUTICAST_IF %s): %s\n", inet_ntoa(io->intf), strerror(errno));
45 45
 			close(sock);
46 46
 			return -1;
47 47
 		}
@@ -50,15 +50,15 @@ int udp_connect_output(struct ts *ts) {
50 50
 	struct sockaddr_in sockaddr;
51 51
 	memset(&sockaddr, 0, sizeof(sockaddr));
52 52
 	sockaddr.sin_family			= AF_INET;
53
-	sockaddr.sin_addr.s_addr	= ts->output_addr.s_addr;
54
-	sockaddr.sin_port			= htons(ts->output_port);
53
+	sockaddr.sin_addr.s_addr	= io->addr.s_addr;
54
+	sockaddr.sin_port			= htons(io->port);
55 55
 	if (connect(sock, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
56 56
 		ts_LOGf("udp_connect() error: %s\n", strerror(errno));
57 57
 		close(sock);
58 58
 		return -1;
59 59
 	}
60
-	ts->output_fd = sock;
61
-	ts_LOGf("Output connected to fd:%d\n", ts->output_fd);
60
+	io->fd = sock;
61
+	ts_LOGf("Output connected to fd:%d\n", io->fd);
62 62
 
63 63
 	return 1;
64 64
 }

+ 1
- 1
udp.h View File

@@ -3,6 +3,6 @@
3 3
 
4 4
 #include "data.h"
5 5
 
6
-int udp_connect_output(struct ts *ts);
6
+int udp_connect_output(struct io *io);
7 7
 
8 8
 #endif

Loading…
Cancel
Save