Add experimental icy_stream Shoutcast stream filter:

fix #595, fix #1151

This provides a stream filter which converts the ICY HTTP
response handshake at the beginning of a stream to HTTP/1.1.
This commit is contained in:
Vinnie Falco committed 2018-06-09 21:12:01 -07:00
1 parent 39b014263a
commit 6647e9ea56
12 files changed
+1110 -2

No files matched your search

+1
View File
@@ -19,6 +19,7 @@ add_executable (tests-beast-experimental
Jamfile
error.cpp
flat_stream.cpp
icy_stream.cpp
ssl_stream.cpp
stream.cpp
)
+1
View File
@@ -10,6 +10,7 @@
local SOURCES =
error.cpp
flat_stream.cpp
icy_stream.cpp
ssl_stream.cpp
stream.cpp
;
+1 -1
View File
@@ -103,7 +103,7 @@ public:
}
};
BEAST_DEFINE_TESTSUITE(beast,example,flat_stream);
BEAST_DEFINE_TESTSUITE(beast,core,flat_stream);
} // beast
} // boost
+127
View File
@@ -0,0 +1,127 @@
//
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
// Test that header file is self-contained.
#include <boost/beast/experimental/http/icy_stream.hpp>
#include <boost/beast/core/buffers_adapter.hpp>
#include <boost/beast/core/buffers_to_string.hpp>
#include <boost/beast/core/read_size.hpp>
#include <boost/beast/experimental/test/stream.hpp>
#include <boost/beast/unit_test/suite.hpp>
#include <array>
#include <memory>
#include <string>
namespace boost {
namespace beast {
namespace http {
class icy_stream_test
: public unit_test::suite
{
public:
void
doMatrix(string_view in, string_view out)
{
using boost::asio::mutable_buffer;
boost::asio::io_context ioc;
auto len = out.size() + 8;
std::unique_ptr<char[]> p(new char[len]);
for(std::size_t i = 1; i < len; ++i)
{
std::array<mutable_buffer, 2> mbs{
mutable_buffer(p.get(), i),
mutable_buffer(p.get() + i, len - i)};
for(std::size_t j = 1; j < in.size(); ++j)
{
for(std::size_t k = 1; k < len; ++k)
{
// sync
{
buffers_adapter<decltype(mbs)> ba(mbs);
std::memset(p.get(), 0, len);
icy_stream<test::stream> is{ioc};
is.next_layer().read_size(j);
is.next_layer().append(in);
connect(is.next_layer()).close();
error_code ec;
for(;;)
{
ba.commit(is.read_some(
ba.prepare(read_size(ba, k)), ec));
if(ec)
break;
}
if(! BEAST_EXPECTS(
ec == boost::asio::error::eof, ec.message()))
continue;
auto const s = buffers_to_string(ba.data());
BEAST_EXPECTS(s == out, s);
}
// async
{
buffers_adapter<decltype(mbs)> ba(mbs);
std::memset(p.get(), 0, len);
icy_stream<test::stream> is{ioc};
is.next_layer().read_size(j);
is.next_layer().append(in);
connect(is.next_layer()).close();
error_code ec;
for(;;)
{
is.async_read_some(
ba.prepare(read_size(ba, k)),
[&ec, &ba](error_code ec_, std::size_t n)
{
ec = ec_;
ba.commit(n);
});
ioc.run();
ioc.reset();
if(ec)
break;
}
if(! BEAST_EXPECTS(
ec == boost::asio::error::eof, ec.message()))
continue;
auto const s = buffers_to_string(ba.data());
if(! BEAST_EXPECTS(s == out, s))
{
s.size();
}
}
}
}
}
}
void
testStream()
{
doMatrix("HTTP/1.1 200 OK\r\n", "HTTP/1.1 200 OK\r\n");
doMatrix("ICY 200 OK\r\n", "HTTP/1.1 200 OK\r\n");
}
void
run() override
{
testStream();
}
};
BEAST_DEFINE_TESTSUITE(beast,http,icy_stream);
} // http
} // beast
} // boost