Support joining multicast addresses (both ASM and SSM).
[cubemap] / input.cpp
1 #include <stddef.h>
2 #include <string>
3
4 #include "httpinput.h"
5 #include "input.h"
6 #include "state.pb.h"
7 #include "udpinput.h"
8
9 using namespace std;
10
11 namespace {
12
13 // Does not support passwords, only user:host, since this is really only used
14 // to parse VLC's udp://source@multicastgroup:1234/ syntax (we do not support
15 // even basic auth).
16 void split_user_host(const string &user_host, string *user, string *host)
17 {
18         size_t split = user_host.find("@");
19         if (split == string::npos) {
20                 user->clear();
21                 *host = user_host;
22         } else {
23                 *user = string(user_host.begin(), user_host.begin() + split);
24                 *host = string(user_host.begin() + split + 1, user_host.end());
25         }
26 }
27
28 }  // namespace
29
30 // Extremely rudimentary URL parsing.
31 bool parse_url(const string &url, string *protocol, string *user, string *host, string *port, string *path)
32 {
33         size_t split = url.find("://");
34         if (split == string::npos) {
35                 return false;
36         }
37         *protocol = string(url.begin(), url.begin() + split);
38
39         string rest = string(url.begin() + split + 3, url.end());
40         split = rest.find_first_of(":/");
41         if (split == string::npos) {
42                 // http://foo
43                 split_user_host(rest, user, host);
44                 *port = *protocol;
45                 *path = "/";
46                 return true;
47         }
48
49         split_user_host(string(rest.begin(), rest.begin() + split), user, host);
50         char ch = rest[split];  // Colon or slash.
51         rest = string(rest.begin() + split + 1, rest.end());
52
53         if (ch == ':') {
54                 // Parse the port.
55                 split = rest.find_first_of('/');
56                 if (split == string::npos) {
57                         // http://foo:1234
58                         *port = rest;
59                         *path = "/";
60                         return true;
61                 } else {
62                         // http://foo:1234/bar
63                         *port = string(rest.begin(), rest.begin() + split);
64                         *path = string(rest.begin() + split, rest.end());
65                         return true;
66                 }
67         }
68
69         // http://foo/bar
70         *port = *protocol;
71         *path = "/" + rest;
72         return true;
73 }
74
75 Input *create_input(const std::string &url)
76 {
77         string protocol, user, host, port, path;
78         if (!parse_url(url, &protocol, &user, &host, &port, &path)) {
79                 return NULL;
80         }
81         if (protocol == "http") {
82                 return new HTTPInput(url);
83         }
84         if (protocol == "udp") {
85                 return new UDPInput(url);
86         }
87         return NULL;
88 }
89
90 Input *create_input(const InputProto &serialized)
91 {
92         string protocol, user, host, port, path;
93         if (!parse_url(serialized.url(), &protocol, &user, &host, &port, &path)) {
94                 return NULL;
95         }
96         if (protocol == "http") {
97                 return new HTTPInput(serialized);
98         }
99         if (protocol == "udp") {
100                 return new UDPInput(serialized);
101         }
102         return NULL;
103 }
104
105 Input::~Input() {}
106