mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Change to parking_lot
and remove remaining panics
This commit is contained in:
parent
62461be1fc
commit
b4f7a9e35e
13 changed files with 200 additions and 121 deletions
94
Cargo.lock
generated
94
Cargo.lock
generated
|
@ -2,6 +2,21 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aes"
|
name = "aes"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -110,6 +125,21 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.63"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
@ -429,6 +459,12 @@ dependencies = [
|
||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -569,6 +605,12 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.26.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib"
|
name = "glib"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
|
@ -1226,6 +1268,7 @@ dependencies = [
|
||||||
"hyper",
|
"hyper",
|
||||||
"librespot-core",
|
"librespot-core",
|
||||||
"log",
|
"log",
|
||||||
|
"parking_lot",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -1278,6 +1321,7 @@ dependencies = [
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"parking_lot",
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"priority-queue",
|
"priority-queue",
|
||||||
"protobuf",
|
"protobuf",
|
||||||
|
@ -1432,6 +1476,16 @@ version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.7.14"
|
version = "0.7.14"
|
||||||
|
@ -1704,6 +1758,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.27.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oboe"
|
name = "oboe"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
|
@ -1771,11 +1834,14 @@ version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"instant",
|
"instant",
|
||||||
"libc",
|
"libc",
|
||||||
|
"petgraph",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
"thread-id",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1807,6 +1873,16 @@ version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
|
@ -2115,6 +2191,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -2467,6 +2549,17 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread-id"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5fdfe0627923f7411a43ec9ec9c39c3a9b4151be313e0922042581fb6c9b717f"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
|
@ -2505,6 +2598,7 @@ dependencies = [
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
|
|
|
@ -50,7 +50,7 @@ version = "0.3.1"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
env_logger = {version = "0.8", default-features = false, features = ["termcolor","humantime","atty"]}
|
env_logger = { version = "0.8", default-features = false, features = ["termcolor", "humantime", "atty"] }
|
||||||
futures-util = { version = "0.3", default_features = false }
|
futures-util = { version = "0.3", default_features = false }
|
||||||
getopts = "0.2.21"
|
getopts = "0.2.21"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
|
@ -58,7 +58,7 @@ hyper = "0.14"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rpassword = "5.0"
|
rpassword = "5.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros", "signal", "sync", "process"] }
|
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros", "signal", "sync", "parking_lot", "process"] }
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
sha-1 = "0.9"
|
sha-1 = "0.9"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ name = "librespot-audio"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
authors = ["Paul Lietar <paul@lietar.net>"]
|
authors = ["Paul Lietar <paul@lietar.net>"]
|
||||||
description="The audio fetching and processing logic for librespot"
|
description="The audio fetching and processing logic for librespot"
|
||||||
license="MIT"
|
license = "MIT"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies.librespot-core]
|
[dependencies.librespot-core]
|
||||||
|
@ -19,6 +19,7 @@ futures-executor = "0.3"
|
||||||
futures-util = { version = "0.3", default_features = false }
|
futures-util = { version = "0.3", default_features = false }
|
||||||
hyper = { version = "0.14", features = ["client"] }
|
hyper = { version = "0.14", features = ["client"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
parking_lot = { version = "0.11", features = ["deadlock_detection"] }
|
||||||
tempfile = "3.1"
|
tempfile = "3.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1", features = ["sync", "macros"] }
|
tokio = { version = "1", features = ["macros", "parking_lot", "sync"] }
|
||||||
|
|
|
@ -6,13 +6,14 @@ use std::{
|
||||||
io::{self, Read, Seek, SeekFrom},
|
io::{self, Read, Seek, SeekFrom},
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{self, AtomicUsize},
|
atomic::{self, AtomicUsize},
|
||||||
Arc, Condvar, Mutex,
|
Arc,
|
||||||
},
|
},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures_util::{future::IntoStream, StreamExt, TryFutureExt};
|
use futures_util::{future::IntoStream, StreamExt, TryFutureExt};
|
||||||
use hyper::{client::ResponseFuture, header::CONTENT_RANGE, Body, Response, StatusCode};
|
use hyper::{client::ResponseFuture, header::CONTENT_RANGE, Body, Response, StatusCode};
|
||||||
|
use parking_lot::{Condvar, Mutex};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
@ -159,7 +160,7 @@ impl StreamLoaderController {
|
||||||
|
|
||||||
pub fn range_available(&self, range: Range) -> bool {
|
pub fn range_available(&self, range: Range) -> bool {
|
||||||
let available = if let Some(ref shared) = self.stream_shared {
|
let available = if let Some(ref shared) = self.stream_shared {
|
||||||
let download_status = shared.download_status.lock().unwrap();
|
let download_status = shared.download_status.lock();
|
||||||
|
|
||||||
range.length
|
range.length
|
||||||
<= download_status
|
<= download_status
|
||||||
|
@ -214,18 +215,21 @@ impl StreamLoaderController {
|
||||||
self.fetch(range);
|
self.fetch(range);
|
||||||
|
|
||||||
if let Some(ref shared) = self.stream_shared {
|
if let Some(ref shared) = self.stream_shared {
|
||||||
let mut download_status = shared.download_status.lock().unwrap();
|
let mut download_status = shared.download_status.lock();
|
||||||
|
|
||||||
while range.length
|
while range.length
|
||||||
> download_status
|
> download_status
|
||||||
.downloaded
|
.downloaded
|
||||||
.contained_length_from_value(range.start)
|
.contained_length_from_value(range.start)
|
||||||
{
|
{
|
||||||
download_status = shared
|
if shared
|
||||||
.cond
|
.cond
|
||||||
.wait_timeout(download_status, DOWNLOAD_TIMEOUT)
|
.wait_for(&mut download_status, DOWNLOAD_TIMEOUT)
|
||||||
.map_err(|_| AudioFileError::WaitTimeout)?
|
.timed_out()
|
||||||
.0;
|
{
|
||||||
|
return Err(AudioFileError::WaitTimeout.into());
|
||||||
|
}
|
||||||
|
|
||||||
if range.length
|
if range.length
|
||||||
> (download_status
|
> (download_status
|
||||||
.downloaded
|
.downloaded
|
||||||
|
@ -473,7 +477,7 @@ impl Read for AudioFileStreaming {
|
||||||
|
|
||||||
let length = min(output.len(), self.shared.file_size - offset);
|
let length = min(output.len(), self.shared.file_size - offset);
|
||||||
|
|
||||||
let length_to_request = match *(self.shared.download_strategy.lock().unwrap()) {
|
let length_to_request = match *(self.shared.download_strategy.lock()) {
|
||||||
DownloadStrategy::RandomAccess() => length,
|
DownloadStrategy::RandomAccess() => length,
|
||||||
DownloadStrategy::Streaming() => {
|
DownloadStrategy::Streaming() => {
|
||||||
// Due to the read-ahead stuff, we potentially request more than the actual request demanded.
|
// Due to the read-ahead stuff, we potentially request more than the actual request demanded.
|
||||||
|
@ -497,7 +501,7 @@ impl Read for AudioFileStreaming {
|
||||||
let mut ranges_to_request = RangeSet::new();
|
let mut ranges_to_request = RangeSet::new();
|
||||||
ranges_to_request.add_range(&Range::new(offset, length_to_request));
|
ranges_to_request.add_range(&Range::new(offset, length_to_request));
|
||||||
|
|
||||||
let mut download_status = self.shared.download_status.lock().unwrap();
|
let mut download_status = self.shared.download_status.lock();
|
||||||
|
|
||||||
ranges_to_request.subtract_range_set(&download_status.downloaded);
|
ranges_to_request.subtract_range_set(&download_status.downloaded);
|
||||||
ranges_to_request.subtract_range_set(&download_status.requested);
|
ranges_to_request.subtract_range_set(&download_status.requested);
|
||||||
|
@ -513,17 +517,17 @@ impl Read for AudioFileStreaming {
|
||||||
}
|
}
|
||||||
|
|
||||||
while !download_status.downloaded.contains(offset) {
|
while !download_status.downloaded.contains(offset) {
|
||||||
download_status = self
|
if self
|
||||||
.shared
|
.shared
|
||||||
.cond
|
.cond
|
||||||
.wait_timeout(download_status, DOWNLOAD_TIMEOUT)
|
.wait_for(&mut download_status, DOWNLOAD_TIMEOUT)
|
||||||
.map_err(|_| {
|
.timed_out()
|
||||||
io::Error::new(
|
{
|
||||||
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::TimedOut,
|
io::ErrorKind::TimedOut,
|
||||||
Error::deadline_exceeded(AudioFileError::WaitTimeout),
|
Error::deadline_exceeded(AudioFileError::WaitTimeout),
|
||||||
)
|
));
|
||||||
})?
|
}
|
||||||
.0;
|
|
||||||
}
|
}
|
||||||
let available_length = download_status
|
let available_length = download_status
|
||||||
.downloaded
|
.downloaded
|
||||||
|
|
|
@ -108,7 +108,7 @@ async fn receive_data(
|
||||||
if request_length > 0 {
|
if request_length > 0 {
|
||||||
let missing_range = Range::new(data_offset, request_length);
|
let missing_range = Range::new(data_offset, request_length);
|
||||||
|
|
||||||
let mut download_status = shared.download_status.lock().unwrap();
|
let mut download_status = shared.download_status.lock();
|
||||||
|
|
||||||
download_status.requested.subtract_range(&missing_range);
|
download_status.requested.subtract_range(&missing_range);
|
||||||
shared.cond.notify_all();
|
shared.cond.notify_all();
|
||||||
|
@ -157,7 +157,7 @@ enum ControlFlow {
|
||||||
|
|
||||||
impl AudioFileFetch {
|
impl AudioFileFetch {
|
||||||
fn get_download_strategy(&mut self) -> DownloadStrategy {
|
fn get_download_strategy(&mut self) -> DownloadStrategy {
|
||||||
*(self.shared.download_strategy.lock().unwrap())
|
*(self.shared.download_strategy.lock())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn download_range(&mut self, offset: usize, mut length: usize) -> AudioFileResult {
|
fn download_range(&mut self, offset: usize, mut length: usize) -> AudioFileResult {
|
||||||
|
@ -172,7 +172,7 @@ impl AudioFileFetch {
|
||||||
let mut ranges_to_request = RangeSet::new();
|
let mut ranges_to_request = RangeSet::new();
|
||||||
ranges_to_request.add_range(&Range::new(offset, length));
|
ranges_to_request.add_range(&Range::new(offset, length));
|
||||||
|
|
||||||
let mut download_status = self.shared.download_status.lock().unwrap();
|
let mut download_status = self.shared.download_status.lock();
|
||||||
|
|
||||||
ranges_to_request.subtract_range_set(&download_status.downloaded);
|
ranges_to_request.subtract_range_set(&download_status.downloaded);
|
||||||
ranges_to_request.subtract_range_set(&download_status.requested);
|
ranges_to_request.subtract_range_set(&download_status.requested);
|
||||||
|
@ -218,7 +218,7 @@ impl AudioFileFetch {
|
||||||
let mut missing_data = RangeSet::new();
|
let mut missing_data = RangeSet::new();
|
||||||
missing_data.add_range(&Range::new(0, self.shared.file_size));
|
missing_data.add_range(&Range::new(0, self.shared.file_size));
|
||||||
{
|
{
|
||||||
let download_status = self.shared.download_status.lock().unwrap();
|
let download_status = self.shared.download_status.lock();
|
||||||
|
|
||||||
missing_data.subtract_range_set(&download_status.downloaded);
|
missing_data.subtract_range_set(&download_status.downloaded);
|
||||||
missing_data.subtract_range_set(&download_status.requested);
|
missing_data.subtract_range_set(&download_status.requested);
|
||||||
|
@ -306,7 +306,7 @@ impl AudioFileFetch {
|
||||||
None => return Err(AudioFileError::Output.into()),
|
None => return Err(AudioFileError::Output.into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut download_status = self.shared.download_status.lock().unwrap();
|
let mut download_status = self.shared.download_status.lock();
|
||||||
|
|
||||||
let received_range = Range::new(data.offset, data.data.len());
|
let received_range = Range::new(data.offset, data.data.len());
|
||||||
download_status.downloaded.add_range(&received_range);
|
download_status.downloaded.add_range(&received_range);
|
||||||
|
@ -336,10 +336,10 @@ impl AudioFileFetch {
|
||||||
self.download_range(request.start, request.length)?;
|
self.download_range(request.start, request.length)?;
|
||||||
}
|
}
|
||||||
StreamLoaderCommand::RandomAccessMode() => {
|
StreamLoaderCommand::RandomAccessMode() => {
|
||||||
*(self.shared.download_strategy.lock().unwrap()) = DownloadStrategy::RandomAccess();
|
*(self.shared.download_strategy.lock()) = DownloadStrategy::RandomAccess();
|
||||||
}
|
}
|
||||||
StreamLoaderCommand::StreamMode() => {
|
StreamLoaderCommand::StreamMode() => {
|
||||||
*(self.shared.download_strategy.lock().unwrap()) = DownloadStrategy::Streaming();
|
*(self.shared.download_strategy.lock()) = DownloadStrategy::Streaming();
|
||||||
}
|
}
|
||||||
StreamLoaderCommand::Close() => return Ok(ControlFlow::Break),
|
StreamLoaderCommand::Close() => return Ok(ControlFlow::Break),
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ pub(super) async fn audio_file_fetch(
|
||||||
initial_request.offset,
|
initial_request.offset,
|
||||||
initial_request.offset + initial_request.length,
|
initial_request.offset + initial_request.length,
|
||||||
);
|
);
|
||||||
let mut download_status = shared.download_status.lock().unwrap();
|
let mut download_status = shared.download_status.lock();
|
||||||
|
|
||||||
download_status.requested.add_range(&requested_range);
|
download_status.requested.add_range(&requested_range);
|
||||||
}
|
}
|
||||||
|
@ -432,7 +432,7 @@ pub(super) async fn audio_file_fetch(
|
||||||
let max_requests_to_send = MAX_PREFETCH_REQUESTS - number_of_open_requests;
|
let max_requests_to_send = MAX_PREFETCH_REQUESTS - number_of_open_requests;
|
||||||
|
|
||||||
let bytes_pending: usize = {
|
let bytes_pending: usize = {
|
||||||
let download_status = fetch.shared.download_status.lock().unwrap();
|
let download_status = fetch.shared.download_status.lock();
|
||||||
|
|
||||||
download_status
|
download_status
|
||||||
.requested
|
.requested
|
||||||
|
|
|
@ -16,7 +16,7 @@ rand = "0.8"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1.0", features = ["macros", "sync"] }
|
tokio = { version = "1.0", features = ["macros", "parking_lot", "sync"] }
|
||||||
tokio-stream = "0.1.1"
|
tokio-stream = "0.1.1"
|
||||||
|
|
||||||
[dependencies.librespot-core]
|
[dependencies.librespot-core]
|
||||||
|
|
|
@ -20,11 +20,11 @@ bytes = "1"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
form_urlencoded = "1.0"
|
form_urlencoded = "1.0"
|
||||||
futures-core = { version = "0.3", default-features = false }
|
futures-core = { version = "0.3", default-features = false }
|
||||||
futures-util = { version = "0.3", default-features = false, features = ["alloc", "bilock", "unstable", "sink"] }
|
futures-util = { version = "0.3", default-features = false, features = ["alloc", "bilock", "sink", "unstable"] }
|
||||||
hmac = "0.11"
|
hmac = "0.11"
|
||||||
httparse = "1.3"
|
httparse = "1.3"
|
||||||
http = "0.2"
|
http = "0.2"
|
||||||
hyper = { version = "0.14", features = ["client", "tcp", "http1", "http2"] }
|
hyper = { version = "0.14", features = ["client", "http1", "http2", "tcp"] }
|
||||||
hyper-proxy = { version = "0.9.1", default-features = false, features = ["rustls"] }
|
hyper-proxy = { version = "0.9.1", default-features = false, features = ["rustls"] }
|
||||||
hyper-rustls = { version = "0.22", default-features = false, features = ["native-tokio"] }
|
hyper-rustls = { version = "0.22", default-features = false, features = ["native-tokio"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
@ -34,10 +34,11 @@ num-derive = "0.3"
|
||||||
num-integer = "0.1"
|
num-integer = "0.1"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
once_cell = "1.5.2"
|
once_cell = "1.5.2"
|
||||||
|
parking_lot = { version = "0.11", features = ["deadlock_detection"] }
|
||||||
pbkdf2 = { version = "0.8", default-features = false, features = ["hmac"] }
|
pbkdf2 = { version = "0.8", default-features = false, features = ["hmac"] }
|
||||||
priority-queue = "1.1"
|
priority-queue = "1.1"
|
||||||
protobuf = "2.14.0"
|
protobuf = "2.14.0"
|
||||||
quick-xml = { version = "0.22", features = [ "serialize" ] }
|
quick-xml = { version = "0.22", features = ["serialize"] }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
rustls = "0.19"
|
rustls = "0.19"
|
||||||
rustls-native-certs = "0.5"
|
rustls-native-certs = "0.5"
|
||||||
|
@ -46,7 +47,7 @@ serde_json = "1.0"
|
||||||
sha-1 = "0.9"
|
sha-1 = "0.9"
|
||||||
shannon = "0.2.0"
|
shannon = "0.2.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1.5", features = ["io-util", "macros", "net", "rt", "time", "sync"] }
|
tokio = { version = "1.5", features = ["io-util", "macros", "net", "parking_lot", "rt", "sync", "time"] }
|
||||||
tokio-stream = "0.1.1"
|
tokio-stream = "0.1.1"
|
||||||
tokio-tungstenite = { version = "0.14", default-features = false, features = ["rustls-tls"] }
|
tokio-tungstenite = { version = "0.14", default-features = false, features = ["rustls-tls"] }
|
||||||
tokio-util = { version = "0.6", features = ["codec"] }
|
tokio-util = { version = "0.6", features = ["codec"] }
|
||||||
|
@ -59,4 +60,4 @@ vergen = "3.0.4"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
tokio = {version = "1.0", features = ["macros"] }
|
tokio = { version = "1.0", features = ["macros", "parking_lot"] }
|
||||||
|
|
|
@ -4,10 +4,11 @@ use std::{
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{Arc, Mutex},
|
sync::Arc,
|
||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use parking_lot::Mutex;
|
||||||
use priority_queue::PriorityQueue;
|
use priority_queue::PriorityQueue;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
@ -187,31 +188,24 @@ impl FsSizeLimiter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&self, file: &Path, size: u64) -> Result<(), Error> {
|
fn add(&self, file: &Path, size: u64) {
|
||||||
self.limiter
|
self.limiter.lock().add(file, size, SystemTime::now());
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.add(file, size, SystemTime::now());
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn touch(&self, file: &Path) -> Result<bool, Error> {
|
fn touch(&self, file: &Path) -> bool {
|
||||||
Ok(self.limiter.lock().unwrap().update(file, SystemTime::now()))
|
self.limiter.lock().update(file, SystemTime::now())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove(&self, file: &Path) -> Result<bool, Error> {
|
fn remove(&self, file: &Path) -> bool {
|
||||||
Ok(self.limiter.lock().unwrap().remove(file))
|
self.limiter.lock().remove(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prune_internal<F: FnMut() -> Result<Option<PathBuf>, Error>>(
|
fn prune_internal<F: FnMut() -> Option<PathBuf>>(mut pop: F) -> Result<(), Error> {
|
||||||
mut pop: F,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut last_error = None;
|
let mut last_error = None;
|
||||||
|
|
||||||
while let Ok(result) = pop() {
|
while let Some(file) = pop() {
|
||||||
if let Some(file) = result {
|
|
||||||
if first {
|
if first {
|
||||||
debug!("Cache dir exceeds limit, removing least recently used files.");
|
debug!("Cache dir exceeds limit, removing least recently used files.");
|
||||||
first = false;
|
first = false;
|
||||||
|
@ -229,7 +223,6 @@ impl FsSizeLimiter {
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
info!("Removed {} cache files.", count);
|
info!("Removed {} cache files.", count);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(err) = last_error {
|
if let Some(err) = last_error {
|
||||||
Err(err.into())
|
Err(err.into())
|
||||||
|
@ -239,14 +232,14 @@ impl FsSizeLimiter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prune(&self) -> Result<(), Error> {
|
fn prune(&self) -> Result<(), Error> {
|
||||||
Self::prune_internal(|| Ok(self.limiter.lock().unwrap().pop()))
|
Self::prune_internal(|| self.limiter.lock().pop())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(path: &Path, limit: u64) -> Result<Self, Error> {
|
fn new(path: &Path, limit: u64) -> Result<Self, Error> {
|
||||||
let mut limiter = SizeLimiter::new(limit);
|
let mut limiter = SizeLimiter::new(limit);
|
||||||
|
|
||||||
Self::init_dir(&mut limiter, path);
|
Self::init_dir(&mut limiter, path);
|
||||||
Self::prune_internal(|| Ok(limiter.pop()))?;
|
Self::prune_internal(|| limiter.pop())?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
limiter: Mutex::new(limiter),
|
limiter: Mutex::new(limiter),
|
||||||
|
@ -388,8 +381,8 @@ impl Cache {
|
||||||
match File::open(&path) {
|
match File::open(&path) {
|
||||||
Ok(file) => {
|
Ok(file) => {
|
||||||
if let Some(limiter) = self.size_limiter.as_deref() {
|
if let Some(limiter) = self.size_limiter.as_deref() {
|
||||||
if let Err(e) = limiter.touch(&path) {
|
if !limiter.touch(&path) {
|
||||||
error!("limiter could not touch {:?}: {}", path, e);
|
error!("limiter could not touch {:?}", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(file)
|
Some(file)
|
||||||
|
@ -411,8 +404,8 @@ impl Cache {
|
||||||
.and_then(|mut file| io::copy(contents, &mut file))
|
.and_then(|mut file| io::copy(contents, &mut file))
|
||||||
{
|
{
|
||||||
if let Some(limiter) = self.size_limiter.as_deref() {
|
if let Some(limiter) = self.size_limiter.as_deref() {
|
||||||
limiter.add(&path, size)?;
|
limiter.add(&path, size);
|
||||||
limiter.prune()?
|
limiter.prune()?;
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -426,7 +419,7 @@ impl Cache {
|
||||||
|
|
||||||
fs::remove_file(&path)?;
|
fs::remove_file(&path)?;
|
||||||
if let Some(limiter) = self.size_limiter.as_deref() {
|
if let Some(limiter) = self.size_limiter.as_deref() {
|
||||||
limiter.remove(&path)?;
|
limiter.remove(&path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
macro_rules! component {
|
macro_rules! component {
|
||||||
($name:ident : $inner:ident { $($key:ident : $ty:ty = $value:expr,)* }) => {
|
($name:ident : $inner:ident { $($key:ident : $ty:ty = $value:expr,)* }) => {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct $name(::std::sync::Arc<($crate::session::SessionWeak, ::std::sync::Mutex<$inner>)>);
|
pub struct $name(::std::sync::Arc<($crate::session::SessionWeak, ::parking_lot::Mutex<$inner>)>);
|
||||||
impl $name {
|
impl $name {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn new(session: $crate::session::SessionWeak) -> $name {
|
pub(crate) fn new(session: $crate::session::SessionWeak) -> $name {
|
||||||
debug!(target:"librespot::component", "new {}", stringify!($name));
|
debug!(target:"librespot::component", "new {}", stringify!($name));
|
||||||
|
|
||||||
$name(::std::sync::Arc::new((session, ::std::sync::Mutex::new($inner {
|
$name(::std::sync::Arc::new((session, ::parking_lot::Mutex::new($inner {
|
||||||
$($key : $value,)*
|
$($key : $value,)*
|
||||||
}))))
|
}))))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn lock<F: FnOnce(&mut $inner) -> R, R>(&self, f: F) -> R {
|
fn lock<F: FnOnce(&mut $inner) -> R, R>(&self, f: F) -> R {
|
||||||
let mut inner = (self.0).1.lock().unwrap();
|
let mut inner = (self.0).1.lock();
|
||||||
f(&mut inner)
|
f(&mut inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{self, AtomicBool},
|
atomic::{self, AtomicBool},
|
||||||
Arc, Mutex,
|
Arc,
|
||||||
},
|
},
|
||||||
task::Poll,
|
task::Poll,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
|
@ -14,6 +14,7 @@ use std::{
|
||||||
|
|
||||||
use futures_core::{Future, Stream};
|
use futures_core::{Future, Stream};
|
||||||
use futures_util::{future::join_all, SinkExt, StreamExt};
|
use futures_util::{future::join_all, SinkExt, StreamExt};
|
||||||
|
use parking_lot::Mutex;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
select,
|
select,
|
||||||
|
@ -310,7 +311,6 @@ impl DealerShared {
|
||||||
if let Some(split) = split_uri(&msg.uri) {
|
if let Some(split) = split_uri(&msg.uri) {
|
||||||
self.message_handlers
|
self.message_handlers
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
|
||||||
.retain(split, &mut |tx| tx.send(msg.clone()).is_ok());
|
.retain(split, &mut |tx| tx.send(msg.clone()).is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,7 @@ impl DealerShared {
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let handler_map = self.request_handlers.lock().unwrap();
|
let handler_map = self.request_handlers.lock();
|
||||||
|
|
||||||
if let Some(handler) = handler_map.get(split) {
|
if let Some(handler) = handler_map.get(split) {
|
||||||
handler.handle_request(request, responder);
|
handler.handle_request(request, responder);
|
||||||
|
@ -349,7 +349,9 @@ impl DealerShared {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn closed(&self) {
|
async fn closed(&self) {
|
||||||
self.notify_drop.acquire().await.unwrap_err();
|
if self.notify_drop.acquire().await.is_ok() {
|
||||||
|
error!("should never have gotten a permit");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_closed(&self) -> bool {
|
fn is_closed(&self) -> bool {
|
||||||
|
@ -367,19 +369,15 @@ impl Dealer {
|
||||||
where
|
where
|
||||||
H: RequestHandler,
|
H: RequestHandler,
|
||||||
{
|
{
|
||||||
add_handler(
|
add_handler(&mut self.shared.request_handlers.lock(), uri, handler)
|
||||||
&mut self.shared.request_handlers.lock().unwrap(),
|
|
||||||
uri,
|
|
||||||
handler,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_handler(&self, uri: &str) -> Option<Box<dyn RequestHandler>> {
|
pub fn remove_handler(&self, uri: &str) -> Option<Box<dyn RequestHandler>> {
|
||||||
remove_handler(&mut self.shared.request_handlers.lock().unwrap(), uri)
|
remove_handler(&mut self.shared.request_handlers.lock(), uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subscribe(&self, uris: &[&str]) -> Result<Subscription, Error> {
|
pub fn subscribe(&self, uris: &[&str]) -> Result<Subscription, Error> {
|
||||||
subscribe(&mut self.shared.message_handlers.lock().unwrap(), uris)
|
subscribe(&mut self.shared.message_handlers.lock(), uris)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn close(mut self) {
|
pub async fn close(mut self) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
process::exit,
|
process::exit,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicUsize, Ordering},
|
atomic::{AtomicUsize, Ordering},
|
||||||
Arc, RwLock, Weak,
|
Arc, Weak,
|
||||||
},
|
},
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
|
@ -18,6 +18,7 @@ use futures_core::TryStream;
|
||||||
use futures_util::{future, ready, StreamExt, TryStreamExt};
|
use futures_util::{future, ready, StreamExt, TryStreamExt};
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
use parking_lot::RwLock;
|
||||||
use quick_xml::events::Event;
|
use quick_xml::events::Event;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
@ -138,8 +139,7 @@ impl Session {
|
||||||
connection::authenticate(&mut transport, credentials, &session.config().device_id)
|
connection::authenticate(&mut transport, credentials, &session.config().device_id)
|
||||||
.await?;
|
.await?;
|
||||||
info!("Authenticated as \"{}\" !", reusable_credentials.username);
|
info!("Authenticated as \"{}\" !", reusable_credentials.username);
|
||||||
session.0.data.write().unwrap().user_data.canonical_username =
|
session.0.data.write().user_data.canonical_username = reusable_credentials.username.clone();
|
||||||
reusable_credentials.username.clone();
|
|
||||||
if let Some(cache) = session.cache() {
|
if let Some(cache) = session.cache() {
|
||||||
cache.save_credentials(&reusable_credentials);
|
cache.save_credentials(&reusable_credentials);
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn time_delta(&self) -> i64 {
|
pub fn time_delta(&self) -> i64 {
|
||||||
self.0.data.read().unwrap().time_delta
|
self.0.data.read().time_delta
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn<T>(&self, task: T)
|
pub fn spawn<T>(&self, task: T)
|
||||||
|
@ -253,7 +253,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
.as_secs() as i64;
|
.as_secs() as i64;
|
||||||
|
|
||||||
self.0.data.write().unwrap().time_delta = server_timestamp - timestamp;
|
self.0.data.write().time_delta = server_timestamp - timestamp;
|
||||||
|
|
||||||
self.debug_info();
|
self.debug_info();
|
||||||
self.send_packet(Pong, vec![0, 0, 0, 0])
|
self.send_packet(Pong, vec![0, 0, 0, 0])
|
||||||
|
@ -261,7 +261,7 @@ impl Session {
|
||||||
Some(CountryCode) => {
|
Some(CountryCode) => {
|
||||||
let country = String::from_utf8(data.as_ref().to_owned())?;
|
let country = String::from_utf8(data.as_ref().to_owned())?;
|
||||||
info!("Country: {:?}", country);
|
info!("Country: {:?}", country);
|
||||||
self.0.data.write().unwrap().user_data.country = country;
|
self.0.data.write().user_data.country = country;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(StreamChunkRes) | Some(ChannelError) => self.channel().dispatch(cmd, data),
|
Some(StreamChunkRes) | Some(ChannelError) => self.channel().dispatch(cmd, data),
|
||||||
|
@ -306,7 +306,7 @@ impl Session {
|
||||||
trace!("Received product info: {:#?}", user_attributes);
|
trace!("Received product info: {:#?}", user_attributes);
|
||||||
Self::check_catalogue(&user_attributes);
|
Self::check_catalogue(&user_attributes);
|
||||||
|
|
||||||
self.0.data.write().unwrap().user_data.attributes = user_attributes;
|
self.0.data.write().user_data.attributes = user_attributes;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Some(PongAck)
|
Some(PongAck)
|
||||||
|
@ -335,7 +335,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn user_data(&self) -> UserData {
|
pub fn user_data(&self) -> UserData {
|
||||||
self.0.data.read().unwrap().user_data.clone()
|
self.0.data.read().user_data.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn device_id(&self) -> &str {
|
pub fn device_id(&self) -> &str {
|
||||||
|
@ -343,21 +343,15 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connection_id(&self) -> String {
|
pub fn connection_id(&self) -> String {
|
||||||
self.0.data.read().unwrap().connection_id.clone()
|
self.0.data.read().connection_id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_connection_id(&self, connection_id: String) {
|
pub fn set_connection_id(&self, connection_id: String) {
|
||||||
self.0.data.write().unwrap().connection_id = connection_id;
|
self.0.data.write().connection_id = connection_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn username(&self) -> String {
|
pub fn username(&self) -> String {
|
||||||
self.0
|
self.0.data.read().user_data.canonical_username.clone()
|
||||||
.data
|
|
||||||
.read()
|
|
||||||
.unwrap()
|
|
||||||
.user_data
|
|
||||||
.canonical_username
|
|
||||||
.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_user_attribute(&self, key: &str, value: &str) -> Option<String> {
|
pub fn set_user_attribute(&self, key: &str, value: &str) -> Option<String> {
|
||||||
|
@ -368,7 +362,6 @@ impl Session {
|
||||||
self.0
|
self.0
|
||||||
.data
|
.data
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
|
||||||
.user_data
|
.user_data
|
||||||
.attributes
|
.attributes
|
||||||
.insert(key.to_owned(), value.to_owned())
|
.insert(key.to_owned(), value.to_owned())
|
||||||
|
@ -377,13 +370,7 @@ impl Session {
|
||||||
pub fn set_user_attributes(&self, attributes: UserAttributes) {
|
pub fn set_user_attributes(&self, attributes: UserAttributes) {
|
||||||
Self::check_catalogue(&attributes);
|
Self::check_catalogue(&attributes);
|
||||||
|
|
||||||
self.0
|
self.0.data.write().user_data.attributes.extend(attributes)
|
||||||
.data
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.user_data
|
|
||||||
.attributes
|
|
||||||
.extend(attributes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weak(&self) -> SessionWeak {
|
fn weak(&self) -> SessionWeak {
|
||||||
|
@ -395,14 +382,14 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown(&self) {
|
pub fn shutdown(&self) {
|
||||||
debug!("Invalidating session[{}]", self.0.session_id);
|
debug!("Invalidating session [{}]", self.0.session_id);
|
||||||
self.0.data.write().unwrap().invalid = true;
|
self.0.data.write().invalid = true;
|
||||||
self.mercury().shutdown();
|
self.mercury().shutdown();
|
||||||
self.channel().shutdown();
|
self.channel().shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_invalid(&self) -> bool {
|
pub fn is_invalid(&self) -> bool {
|
||||||
self.0.data.read().unwrap().invalid
|
self.0.data.read().invalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +402,8 @@ impl SessionWeak {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn upgrade(&self) -> Session {
|
pub(crate) fn upgrade(&self) -> Session {
|
||||||
self.try_upgrade().expect("Session died") // TODO
|
self.try_upgrade()
|
||||||
|
.expect("session was dropped and so should have this component")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,14 @@ form_urlencoded = "1.0"
|
||||||
futures-core = "0.3"
|
futures-core = "0.3"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
hmac = "0.11"
|
hmac = "0.11"
|
||||||
hyper = { version = "0.14", features = ["server", "http1", "tcp"] }
|
hyper = { version = "0.14", features = ["http1", "server", "tcp"] }
|
||||||
libmdns = "0.6"
|
libmdns = "0.6"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
serde_json = "1.0.25"
|
serde_json = "1.0.25"
|
||||||
sha-1 = "0.9"
|
sha-1 = "0.9"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1.0", features = ["sync", "rt"] }
|
tokio = { version = "1.0", features = ["parking_lot", "sync", "rt"] }
|
||||||
|
|
||||||
dns-sd = { version = "0.1.3", optional = true }
|
dns-sd = { version = "0.1.3", optional = true }
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ version = "0.3.1"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
tokio = { version = "1.0", features = ["macros", "rt"] }
|
tokio = { version = "1.0", features = ["macros", "parking_lot", "rt"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
with-dns-sd = ["dns-sd"]
|
with-dns-sd = ["dns-sd"]
|
||||||
|
|
|
@ -24,7 +24,7 @@ log = "0.4"
|
||||||
byteorder = "1.4"
|
byteorder = "1.4"
|
||||||
shell-words = "1.0.0"
|
shell-words = "1.0.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
tokio = { version = "1", features = ["rt", "rt-multi-thread", "sync"] }
|
tokio = { version = "1", features = ["parking_lot", "rt", "rt-multi-thread", "sync"] }
|
||||||
zerocopy = { version = "0.3" }
|
zerocopy = { version = "0.3" }
|
||||||
|
|
||||||
# Backends
|
# Backends
|
||||||
|
|
Loading…
Reference in a new issue