102207f955deabdc8861ffbd9798fcefd1542e29
[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
41         // Split at the first slash, or the first colon that's not within [].
42         bool within_brackets = false;
43         for (split = 0; split < rest.size(); ++split) {
44                 if (rest[split] == '[') {
45                         if (within_brackets) {
46                                 // Can't nest brackets.
47                                 return false;
48                         }
49                         within_brackets = true;
50                 } else if (rest[split] == ']') {
51                         if (!within_brackets) {
52                                 // ] without matching [.
53                                 return false;
54                         }
55                         within_brackets = false;
56                 } else if (rest[split] == '/') {
57                         break;
58                 } else if (rest[split] == ':' && !within_brackets) {
59                         break;
60                 }
61         }
62
63         if (split == rest.size()) {
64                 // http://foo
65                 split_user_host(rest, user, host);
66                 fprintf(stderr, "ooo user='%s' host='%s'\n", user->c_str(), host->c_str());
67                 *port = *protocol;
68                 *path = "/";
69                 return true;
70         }
71
72         split_user_host(string(rest.begin(), rest.begin() + split), user, host);
73         char ch = rest[split];  // Colon or slash.
74         rest = string(rest.begin() + split + 1, rest.end());
75
76         if (ch == ':') {
77                 // Parse the port.
78                 split = rest.find_first_of('/');
79                 if (split == string::npos) {
80                         // http://foo:1234
81                         *port = rest;
82                         *path = "/";
83                         return true;
84                 } else {
85                         // http://foo:1234/bar
86                         *port = string(rest.begin(), rest.begin() + split);
87                         *path = string(rest.begin() + split, rest.end());
88                         return true;
89                 }
90         }
91
92         // http://foo/bar
93         *port = *protocol;
94         *path = "/" + rest;
95         return true;
96 }
97
98 Input *create_input(const std::string &url)
99 {
100         string protocol, user, host, port, path;
101         if (!parse_url(url, &protocol, &user, &host, &port, &path)) {
102                 return NULL;
103         }
104         if (protocol == "http") {
105                 return new HTTPInput(url);
106         }
107         if (protocol == "udp") {
108                 return new UDPInput(url);
109         }
110         return NULL;
111 }
112
113 Input *create_input(const InputProto &serialized)
114 {
115         string protocol, user, host, port, path;
116         if (!parse_url(serialized.url(), &protocol, &user, &host, &port, &path)) {
117                 return NULL;
118         }
119         if (protocol == "http") {
120                 return new HTTPInput(serialized);
121         }
122         if (protocol == "udp") {
123                 return new UDPInput(serialized);
124         }
125         return NULL;
126 }
127
128 Input::~Input() {}
129