File: input.cpp

package info (click to toggle)
cubemap 1.4.2-1
  • links: PTS
  • area: main
  • in suites: buster
  • size: 844 kB
  • sloc: ansic: 8,155; cpp: 5,539; sh: 114; perl: 112; makefile: 63
file content (129 lines) | stat: -rw-r--r-- 3,052 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <stddef.h>
#include <string>

#include "httpinput.h"
#include "input.h"
#include "state.pb.h"
#include "udpinput.h"

using namespace std;

namespace {

// Does not support passwords, only user:host, since this is really only used
// to parse VLC's udp://source@multicastgroup:1234/ syntax (we do not support
// even basic auth).
void split_user_host(const string &user_host, string *user, string *host)
{
	size_t split = user_host.find("@");
	if (split == string::npos) {
		user->clear();
		*host = user_host;
	} else {
		*user = string(user_host.begin(), user_host.begin() + split);
		*host = string(user_host.begin() + split + 1, user_host.end());
	}
}

}  // namespace

// Extremely rudimentary URL parsing.
bool parse_url(const string &url, string *protocol, string *user, string *host, string *port, string *path)
{
	size_t split = url.find("://");
	if (split == string::npos) {
		return false;
	}
	*protocol = string(url.begin(), url.begin() + split);

	string rest = string(url.begin() + split + 3, url.end());

	// Split at the first slash, or the first colon that's not within [].
	bool within_brackets = false;
	for (split = 0; split < rest.size(); ++split) {
		if (rest[split] == '[') {
			if (within_brackets) {
				// Can't nest brackets.
				return false;
			}
			within_brackets = true;
		} else if (rest[split] == ']') {
			if (!within_brackets) {
				// ] without matching [.
				return false;
			}
			within_brackets = false;
		} else if (rest[split] == '/') {
			break;
		} else if (rest[split] == ':' && !within_brackets) {
			break;
		}
	}

	if (split == rest.size()) {
		// http://foo
		split_user_host(rest, user, host);
		*port = *protocol;
		*path = "/";
		return true;
	}

	split_user_host(string(rest.begin(), rest.begin() + split), user, host);
	char ch = rest[split];  // Colon or slash.
	rest = string(rest.begin() + split + 1, rest.end());

	if (ch == ':') {
		// Parse the port.
		split = rest.find_first_of('/');
		if (split == string::npos) {
			// http://foo:1234
			*port = rest;
			*path = "/";
			return true;
		} else {
			// http://foo:1234/bar
			*port = string(rest.begin(), rest.begin() + split);
			*path = string(rest.begin() + split, rest.end());
			return true;
		}
	}

	// http://foo/bar
	*port = *protocol;
	*path = "/" + rest;
	return true;
}

Input *create_input(const string &url, Input::Encoding encoding)
{
	string protocol, user, host, port, path;
	if (!parse_url(url, &protocol, &user, &host, &port, &path)) {
		return nullptr;
	}
	if (protocol == "http") {
		return new HTTPInput(url, encoding);
	}
	if (protocol == "udp") {
		assert(encoding == Input::INPUT_ENCODING_RAW);
		return new UDPInput(url);
	}
	return nullptr;
}

Input *create_input(const InputProto &serialized)
{
	string protocol, user, host, port, path;
	if (!parse_url(serialized.url(), &protocol, &user, &host, &port, &path)) {
		return nullptr;
	}
	if (protocol == "http") {
		return new HTTPInput(serialized);
	}
	if (protocol == "udp") {
		return new UDPInput(serialized);
	}
	return nullptr;
}

Input::~Input() {}