28 #include <boost/algorithm/string.hpp>
29 #include <boost/asio/ip/tcp.hpp>
45 Url(
const std::string& url)
48 static const std::regex protocolExp(
"(\\w+\\d?(\\+\\w+)?)://([^/]*)(\\/[^?]*)?");
49 std::smatch protocolMatch;
50 if (!std::regex_match(url, protocolMatch, protocolExp)) {
53 m_scheme = protocolMatch[1];
54 std::string authority = protocolMatch[3];
55 m_path = protocolMatch[4];
58 static const std::regex v6Exp(
"^\\[([a-fA-F0-9:]+)\\](?:\\:(\\d+))?$");
60 static const std::regex v4MappedV6Exp(
"^\\[::ffff:(\\d+(?:\\.\\d+){3})\\](?:\\:(\\d+))?$");
62 static const std::regex v4HostExp(
"^([^:]+)(?:\\:(\\d+))?$");
64 if (authority.empty()) {
69 bool isV6 = std::regex_match(authority, match, v6Exp);
71 std::regex_match(authority, match, v4MappedV6Exp) ||
72 std::regex_match(authority, match, v4HostExp)) {
121 std::string m_scheme;
127 class HttpException :
public std::runtime_error
130 using std::runtime_error::runtime_error;
139 NdnFchDiscovery::doStart()
142 boost::asio::ip::tcp::iostream requestStream;
143 requestStream.expires_after(std::chrono::seconds(3));
146 if (!url.isValid()) {
147 NDN_THROW(HttpException(
"Invalid NDN-FCH URL: " + m_url));
149 if (!boost::iequals(url.getScheme(),
"http")) {
150 NDN_THROW(HttpException(
"Only http:// NDN-FCH URLs are supported"));
153 requestStream.connect(url.getHost(), url.getPort());
154 if (!requestStream) {
155 NDN_THROW(HttpException(
"HTTP connection error to " + m_url));
158 requestStream <<
"GET " << url.getPath() <<
" HTTP/1.0\r\n";
159 requestStream <<
"Host: " << url.getHost() <<
":" << url.getPort() <<
"\r\n";
160 requestStream <<
"Accept: */*\r\n";
161 requestStream <<
"Cache-Control: no-cache\r\n";
162 requestStream <<
"Connection: close\r\n\r\n";
163 requestStream.flush();
165 std::string statusLine;
166 std::getline(requestStream, statusLine);
167 if (!requestStream) {
168 NDN_THROW(HttpException(
"HTTP communication error"));
171 std::stringstream responseStream(statusLine);
172 std::string httpVersion;
173 responseStream >> httpVersion;
174 unsigned int statusCode;
175 responseStream >> statusCode;
176 std::string statusMessage;
178 std::getline(responseStream, statusMessage);
179 if (!
static_cast<bool>(requestStream) || httpVersion.substr(0, 5) !=
"HTTP/") {
180 NDN_THROW(HttpException(
"HTTP communication error"));
182 if (statusCode != 200) {
183 boost::trim(statusMessage);
184 NDN_THROW(HttpException(
"HTTP request failed: " + std::to_string(statusCode) +
" " + statusMessage));
187 while (std::getline(requestStream, header) && header !=
"\r")
191 requestStream >> hubHost;
192 if (hubHost.empty()) {
193 NDN_THROW(HttpException(
"NDN-FCH did not return hub host"));
198 catch (
const std::runtime_error& e) {
199 this->
fail(e.what());
NdnFchDiscovery(const std::string &url)
Create stage to discover NDN hub using NDN-FCH protocol.
void provideHubFaceUri(const std::string &s)
Parse HUB FaceUri from string and declare success.
void fail(const std::string &msg)