--- /dev/null
+record-dvb
+*.d
--- /dev/null
+CFLAGS =-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -Wall -g
+
+OBJS = record-dvb.o http.o mcast.o common.o
+
+all: record-dvb
+
+DEPEND=$(OBJS:.o=.d)
+-include $(DEPEND)
+
+record-dvb: $(OBJS)
+
+clean:
+ rm -f record-dvb $(OBJS) $(DEPEND)
+
+%.o: %.c
+ $(COMPILE.c) $(OUTPUT_OPTION) $<
+ $(COMPILE.c) -MM $< > $*.d
+
+.PHONY: all clean
--- /dev/null
+#include <strings.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "common.h"
+
+struct dvb_host *parse(char *urlpart, char *defport)
+{
+ struct dvb_host *dvbhost;
+ char *pos;
+
+ if (!(dvbhost = malloc(sizeof(struct dvb_host)))) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+
+ bzero(dvbhost, sizeof(struct dvb_host));
+
+ if (!(dvbhost->hostname = strdup(urlpart))) {
+ perror("strdup");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Unneded, but better readablity: */
+ dvbhost->location = NULL;
+ dvbhost->port = NULL;
+
+ pos = dvbhost->hostname;
+
+ while(*pos != '\0' && *pos != ':' && *pos != '/')
+ pos++;
+
+ if (*pos == '/')
+ dvbhost->location = pos + 1;
+
+ if (*pos == ':')
+ dvbhost->port = pos + 1;
+
+ *pos = 0;
+
+ if (dvbhost->port) {
+ pos++;
+
+ while(*pos != '\0' && *pos != '/')
+ pos ++;
+
+ if(*pos == '/')
+ dvbhost->location = pos + 1;
+
+ *pos = 0;
+ }
+
+ if (!dvbhost->port)
+ dvbhost->port = strdup(defport);
+
+ if (!dvbhost->location)
+ if(!(dvbhost->location = strdup(""))) {
+ perror("strdup");
+ exit(EXIT_FAILURE);
+ }
+
+ return dvbhost;
+}
--- /dev/null
+struct dvb_host {
+ char *hostname;
+ char *port;
+ char *location;
+};
+
+struct dvb_host *parse(char *urlpart, char *defport);
--- /dev/null
+#include <strings.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "common.h"
+#include "http.h"
+
+#define BUFFSIZE 1024
+
+int is_http(char *url)
+{
+ if (strlen(url) < 8)
+ return 0;
+
+ if (!strncasecmp("http://",url,7))
+ return 1;
+
+ return 0;
+}
+
+int open_http(char *url)
+{
+ int fd;
+ struct sockaddr_in server;
+ struct dvb_host *dvbhost;
+ struct addrinfo *s_addrinfo, addrhints;
+ char buffer[BUFFSIZE];
+ int i;
+
+ if(!is_http(url))
+ return -1;
+
+ dvbhost = parse(&(url[7]), "80");
+
+ bzero(&addrhints, sizeof(struct addrinfo));
+ addrhints.ai_family = PF_INET;
+ addrhints.ai_socktype = SOCK_STREAM;
+
+ if ((i=getaddrinfo(dvbhost->hostname, dvbhost->port, &addrhints, &s_addrinfo))) {
+ fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(i));
+ return -1;
+ }
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ bzero(&server, sizeof(struct sockaddr_in));
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_addr.s_addr;
+ server.sin_port = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_port;
+
+ if (connect(fd, (struct sockaddr*) &server, sizeof(server)) < 0) {
+ perror("connect");
+ return -1;
+ }
+
+ freeaddrinfo(s_addrinfo);
+
+
+ snprintf(buffer, BUFFSIZE-1, "GET /%s HTTP/1.0\n\n",dvbhost->location);
+ buffer[BUFFSIZE-1] = 0;
+ send(fd, buffer, strlen(buffer), 0);
+ i = 0;
+ while(i < 2) {
+ if (recv(fd, buffer, 1, 0) < 1) {
+ perror("recv");
+ exit(EXIT_FAILURE);
+ }
+ printf("%c",buffer[0]);
+ if (buffer[0] == 0x0a)
+ i++;
+ else
+ if (buffer[0] != 0x0d)
+ i = 0;
+ }
+
+ return fd;
+}
--- /dev/null
+int is_http(char *url);
+int open_http(char *url);
--- /dev/null
+#include <strings.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "mcast.h"
+
+int is_mcast(char *url)
+{
+ if (strlen(url) < 7)
+ return 0;
+
+ if (!strncasecmp("udp://",url,6))
+ return 1;
+
+ return 0;
+}
+
+int open_mcast(char *url)
+{
+ fprintf(stderr,"multicast currently unimplemented!\n");
+
+ exit(EXIT_FAILURE);
+}
--- /dev/null
+int is_mcast(char *url);
+int open_mcast(char *url);
--- /dev/null
+#include <features.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <strings.h>
+
+#include "http.h"
+#include "mcast.h"
+
+#define CHUNKSIZE 8192
+
+void record(int(*open_fn)(char *), char *url, char *outfile, int duration)
+{
+ struct timeval start, curr;
+ int bytes, written;
+ char buffer[CHUNKSIZE];
+ int i;
+ int in, out;
+
+ if ((out = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_LARGEFILE, 00644)) < 0) {
+ perror("open");
+ exit(EXIT_FAILURE);
+ }
+
+ if ((in = (*open_fn)(url)) < 0) {
+ fprintf(stderr,"Can't open url %s!\n",url);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Recording from %s for %d seconds...\n", url, duration);
+
+ gettimeofday(&start, NULL);
+
+ do {
+ if ((bytes = recv(in, buffer, CHUNKSIZE, 0)) < 1) {
+ perror("recv");
+ exit(EXIT_FAILURE);
+ }
+
+ written = 0;
+ do {
+ if ((i = write(out, buffer, bytes-written)) < 0) {
+ perror("write");
+ exit(EXIT_FAILURE);
+ }
+ written += i;
+ } while(written < bytes);
+
+ gettimeofday(&curr, NULL);
+ } while (curr.tv_sec < start.tv_sec+duration);
+
+ close(out);
+ close(in);
+ shutdown(in, SHUT_RDWR);
+}
+
+int main(int argc, char **argv)
+{
+ int duration;
+ char *url;
+ char *outfile;
+ int(*open_fn)(char *);
+
+ if (argc == 4) {
+ url = argv[1];
+ duration = atol(argv[2])*60;
+ outfile = argv[3];
+ } else {
+ fprintf(stderr,"Syntax: %s URL duration outfile\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (is_http(url)) {
+ open_fn = &open_http;
+ } else if (is_mcast(url)) {
+ open_fn = &open_mcast;
+ } else {
+ printf("URL %s not supported!\n", url);
+ exit(EXIT_FAILURE);
+ }
+
+ record(open_fn, url, outfile, duration);
+
+ return EXIT_SUCCESS;
+}