|
|
|
@ -27,8 +27,11 @@ pub struct State { |
|
|
|
client: HttpClient,
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl Send for State {}
|
|
|
|
unsafe impl Sync for State {}
|
|
|
|
|
|
|
|
impl State {
|
|
|
|
pub fn new(uri: &Uri, rate_limit: u64, concurrency_limit: usize) -> anyhow::Result<Self>
|
|
|
|
pub fn new(uri: &Uri, concurrency_limit: usize, timeout: Duration) -> anyhow::Result<Self>
|
|
|
|
{
|
|
|
|
let scheme = uri.scheme()
|
|
|
|
. ok_or(anyhow!("Problem scheme in m3u8 uri"))?;
|
|
|
|
@ -42,12 +45,11 @@ impl State { |
|
|
|
scheme: scheme.clone(),
|
|
|
|
auth: authority.clone(),
|
|
|
|
base_path: base_path.to_string(),
|
|
|
|
timeout: Duration::from_secs(10),
|
|
|
|
timeout,
|
|
|
|
client: ServiceBuilder::new()
|
|
|
|
// Add some layers.
|
|
|
|
. buffer(64)
|
|
|
|
. rate_limit(rate_limit, Duration::from_secs(1))
|
|
|
|
. concurrency_limit(concurrency_limit)
|
|
|
|
. timeout(timeout)
|
|
|
|
// Make client compatible with the `tower-http` layers.
|
|
|
|
. layer(HttpClientLayer)
|
|
|
|
. service(reqwest::Client::builder()
|
|
|
|
@ -61,10 +63,6 @@ impl State { |
|
|
|
Ok(state)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn set_timeout(&mut self, timeout: Duration) {
|
|
|
|
self.timeout = timeout;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) async fn get_m3u8_segment_uris(&mut self, path_and_query: &str)
|
|
|
|
-> anyhow::Result<Vec<Uri>>
|
|
|
|
{
|
|
|
|
@ -94,7 +92,7 @@ impl State { |
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) async fn get_m3u8_segment(&mut self, uri: &Uri)
|
|
|
|
-> Result<(), DownloadError>
|
|
|
|
-> Result<Uri, DownloadError>
|
|
|
|
{
|
|
|
|
// I consider a missing path as fatal... there is absolutely nothing we can do about it
|
|
|
|
// and we need all files from the playlist.
|
|
|
|
@ -118,7 +116,7 @@ impl State { |
|
|
|
None => (),
|
|
|
|
Some(v) => if let Ok(v) = v.to_str() {
|
|
|
|
if v == "true" {
|
|
|
|
return Ok(())
|
|
|
|
return Ok(uri.clone())
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
@ -174,7 +172,7 @@ impl State { |
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
Ok(uri.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn download_uri(&self, segment: &MediaSegment) -> anyhow::Result<Uri>
|
|
|
|
@ -222,18 +220,12 @@ impl State { |
|
|
|
. method("HEAD")
|
|
|
|
. uri(uri)
|
|
|
|
. body(Body::default())?;
|
|
|
|
|
|
|
|
log!(Level::Debug, "{:?}", request);
|
|
|
|
|
|
|
|
// Send get request with timeout.
|
|
|
|
// let send_fut = self.client.get(uri).send()?;
|
|
|
|
let send_fut = self.client.execute(request);
|
|
|
|
let response = timeout(self.timeout, send_fut).await??;
|
|
|
|
|
|
|
|
let response = self.client.execute(request).await?;
|
|
|
|
anyhow::ensure!( response.status().is_success()
|
|
|
|
, "resonse status failed: {}"
|
|
|
|
, response.status() );
|
|
|
|
|
|
|
|
log!(Level::Debug, "{:?}", response);
|
|
|
|
|
|
|
|
let content_length: u64 = response.headers().get(CONTENT_LENGTH)
|
|
|
|
@ -259,18 +251,12 @@ impl State { |
|
|
|
. uri(uri)
|
|
|
|
. header(RANGE, format!("bytes={}-", from))
|
|
|
|
. body(Body::default())?;
|
|
|
|
|
|
|
|
log!(Level::Debug, "{:?}", request);
|
|
|
|
|
|
|
|
// Send get request with timeout.
|
|
|
|
// let send_fut = self.client.get(uri).send()?;
|
|
|
|
let send_fut = self.client.execute(request);
|
|
|
|
let response = timeout(self.timeout, send_fut).await??;
|
|
|
|
|
|
|
|
let response = self.client.execute(request).await?;
|
|
|
|
anyhow::ensure!( response.status().is_success()
|
|
|
|
, "resonse status failed: {}"
|
|
|
|
, response.status() );
|
|
|
|
|
|
|
|
log!(Level::Debug, "{:?}", response);
|
|
|
|
|
|
|
|
Ok(response)
|
|
|
|
|