X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=input.cpp;h=dba6cf38b26b3ca87a6a953c8842600012e0124b;hp=d7c2b774d79fd66cbcb8a41d923c12af33c49029;hb=0f36a8f674788a6ee10ff54ae72619b384c62b9d;hpb=488f28bf7070f44469a006ed4a9d4c423788d175 diff --git a/input.cpp b/input.cpp index d7c2b77..dba6cf3 100644 --- a/input.cpp +++ b/input.cpp @@ -1,5 +1,4 @@ #include -#include #include #include "httpinput.h" @@ -9,8 +8,27 @@ 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 *host, string *port, string *path) +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) { @@ -19,16 +37,38 @@ bool parse_url(const string &url, string *protocol, string *host, string *port, *protocol = string(url.begin(), url.begin() + split); string rest = string(url.begin() + split + 3, url.end()); - split = rest.find_first_of(":/"); - if (split == string::npos) { + + // 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 - *host = rest; + split_user_host(rest, user, host); *port = *protocol; *path = "/"; return true; } - *host = string(rest.begin(), rest.begin() + split); + 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()); @@ -50,30 +90,31 @@ bool parse_url(const string &url, string *protocol, string *host, string *port, // http://foo/bar *port = *protocol; - *path = rest; + *path = "/" + rest; return true; } -Input *create_input(const std::string &stream_id, const std::string &url) +Input *create_input(const string &url, Input::Encoding encoding) { - string protocol, host, port, path; - if (!parse_url(url, &protocol, &host, &port, &path)) { - return NULL; + string protocol, user, host, port, path; + if (!parse_url(url, &protocol, &user, &host, &port, &path)) { + return nullptr; } if (protocol == "http") { - return new HTTPInput(stream_id, url); + return new HTTPInput(url, encoding); } if (protocol == "udp") { - return new UDPInput(stream_id, url); + assert(encoding == Input::INPUT_ENCODING_RAW); + return new UDPInput(url); } - return NULL; + return nullptr; } Input *create_input(const InputProto &serialized) { - string protocol, host, port, path; - if (!parse_url(serialized.url(), &protocol, &host, &port, &path)) { - return NULL; + 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); @@ -81,7 +122,7 @@ Input *create_input(const InputProto &serialized) if (protocol == "udp") { return new UDPInput(serialized); } - return NULL; + return nullptr; } Input::~Input() {}