mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-03-31 17:53:44 -04:00
upgrade to 2018 Rust edition
This is mostly just "cargo fix --edition" + Cargo.toml changes. There's one fix for upgrading to NLL in db/writer.rs: Writer::previously_opened wouldn't build with NLL because of a double-borrow the previous borrow checker somehow didn't catch. Restructure to avoid it. I'll put elective NLL changes in a following commit.
This commit is contained in:
parent
ff58f24785
commit
699ec87968
@ -3,6 +3,7 @@ name = "moonfire-base"
|
|||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
authors = ["Scott Lamb <slamb@slamb.org>"]
|
authors = ["Scott Lamb <slamb@slamb.org>"]
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
nightly = []
|
nightly = []
|
||||||
|
@ -3,6 +3,7 @@ name = "moonfire-db"
|
|||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
authors = ["Scott Lamb <slamb@slamb.org>"]
|
authors = ["Scott Lamb <slamb@slamb.org>"]
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
nightly = []
|
nightly = []
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use base::strutil;
|
use crate::base::strutil;
|
||||||
use blake2_rfc::blake2b::blake2b;
|
use blake2_rfc::blake2b::blake2b;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
@ -730,10 +730,10 @@ fn lookup_session(conn: &Connection, hash: &SessionHash) -> Result<Session, Erro
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use db;
|
use crate::db;
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use super::*;
|
use super::*;
|
||||||
use testutil;
|
use crate::testutil;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_empty_db() {
|
fn open_empty_db() {
|
||||||
|
10
db/check.rs
10
db/check.rs
@ -30,14 +30,14 @@
|
|||||||
|
|
||||||
//! Subcommand to check the database and sample file dir for errors.
|
//! Subcommand to check the database and sample file dir for errors.
|
||||||
|
|
||||||
use db::{self, CompositeId, FromSqlUuid};
|
use crate::db::{self, CompositeId, FromSqlUuid};
|
||||||
use dir;
|
use crate::dir;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use raw;
|
use crate::raw;
|
||||||
use recording;
|
use crate::recording;
|
||||||
use rusqlite::{self, types::ToSql};
|
use rusqlite::{self, types::ToSql};
|
||||||
use schema;
|
use crate::schema;
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
36
db/db.rs
36
db/db.rs
@ -52,18 +52,18 @@
|
|||||||
//! A list of mutations is built up in-memory and occasionally flushed to reduce SSD write
|
//! A list of mutations is built up in-memory and occasionally flushed to reduce SSD write
|
||||||
//! cycles.
|
//! cycles.
|
||||||
|
|
||||||
use auth;
|
use crate::auth;
|
||||||
use base::clock::{self, Clocks};
|
use crate::base::clock::{self, Clocks};
|
||||||
use dir;
|
use crate::dir;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use fnv::{self, FnvHashMap, FnvHashSet};
|
use fnv::{self, FnvHashMap, FnvHashSet};
|
||||||
use lru_cache::LruCache;
|
use lru_cache::LruCache;
|
||||||
use openssl::hash;
|
use openssl::hash;
|
||||||
use parking_lot::{Mutex,MutexGuard};
|
use parking_lot::{Mutex,MutexGuard};
|
||||||
use raw;
|
use crate::raw;
|
||||||
use recording::{self, TIME_UNITS_PER_SEC};
|
use crate::recording::{self, TIME_UNITS_PER_SEC};
|
||||||
use rusqlite::{self, types::ToSql};
|
use rusqlite::{self, types::ToSql};
|
||||||
use schema;
|
use crate::schema;
|
||||||
use std::collections::{BTreeMap, VecDeque};
|
use std::collections::{BTreeMap, VecDeque};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@ -309,11 +309,11 @@ impl SampleFileDir {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use auth::Request;
|
pub use crate::auth::Request;
|
||||||
pub use auth::RawSessionId;
|
pub use crate::auth::RawSessionId;
|
||||||
pub use auth::Session;
|
pub use crate::auth::Session;
|
||||||
pub use auth::User;
|
pub use crate::auth::User;
|
||||||
pub use auth::UserChange;
|
pub use crate::auth::UserChange;
|
||||||
|
|
||||||
/// In-memory state about a camera.
|
/// In-memory state about a camera.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -735,13 +735,13 @@ impl StreamStateChanger {
|
|||||||
/// Applies the change to the given `streams_by_id`. The caller is expected to set
|
/// Applies the change to the given `streams_by_id`. The caller is expected to set
|
||||||
/// `Camera::streams` to the return value.
|
/// `Camera::streams` to the return value.
|
||||||
fn apply(mut self, streams_by_id: &mut BTreeMap<i32, Stream>) -> [Option<i32>; 2] {
|
fn apply(mut self, streams_by_id: &mut BTreeMap<i32, Stream>) -> [Option<i32>; 2] {
|
||||||
for (id, mut stream) in self.streams.drain(..) {
|
for (id, stream) in self.streams.drain(..) {
|
||||||
use ::std::collections::btree_map::Entry;
|
use ::std::collections::btree_map::Entry;
|
||||||
match (streams_by_id.entry(id), stream) {
|
match (streams_by_id.entry(id), stream) {
|
||||||
(Entry::Vacant(mut e), Some(new)) => { e.insert(new); },
|
(Entry::Vacant(e), Some(new)) => { e.insert(new); },
|
||||||
(Entry::Vacant(_), None) => {},
|
(Entry::Vacant(_), None) => {},
|
||||||
(Entry::Occupied(mut e), Some(new)) => { e.insert(new); },
|
(Entry::Occupied(mut e), Some(new)) => { e.insert(new); },
|
||||||
(Entry::Occupied(mut e), None) => { e.remove(); },
|
(Entry::Occupied(e), None) => { e.remove(); },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.sids
|
self.sids
|
||||||
@ -874,7 +874,7 @@ impl LockedDatabase {
|
|||||||
for dir in self.sample_file_dirs_by_id.values() {
|
for dir in self.sample_file_dirs_by_id.values() {
|
||||||
raw::mark_sample_files_deleted(&tx, &dir.garbage_unlinked)?;
|
raw::mark_sample_files_deleted(&tx, &dir.garbage_unlinked)?;
|
||||||
}
|
}
|
||||||
for (&stream_id, mut r) in &mut new_ranges {
|
for (&stream_id, r) in &mut new_ranges {
|
||||||
*r = raw::get_range(&tx, stream_id)?;
|
*r = raw::get_range(&tx, stream_id)?;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -1921,11 +1921,11 @@ impl<'db, C: Clocks + Clone> ::std::ops::DerefMut for DatabaseGuard<'db, C> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
extern crate tempdir;
|
extern crate tempdir;
|
||||||
|
|
||||||
use base::clock;
|
use crate::base::clock;
|
||||||
use recording::{self, TIME_UNITS_PER_SEC};
|
use crate::recording::{self, TIME_UNITS_PER_SEC};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use testutil;
|
use crate::testutil;
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::adjust_days; // non-public.
|
use super::adjust_days; // non-public.
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -32,11 +32,11 @@
|
|||||||
//!
|
//!
|
||||||
//! This includes opening files for serving, rotating away old files, and saving new files.
|
//! This includes opening files for serving, rotating away old files, and saving new files.
|
||||||
|
|
||||||
use db::CompositeId;
|
use crate::db::CompositeId;
|
||||||
use failure::{Error, Fail};
|
use failure::{Error, Fail};
|
||||||
use libc::{self, c_char};
|
use libc::{self, c_char};
|
||||||
use protobuf::{self, Message};
|
use protobuf::{self, Message};
|
||||||
use schema;
|
use crate::schema;
|
||||||
use std::ffi;
|
use std::ffi;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{self, Read, Write};
|
use std::io::{self, Read, Write};
|
||||||
|
@ -65,4 +65,4 @@ pub mod writer;
|
|||||||
// #[cfg(test)] is not passed on to dependencies.
|
// #[cfg(test)] is not passed on to dependencies.
|
||||||
pub mod testutil;
|
pub mod testutil;
|
||||||
|
|
||||||
pub use db::*;
|
pub use crate::db::*;
|
||||||
|
@ -30,10 +30,10 @@
|
|||||||
|
|
||||||
//! Raw database access: SQLite statements which do not touch any cached state.
|
//! Raw database access: SQLite statements which do not touch any cached state.
|
||||||
|
|
||||||
use db::{self, CompositeId, FromSqlUuid};
|
use crate::db::{self, CompositeId, FromSqlUuid};
|
||||||
use failure::{Error, ResultExt};
|
use failure::{Error, ResultExt};
|
||||||
use fnv::FnvHashSet;
|
use fnv::FnvHashSet;
|
||||||
use recording;
|
use crate::recording;
|
||||||
use rusqlite::{self, types::ToSql};
|
use rusqlite::{self, types::ToSql};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use coding::{append_varint32, decode_varint32, unzigzag32, zigzag32};
|
use crate::coding::{append_varint32, decode_varint32, unzigzag32, zigzag32};
|
||||||
use db;
|
use crate::db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
@ -492,8 +492,8 @@ impl Segment {
|
|||||||
// Note: this inner loop uses try! rather than ? for performance. Don't change these
|
// Note: this inner loop uses try! rather than ? for performance. Don't change these
|
||||||
// lines without reading https://github.com/rust-lang/rust/issues/37939 and running
|
// lines without reading https://github.com/rust-lang/rust/issues/37939 and running
|
||||||
// mp4::bench::build_index.
|
// mp4::bench::build_index.
|
||||||
try!(f(&it));
|
r#try!(f(&it));
|
||||||
have_frame = try!(it.next(data));
|
have_frame = r#try!(it.next(data));
|
||||||
}
|
}
|
||||||
if key_frame < self.key_frames {
|
if key_frame < self.key_frames {
|
||||||
bail!("recording {}: expected {} key frames, found only {}",
|
bail!("recording {}: expected {} key frames, found only {}",
|
||||||
@ -505,9 +505,9 @@ impl Segment {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use base::clock::RealClocks;
|
use crate::base::clock::RealClocks;
|
||||||
use super::*;
|
use super::*;
|
||||||
use testutil::{self, TestDb};
|
use crate::testutil::{self, TestDb};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_time() {
|
fn test_parse_time() {
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use base::clock::Clocks;
|
use crate::base::clock::Clocks;
|
||||||
use db;
|
use crate::db;
|
||||||
use dir;
|
use crate::dir;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use mylog;
|
use mylog;
|
||||||
use rusqlite;
|
use rusqlite;
|
||||||
@ -40,7 +40,7 @@ use std::thread;
|
|||||||
use tempdir::TempDir;
|
use tempdir::TempDir;
|
||||||
use time;
|
use time;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use writer;
|
use crate::writer;
|
||||||
|
|
||||||
static INIT: sync::Once = sync::ONCE_INIT;
|
static INIT: sync::Once = sync::ONCE_INIT;
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ pub fn init() {
|
|||||||
h.install().unwrap();
|
h.install().unwrap();
|
||||||
env::set_var("TZ", "America/Los_Angeles");
|
env::set_var("TZ", "America/Los_Angeles");
|
||||||
time::tzset();
|
time::tzset();
|
||||||
::auth::set_test_config();
|
crate::auth::set_test_config();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ impl<C: Clocks + Clone> TestDb<C> {
|
|||||||
/// There will no backing sample file, so it won't be possible to generate a full `.mp4`.
|
/// There will no backing sample file, so it won't be possible to generate a full `.mp4`.
|
||||||
pub fn insert_recording_from_encoder(&self, r: db::RecordingToInsert)
|
pub fn insert_recording_from_encoder(&self, r: db::RecordingToInsert)
|
||||||
-> db::ListRecordingsRow {
|
-> db::ListRecordingsRow {
|
||||||
use recording::{self, TIME_UNITS_PER_SEC};
|
use crate::recording::{self, TIME_UNITS_PER_SEC};
|
||||||
let mut db = self.db.lock();
|
let mut db = self.db.lock();
|
||||||
let video_sample_entry_id = db.insert_video_sample_entry(
|
let video_sample_entry_id = db.insert_video_sample_entry(
|
||||||
1920, 1080, [0u8; 100].to_vec(), "avc1.000000".to_owned()).unwrap();
|
1920, 1080, [0u8; 100].to_vec(), "avc1.000000".to_owned()).unwrap();
|
||||||
@ -153,7 +153,7 @@ impl<C: Clocks + Clone> TestDb<C> {
|
|||||||
// For benchmarking
|
// For benchmarking
|
||||||
#[cfg(feature="nightly")]
|
#[cfg(feature="nightly")]
|
||||||
pub fn add_dummy_recordings_to_db(db: &db::Database, num: usize) {
|
pub fn add_dummy_recordings_to_db(db: &db::Database, num: usize) {
|
||||||
use recording::{self, TIME_UNITS_PER_SEC};
|
use crate::recording::{self, TIME_UNITS_PER_SEC};
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
data.extend_from_slice(include_bytes!("testdata/video_sample_index.bin"));
|
data.extend_from_slice(include_bytes!("testdata/video_sample_index.bin"));
|
||||||
let mut db = db.lock();
|
let mut db = db.lock();
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
///
|
///
|
||||||
/// See `guide/schema.md` for more information.
|
/// See `guide/schema.md` for more information.
|
||||||
|
|
||||||
use db;
|
use crate::db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use rusqlite::{self, types::ToSql};
|
use rusqlite::{self, types::ToSql};
|
||||||
|
|
||||||
|
@ -30,9 +30,9 @@
|
|||||||
|
|
||||||
/// Upgrades a version 0 schema to a version 1 schema.
|
/// Upgrades a version 0 schema to a version 1 schema.
|
||||||
|
|
||||||
use db;
|
use crate::db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use recording;
|
use crate::recording;
|
||||||
use rusqlite::{self, types::ToSql};
|
use rusqlite::{self, types::ToSql};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
@ -30,11 +30,11 @@
|
|||||||
|
|
||||||
/// Upgrades a version 1 schema to a version 2 schema.
|
/// Upgrades a version 1 schema to a version 2 schema.
|
||||||
|
|
||||||
use dir;
|
use crate::dir;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use libc;
|
use libc;
|
||||||
use rusqlite::{self, types::ToSql};
|
use rusqlite::{self, types::ToSql};
|
||||||
use schema::DirMeta;
|
use crate::schema::DirMeta;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@ -332,7 +332,7 @@ fn verify_dir_contents(sample_file_path: &str, tx: &rusqlite::Transaction) -> Re
|
|||||||
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let uuid: ::db::FromSqlUuid = row.get_checked(0)?;
|
let uuid: crate::db::FromSqlUuid = row.get_checked(0)?;
|
||||||
if !files.remove(&uuid.0) {
|
if !files.remove(&uuid.0) {
|
||||||
bail!("{} is missing from dir {}!", uuid.0, sample_file_path);
|
bail!("{} is missing from dir {}!", uuid.0, sample_file_path);
|
||||||
}
|
}
|
||||||
@ -343,7 +343,7 @@ fn verify_dir_contents(sample_file_path: &str, tx: &rusqlite::Transaction) -> Re
|
|||||||
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let uuid: ::db::FromSqlUuid = row.get_checked(0)?;
|
let uuid: crate::db::FromSqlUuid = row.get_checked(0)?;
|
||||||
files.remove(&uuid.0);
|
files.remove(&uuid.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,11 +32,11 @@
|
|||||||
/// Note that a version 2 schema is never actually used; so we know the upgrade from version 1 was
|
/// Note that a version 2 schema is never actually used; so we know the upgrade from version 1 was
|
||||||
/// completed, and possibly an upgrade from 2 to 3 is half-finished.
|
/// completed, and possibly an upgrade from 2 to 3 is half-finished.
|
||||||
|
|
||||||
use db::{self, FromSqlUuid};
|
use crate::db::{self, FromSqlUuid};
|
||||||
use dir;
|
use crate::dir;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use libc;
|
use libc;
|
||||||
use schema;
|
use crate::schema;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
40
db/writer.rs
40
db/writer.rs
@ -32,13 +32,13 @@
|
|||||||
//!
|
//!
|
||||||
//! This includes opening files for serving, rotating away old files, and saving new files.
|
//! This includes opening files for serving, rotating away old files, and saving new files.
|
||||||
|
|
||||||
use base::clock::{self, Clocks};
|
use crate::base::clock::{self, Clocks};
|
||||||
use db::{self, CompositeId};
|
use crate::db::{self, CompositeId};
|
||||||
use dir;
|
use crate::dir;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use recording;
|
use crate::recording;
|
||||||
use openssl::hash;
|
use openssl::hash;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io;
|
use std::io;
|
||||||
@ -588,12 +588,13 @@ impl<'a, C: Clocks + Clone, D: DirWriter> Writer<'a, C, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Opens a new writer.
|
/// Opens a new writer.
|
||||||
/// This returns a writer that violates the invariant that `unflushed_sample` is `Some`.
|
/// On successful return, `self.state` will be `WriterState::Open(w)` with `w` violating the
|
||||||
/// The caller (`write`) is responsible for correcting this.
|
/// invariant that `unflushed_sample` is `Some`. The caller (`write`) is responsible for
|
||||||
fn open(&mut self) -> Result<&mut InnerWriter<D::File>, Error> {
|
/// correcting this.
|
||||||
|
fn open(&mut self) -> Result<(), Error> {
|
||||||
let prev = match self.state {
|
let prev = match self.state {
|
||||||
WriterState::Unopened => None,
|
WriterState::Unopened => None,
|
||||||
WriterState::Open(ref mut w) => return Ok(w),
|
WriterState::Open(_) => return Ok(()),
|
||||||
WriterState::Closed(prev) => Some(prev),
|
WriterState::Closed(prev) => Some(prev),
|
||||||
};
|
};
|
||||||
let (id, r) = self.db.lock().add_recording(self.stream_id, db::RecordingToInsert {
|
let (id, r) = self.db.lock().add_recording(self.stream_id, db::RecordingToInsert {
|
||||||
@ -614,12 +615,9 @@ impl<'a, C: Clocks + Clone, D: DirWriter> Writer<'a, C, D> {
|
|||||||
local_start: recording::Time(i64::max_value()),
|
local_start: recording::Time(i64::max_value()),
|
||||||
adjuster: ClockAdjuster::new(prev.map(|p| p.local_time_delta.0)),
|
adjuster: ClockAdjuster::new(prev.map(|p| p.local_time_delta.0)),
|
||||||
unflushed_sample: None,
|
unflushed_sample: None,
|
||||||
});
|
});
|
||||||
match self.state {
|
Ok(())
|
||||||
WriterState::Open(ref mut w) => Ok(w),
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn previously_opened(&self) -> Result<bool, Error> {
|
pub fn previously_opened(&self) -> Result<bool, Error> {
|
||||||
Ok(match self.state {
|
Ok(match self.state {
|
||||||
@ -633,7 +631,11 @@ impl<'a, C: Clocks + Clone, D: DirWriter> Writer<'a, C, D> {
|
|||||||
/// `local_time` should be the local clock's time as of when this packet was received.
|
/// `local_time` should be the local clock's time as of when this packet was received.
|
||||||
pub fn write(&mut self, pkt: &[u8], local_time: recording::Time, pts_90k: i64,
|
pub fn write(&mut self, pkt: &[u8], local_time: recording::Time, pts_90k: i64,
|
||||||
is_key: bool) -> Result<(), Error> {
|
is_key: bool) -> Result<(), Error> {
|
||||||
let w = self.open()?;
|
self.open()?;
|
||||||
|
let w = match self.state {
|
||||||
|
WriterState::Open(ref mut w) => w,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
// Note w's invariant that `unflushed_sample` is `None` may currently be violated.
|
// Note w's invariant that `unflushed_sample` is `None` may currently be violated.
|
||||||
// We must restore it on all success or error paths.
|
// We must restore it on all success or error paths.
|
||||||
@ -739,16 +741,16 @@ impl<'a, C: Clocks + Clone, D: DirWriter> Drop for Writer<'a, C, D> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use base::clock::SimulatedClocks;
|
use crate::base::clock::SimulatedClocks;
|
||||||
use db::{self, CompositeId};
|
use crate::db::{self, CompositeId};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use recording;
|
use crate::recording;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use super::{ClockAdjuster, Writer};
|
use super::{ClockAdjuster, Writer};
|
||||||
use testutil;
|
use crate::testutil;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct MockDir(Arc<Mutex<VecDeque<MockDirAction>>>);
|
struct MockDir(Arc<Mutex<VecDeque<MockDirAction>>>);
|
||||||
|
@ -3,6 +3,7 @@ name = "moonfire-ffmpeg"
|
|||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
authors = ["Scott Lamb <slamb@slamb.org>"]
|
authors = ["Scott Lamb <slamb@slamb.org>"]
|
||||||
readme = "../README.md"
|
readme = "../README.md"
|
||||||
|
edition = "2018"
|
||||||
#links = "ffmpeg"
|
#links = "ffmpeg"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
//! Subcommand to check the database and sample file dir for errors.
|
//! Subcommand to check the database and sample file dir for errors.
|
||||||
|
|
||||||
use db::check;
|
use crate::db::check;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
static USAGE: &'static str = r#"
|
static USAGE: &'static str = r#"
|
||||||
|
@ -33,12 +33,12 @@ extern crate cursive;
|
|||||||
use self::cursive::Cursive;
|
use self::cursive::Cursive;
|
||||||
use self::cursive::traits::{Boxable, Identifiable, Finder};
|
use self::cursive::traits::{Boxable, Identifiable, Finder};
|
||||||
use self::cursive::views;
|
use self::cursive::views;
|
||||||
use db::{self, writer};
|
use crate::db::{self, writer};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use stream::{self, Opener, Stream};
|
use crate::stream::{self, Opener, Stream};
|
||||||
use super::{decode_size, encode_size};
|
use super::{decode_size, encode_size};
|
||||||
|
|
||||||
/// Builds a `CameraChange` from an active `edit_camera_dialog`.
|
/// Builds a `CameraChange` from an active `edit_camera_dialog`.
|
||||||
|
@ -33,7 +33,7 @@ extern crate cursive;
|
|||||||
use self::cursive::Cursive;
|
use self::cursive::Cursive;
|
||||||
use self::cursive::traits::{Boxable, Identifiable};
|
use self::cursive::traits::{Boxable, Identifiable};
|
||||||
use self::cursive::views;
|
use self::cursive::views;
|
||||||
use db::{self, writer};
|
use crate::db::{self, writer};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -37,8 +37,8 @@ extern crate cursive;
|
|||||||
|
|
||||||
use self::cursive::Cursive;
|
use self::cursive::Cursive;
|
||||||
use self::cursive::views;
|
use self::cursive::views;
|
||||||
use clock;
|
use crate::clock;
|
||||||
use db;
|
use crate::db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -33,7 +33,7 @@ extern crate cursive;
|
|||||||
use self::cursive::Cursive;
|
use self::cursive::Cursive;
|
||||||
use self::cursive::traits::{Boxable, Identifiable};
|
use self::cursive::traits::{Boxable, Identifiable};
|
||||||
use self::cursive::views;
|
use self::cursive::views;
|
||||||
use db;
|
use crate::db;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// Builds a `UserChange` from an active `edit_user_dialog`.
|
/// Builds a `UserChange` from an active `edit_user_dialog`.
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use db;
|
use crate::db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
static USAGE: &'static str = r#"
|
static USAGE: &'static str = r#"
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use db::dir;
|
use crate::db::dir;
|
||||||
use docopt;
|
use docopt;
|
||||||
use failure::{Error, Fail};
|
use failure::{Error, Fail};
|
||||||
use libc;
|
use libc;
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use clock;
|
use crate::clock;
|
||||||
use db::{self, dir, writer};
|
use crate::db::{self, dir, writer};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use futures::{Future, Stream};
|
use futures::{Future, Stream};
|
||||||
@ -37,11 +37,11 @@ use std::error::Error as StdError;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use stream;
|
use crate::stream;
|
||||||
use streamer;
|
use crate::streamer;
|
||||||
use tokio;
|
use tokio;
|
||||||
use tokio_signal::unix::{Signal, SIGINT, SIGTERM};
|
use tokio_signal::unix::{Signal, SIGINT, SIGTERM};
|
||||||
use web;
|
use crate::web;
|
||||||
|
|
||||||
// These are used in a hack to get the name of the current time zone (e.g. America/Los_Angeles).
|
// These are used in a hack to get the name of the current time zone (e.g. America/Los_Angeles).
|
||||||
// They seem to be correct for Linux and macOS at least.
|
// They seem to be correct for Linux and macOS at least.
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use db::recording;
|
use crate::db::recording;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
const USAGE: &'static str = r#"
|
const USAGE: &'static str = r#"
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
///
|
///
|
||||||
/// See `guide/schema.md` for more information.
|
/// See `guide/schema.md` for more information.
|
||||||
|
|
||||||
use db;
|
use crate::db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
const USAGE: &'static str = r#"
|
const USAGE: &'static str = r#"
|
||||||
|
@ -248,7 +248,7 @@ pub fn transform_sample_data(annexb_sample: &[u8], avc_sample: &mut Vec<u8>) ->
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use db::testutil;
|
use crate::db::testutil;
|
||||||
|
|
||||||
const ANNEX_B_TEST_INPUT: [u8; 35] = [
|
const ANNEX_B_TEST_INPUT: [u8; 35] = [
|
||||||
0x00, 0x00, 0x00, 0x01, 0x67, 0x4d, 0x00, 0x1f,
|
0x00, 0x00, 0x00, 0x01, 0x67, 0x4d, 0x00, 0x1f,
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use db::{self, auth::SessionHash};
|
use crate::db::{self, auth::SessionHash};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use serde::ser::{SerializeMap, SerializeSeq, Serializer};
|
use serde::ser::{SerializeMap, SerializeSeq, Serializer};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
@ -67,7 +67,7 @@ extern crate tokio_signal;
|
|||||||
extern crate url;
|
extern crate url;
|
||||||
extern crate uuid;
|
extern crate uuid;
|
||||||
|
|
||||||
use base::clock as clock;
|
use crate::base::clock as clock;
|
||||||
|
|
||||||
mod body;
|
mod body;
|
||||||
mod cmds;
|
mod cmds;
|
||||||
@ -141,7 +141,7 @@ fn main() {
|
|||||||
.build();
|
.build();
|
||||||
h.clone().install().unwrap();
|
h.clone().install().unwrap();
|
||||||
|
|
||||||
if let Err(e) = { let _a = h.async(); args.arg_command.unwrap().run() } {
|
if let Err(e) = { let _a = h.r#async(); args.arg_command.unwrap().run() } {
|
||||||
error!("{:?}", e);
|
error!("{:?}", e);
|
||||||
::std::process::exit(1);
|
::std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
22
src/mp4.rs
22
src/mp4.rs
@ -78,12 +78,12 @@
|
|||||||
|
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
||||||
use base::strutil;
|
use crate::base::strutil;
|
||||||
use bytes::{Buf, BytesMut};
|
use bytes::{Buf, BytesMut};
|
||||||
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
|
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
|
||||||
use body::{Chunk, BoxedError, wrap_error};
|
use crate::body::{Chunk, BoxedError, wrap_error};
|
||||||
use db::recording::{self, TIME_UNITS_PER_SEC};
|
use crate::db::recording::{self, TIME_UNITS_PER_SEC};
|
||||||
use db::{self, dir};
|
use crate::db::{self, dir};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use futures::stream;
|
use futures::stream;
|
||||||
@ -94,7 +94,7 @@ use memmap;
|
|||||||
use openssl::hash;
|
use openssl::hash;
|
||||||
use parking_lot::{Once, ONCE_INIT};
|
use parking_lot::{Once, ONCE_INIT};
|
||||||
use reffers::ARefs;
|
use reffers::ARefs;
|
||||||
use slices::{self, Slices};
|
use crate::slices::{self, Slices};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@ -1530,13 +1530,13 @@ impl http_serve::Entity for File {
|
|||||||
/// to verify the output is byte-for-byte as expected.
|
/// to verify the output is byte-for-byte as expected.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use base::strutil;
|
use crate::base::strutil;
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use clock::RealClocks;
|
use crate::clock::RealClocks;
|
||||||
use db::recording::{self, TIME_UNITS_PER_SEC};
|
use crate::db::recording::{self, TIME_UNITS_PER_SEC};
|
||||||
use db::testutil::{self, TestDb, TEST_STREAM_ID};
|
use crate::db::testutil::{self, TestDb, TEST_STREAM_ID};
|
||||||
use db::writer;
|
use crate::db::writer;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use futures::Stream as FuturesStream;
|
use futures::Stream as FuturesStream;
|
||||||
use openssl::hash;
|
use openssl::hash;
|
||||||
@ -1546,7 +1546,7 @@ mod tests {
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::str;
|
use std::str;
|
||||||
use super::*;
|
use super::*;
|
||||||
use stream::{self, Opener, Stream};
|
use crate::stream::{self, Opener, Stream};
|
||||||
|
|
||||||
fn fill_slice<E: http_serve::Entity>(slice: &mut [u8], e: &E, start: u64)
|
fn fill_slice<E: http_serve::Entity>(slice: &mut [u8], e: &E, start: u64)
|
||||||
where E::Error : ::std::fmt::Debug {
|
where E::Error : ::std::fmt::Debug {
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
//! Tools for implementing a `http_serve::Entity` body composed from many "slices".
|
//! Tools for implementing a `http_serve::Entity` body composed from many "slices".
|
||||||
|
|
||||||
use body::{BoxedError, wrap_error};
|
use crate::body::{BoxedError, wrap_error};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use futures::stream;
|
use futures::stream;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
@ -149,8 +149,8 @@ impl<S> Slices<S> where S: Slice {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use body::BoxedError;
|
use crate::body::BoxedError;
|
||||||
use db::testutil;
|
use crate::db::testutil;
|
||||||
use futures::{Future, Stream};
|
use futures::{Future, Stream};
|
||||||
use futures::stream;
|
use futures::stream;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use h264;
|
use crate::h264;
|
||||||
use moonfire_ffmpeg;
|
use moonfire_ffmpeg;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
@ -28,14 +28,14 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use clock::{Clocks, TimerGuard};
|
use crate::clock::{Clocks, TimerGuard};
|
||||||
use db::{Camera, Database, Stream, dir, recording, writer};
|
use crate::db::{Camera, Database, Stream, dir, recording, writer};
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use h264;
|
use crate::h264;
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use stream;
|
use crate::stream;
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
pub static ROTATE_INTERVAL_SEC: i64 = 60;
|
pub static ROTATE_INTERVAL_SEC: i64 = 60;
|
||||||
@ -186,18 +186,18 @@ impl<'a, C, S> Streamer<'a, C, S> where C: 'a + Clocks + Clone, S: 'a + stream::
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use clock::{self, Clocks};
|
use crate::clock::{self, Clocks};
|
||||||
use db::{self, CompositeId};
|
use crate::db::{self, CompositeId};
|
||||||
use db::recording;
|
use crate::db::recording;
|
||||||
use db::testutil;
|
use crate::db::testutil;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use h264;
|
use crate::h264;
|
||||||
use moonfire_ffmpeg;
|
use moonfire_ffmpeg;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use stream::{self, Opener, Stream};
|
use crate::stream::{self, Opener, Stream};
|
||||||
use time;
|
use time;
|
||||||
|
|
||||||
struct ProxyingStream<'a> {
|
struct ProxyingStream<'a> {
|
||||||
|
22
src/web.rs
22
src/web.rs
@ -30,24 +30,24 @@
|
|||||||
|
|
||||||
extern crate hyper;
|
extern crate hyper;
|
||||||
|
|
||||||
use base::clock::Clocks;
|
use crate::base::clock::Clocks;
|
||||||
use base::strutil;
|
use crate::base::strutil;
|
||||||
use body::{Body, BoxedError};
|
use crate::body::{Body, BoxedError};
|
||||||
use base64;
|
use base64;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use core::borrow::Borrow;
|
use core::borrow::Borrow;
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use db::{self, auth, recording};
|
use crate::db::{self, auth, recording};
|
||||||
use db::dir::SampleFileDir;
|
use crate::db::dir::SampleFileDir;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use futures::{Future, Stream, future};
|
use futures::{Future, Stream, future};
|
||||||
use futures_cpupool;
|
use futures_cpupool;
|
||||||
use json;
|
use crate::json;
|
||||||
use http::{self, Request, Response, status::StatusCode};
|
use http::{self, Request, Response, status::StatusCode};
|
||||||
use http_serve;
|
use http_serve;
|
||||||
use http::header::{self, HeaderValue};
|
use http::header::{self, HeaderValue};
|
||||||
use mp4;
|
use crate::mp4;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -842,8 +842,8 @@ impl ::hyper::service::Service for Service {
|
|||||||
mod tests {
|
mod tests {
|
||||||
extern crate reqwest;
|
extern crate reqwest;
|
||||||
|
|
||||||
use db;
|
use crate::db;
|
||||||
use db::testutil::{self, TestDb};
|
use crate::db::testutil::{self, TestDb};
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use http::{self, header};
|
use http::{self, header};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@ -851,7 +851,7 @@ mod tests {
|
|||||||
use super::Segments;
|
use super::Segments;
|
||||||
|
|
||||||
struct Server {
|
struct Server {
|
||||||
db: TestDb<::base::clock::RealClocks>,
|
db: TestDb<crate::base::clock::RealClocks>,
|
||||||
base_url: String,
|
base_url: String,
|
||||||
//test_camera_uuid: Uuid,
|
//test_camera_uuid: Uuid,
|
||||||
handle: Option<::std::thread::JoinHandle<()>>,
|
handle: Option<::std::thread::JoinHandle<()>>,
|
||||||
@ -860,7 +860,7 @@ mod tests {
|
|||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
fn new() -> Server {
|
fn new() -> Server {
|
||||||
let db = TestDb::new(::base::clock::RealClocks {});
|
let db = TestDb::new(crate::base::clock::RealClocks {});
|
||||||
let (shutdown_tx, shutdown_rx) = futures::sync::oneshot::channel::<()>();
|
let (shutdown_tx, shutdown_rx) = futures::sync::oneshot::channel::<()>();
|
||||||
let addr = "127.0.0.1:0".parse().unwrap();
|
let addr = "127.0.0.1:0".parse().unwrap();
|
||||||
let require_auth = true;
|
let require_auth = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user