File: input.cpp

package info (click to toggle)
cubemap 1.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 380 kB
  • ctags: 398
  • sloc: cpp: 3,895; sh: 114; perl: 86; makefile: 61
file content (128 lines) | stat: -rw-r--r-- 2,960 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
#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 std::string &url)
{
	string protocol, user, host, port, path;
	if (!parse_url(url, &protocol, &user, &host, &port, &path)) {
		return NULL;
	}
	if (protocol == "http") {
		return new HTTPInput(url);
	}
	if (protocol == "udp") {
		return new UDPInput(url);
	}
	return NULL;
}

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

Input::~Input() {}