enforce timeouts
[record-dvb] / record-dvb.c
1 #include <features.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/time.h>
5 #include <time.h>
6 #include <sys/socket.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/select.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <strings.h>
13
14 #include "http.h"
15 #include "mcast.h"
16 #include "sap.h"
17
18 #define CHUNKSIZE 3000
19 #define GTOD_INTERVAL 100
20 #define MAX_ERROR_SLEEP 60
21
22 void record(int(*open_fn)(char *), char *url, char *outfile, int duration)
23 {
24 struct timeval start, curr;
25 int bytes, recvd, written, count = 0;
26 int error_sleep = 0;
27 char buffer[CHUNKSIZE];
28 int in, out;
29 fd_set rfds;
30 struct timeval tv;
31 int retval;
32
33 if ((in = (*open_fn)(url)) < 0) {
34 fprintf(stderr,"Can't open url %s!\n",url);
35 exit(EXIT_FAILURE);
36 }
37
38 if ((out = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_LARGEFILE, 00644)) < 0) {
39 perror("open");
40 exit(EXIT_FAILURE);
41 }
42
43 printf("Recording from %s for %d seconds...\n", url, duration);
44
45 gettimeofday(&start, NULL);
46 curr = start;
47
48 do {
49 if (error_sleep) {
50 sleep(error_sleep);
51 printf("Reconnecting... ");
52 if ((in = (*open_fn)(url)) < 0) {
53 if (error_sleep < MAX_ERROR_SLEEP)
54 error_sleep *= 2;
55
56 if (error_sleep > MAX_ERROR_SLEEP)
57 error_sleep = MAX_ERROR_SLEEP;
58
59 printf("failed\n");
60 continue;
61 } else {
62 printf("succeeded\n");
63 error_sleep = 0;
64 }
65 }
66
67 FD_ZERO(&rfds);
68 FD_SET(in, &rfds);
69
70 tv.tv_sec = 1;
71 tv.tv_usec = 0;
72
73 if ((retval = select(in + 1, &rfds, NULL, NULL, &tv)) == -1) {
74 error_sleep = 1;
75 continue;
76 }
77
78 if (!retval) {
79 gettimeofday(&curr, NULL);
80 continue;
81 }
82
83 if ((recvd = recv(in, buffer, CHUNKSIZE, 0)) < 1) {
84 error_sleep = 1;
85 continue;
86 }
87 written = 0;
88 do {
89 if ((bytes = write(out, buffer, recvd-written)) < 0) {
90 perror("write");
91 exit(EXIT_FAILURE);
92 }
93 written += bytes;
94 } while(written < recvd);
95
96 if (!(++count % GTOD_INTERVAL))
97 gettimeofday(&curr, NULL);
98 } while (curr.tv_sec < start.tv_sec+duration);
99
100 close(out);
101 close(in);
102 shutdown(in, SHUT_RDWR);
103 }
104
105 int main(int argc, char **argv)
106 {
107 int duration;
108 char *url;
109 char *outfile;
110 int(*open_fn)(char *);
111
112 if (argc == 4) {
113 url = argv[1];
114 duration = atoi(argv[2])*60;
115 outfile = argv[3];
116 } else {
117 fprintf(stderr,"Syntax: %s URL duration_in_minutes outfile\n", argv[0]);
118 exit(EXIT_FAILURE);
119 }
120
121 if (!is_http(url) && !is_mcast(url)) {
122 char *service_url;
123 if ((service_url = get_url_from_sap(url))) {
124 printf("SAP says: '%s' -> %s\n", url, service_url);
125 url = service_url;
126 }
127 }
128
129 if (is_http(url)) {
130 open_fn = &open_http;
131 } else if (is_mcast(url)) {
132 open_fn = &open_mcast;
133 } else {
134 printf("URL '%s' not supported!\n", url);
135 exit(EXIT_FAILURE);
136 }
137
138 record(open_fn, url, outfile, duration);
139
140 return EXIT_SUCCESS;
141 }
Impressum, Datenschutz