mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2024-12-25 22:55:55 -05:00
update deps (particularly hyper) + fix warnings
This commit is contained in:
parent
857a66f29c
commit
11420df065
739
Cargo.lock
generated
739
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,8 @@ byteorder = "1.0"
|
||||
docopt = "0.8"
|
||||
futures = "0.1"
|
||||
fnv = "1.0"
|
||||
http-entity = { git = "https://github.com/scottlamb/http-entity", branch = "hyper-0.11.x" }
|
||||
hyper = { git = "https://github.com/scottlamb/hyper", branch = "moonfire-on-0.11.x" }
|
||||
http-entity = { git = "https://github.com/scottlamb/http-entity" }
|
||||
hyper = "0.11.2"
|
||||
lazy_static = "0.2"
|
||||
libc = "0.2"
|
||||
log = { version = "0.3", features = ["release_max_level_info"] }
|
||||
@ -44,7 +44,7 @@ url = "1.4"
|
||||
uuid = { version = "0.5", features = ["serde", "v4"] }
|
||||
|
||||
[dev-dependencies]
|
||||
reqwest = "0.6"
|
||||
reqwest = "0.7"
|
||||
tempdir = "0.3"
|
||||
|
||||
[dependencies.cursive]
|
||||
@ -59,5 +59,4 @@ debug = true
|
||||
debug = true
|
||||
|
||||
[replace]
|
||||
"https://github.com/hyperium/hyper#hyper:0.11.0-a.0" = { git = "https://github.com/scottlamb/hyper", branch = "moonfire-on-0.11.x" }
|
||||
"hyper:0.10.12" = { git = "https://github.com/scottlamb/hyper", branch = "moonfire-on-0.10.x" }
|
||||
"hyper:0.11.2" = { git = "https://github.com/scottlamb/hyper", branch = "moonfire-on-0.11.x" }
|
||||
|
@ -76,7 +76,11 @@ static int lock_callback(void **mutex, enum AVLockOp op) {
|
||||
case AV_LOCK_RELEASE:
|
||||
if (pthread_mutex_unlock(*mutex) != 0)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void moonfire_ffmpeg_init(void) {
|
||||
@ -91,7 +95,7 @@ struct moonfire_ffmpeg_streams {
|
||||
};
|
||||
|
||||
struct moonfire_ffmpeg_data {
|
||||
const char *data;
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,7 @@ use clock;
|
||||
use db;
|
||||
use dir;
|
||||
use error::Error;
|
||||
use futures::{BoxFuture, Future, Stream};
|
||||
use futures::{Future, Stream};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::thread;
|
||||
@ -66,13 +66,12 @@ struct Args {
|
||||
flag_read_only: bool,
|
||||
}
|
||||
|
||||
fn setup_shutdown_future(h: &reactor::Handle) -> BoxFuture<(), ()> {
|
||||
fn setup_shutdown_future(h: &reactor::Handle) -> Box<Future<Item = (), Error = ()>> {
|
||||
let int = Signal::new(SIGINT, h).flatten_stream().into_future();
|
||||
let term = Signal::new(SIGTERM, h).flatten_stream().into_future();
|
||||
int.select(term)
|
||||
.map(|_| ())
|
||||
.map_err(|_| ())
|
||||
.boxed()
|
||||
Box::new(int.select(term)
|
||||
.map(|_| ())
|
||||
.map_err(|_| ()))
|
||||
}
|
||||
|
||||
pub fn run() -> Result<(), Error> {
|
||||
|
10
src/db.rs
10
src/db.rs
@ -613,7 +613,7 @@ impl<'a> Transaction<'a> {
|
||||
(":uuid", &uuid),
|
||||
(":state", &(ReservationState::Deleting as i64))
|
||||
])?;
|
||||
let mut m = Transaction::get_mods_by_camera(&mut self.mods_by_camera, row.camera_id);
|
||||
let m = Transaction::get_mods_by_camera(&mut self.mods_by_camera, row.camera_id);
|
||||
m.duration -= row.time.end - row.time.start;
|
||||
m.sample_file_bytes -= row.sample_file_bytes as i64;
|
||||
adjust_days(row.time.clone(), -1, &mut m.days);
|
||||
@ -665,7 +665,7 @@ impl<'a> Transaction<'a> {
|
||||
}
|
||||
}
|
||||
self.must_rollback = true;
|
||||
let mut m = Transaction::get_mods_by_camera(&mut self.mods_by_camera, r.camera_id);
|
||||
let m = Transaction::get_mods_by_camera(&mut self.mods_by_camera, r.camera_id);
|
||||
{
|
||||
let recording_id = m.new_next_recording_id.unwrap_or(cam.next_recording_id);
|
||||
let composite_id = composite_id(r.camera_id, recording_id);
|
||||
@ -720,7 +720,7 @@ impl<'a> Transaction<'a> {
|
||||
if changes != 1 {
|
||||
return Err(Error::new(format!("no such camera {}", camera_id)));
|
||||
}
|
||||
let mut m = Transaction::get_mods_by_camera(&mut self.mods_by_camera, camera_id);
|
||||
let m = Transaction::get_mods_by_camera(&mut self.mods_by_camera, camera_id);
|
||||
m.new_retain_bytes = Some(new_limit);
|
||||
Ok(())
|
||||
}
|
||||
@ -731,7 +731,7 @@ impl<'a> Transaction<'a> {
|
||||
self.precommit()?;
|
||||
self.tx.commit()?;
|
||||
for (&camera_id, m) in &self.mods_by_camera {
|
||||
let mut camera = self.state.cameras_by_id.get_mut(&camera_id)
|
||||
let camera = self.state.cameras_by_id.get_mut(&camera_id)
|
||||
.expect("modified camera must exist");
|
||||
camera.duration += m.duration;
|
||||
camera.sample_file_bytes += m.sample_file_bytes;
|
||||
@ -1348,7 +1348,7 @@ impl Database {
|
||||
},
|
||||
}));
|
||||
{
|
||||
let mut l = &mut *db.lock();
|
||||
let l = &mut *db.lock();
|
||||
l.init_video_sample_entries().annotate_err("init_video_sample_entries")?;
|
||||
l.init_cameras().annotate_err("init_cameras")?;
|
||||
for (&camera_id, ref mut camera) in &mut l.state.cameras_by_id {
|
||||
|
32
src/mp4.rs
32
src/mp4.rs
@ -76,14 +76,12 @@
|
||||
//! * mdat (media data container)
|
||||
//! ```
|
||||
|
||||
extern crate byteorder;
|
||||
extern crate time;
|
||||
|
||||
use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
|
||||
use db;
|
||||
use dir;
|
||||
use error::Error;
|
||||
use futures::Stream;
|
||||
use futures::stream;
|
||||
use http_entity;
|
||||
use hyper::header;
|
||||
@ -396,7 +394,7 @@ impl Segment {
|
||||
v.into_boxed_slice()
|
||||
};
|
||||
{
|
||||
let (stts, mut rest) = buf.split_at_mut(lens.stts);
|
||||
let (stts, rest) = buf.split_at_mut(lens.stts);
|
||||
let (stsz, stss) = rest.split_at_mut(lens.stsz);
|
||||
let mut frame = 0;
|
||||
let mut key_frame = 0;
|
||||
@ -536,7 +534,7 @@ impl slices::Slice for Slice {
|
||||
SliceType::VideoSampleData => f.0.get_video_sample_data(p, range.clone()),
|
||||
SliceType::SubtitleSampleData => f.0.get_subtitle_sample_data(p, range.clone(), len),
|
||||
};
|
||||
stream::once(res
|
||||
Box::new(stream::once(res
|
||||
.map_err(|e| {
|
||||
error!("Error producing {:?}: {:?}", self, e);
|
||||
::hyper::Error::Incomplete
|
||||
@ -548,7 +546,7 @@ impl slices::Slice for Slice {
|
||||
return Err(::hyper::Error::Incomplete);
|
||||
}
|
||||
Ok(c)
|
||||
})).boxed()
|
||||
})))
|
||||
}
|
||||
|
||||
fn get_slices(ctx: &File) -> &Slices<Self> { &ctx.0.slices }
|
||||
@ -1217,7 +1215,10 @@ impl FileInner {
|
||||
#[derive(Clone)]
|
||||
pub struct File(Arc<FileInner>);
|
||||
|
||||
impl http_entity::Entity<Body> for File {
|
||||
impl http_entity::Entity for File {
|
||||
type Chunk = slices::Chunk;
|
||||
type Body = slices::Body;
|
||||
|
||||
fn add_headers(&self, hdrs: &mut header::Headers) {
|
||||
hdrs.set(header::ContentType("video/mp4".parse().unwrap()));
|
||||
}
|
||||
@ -1258,12 +1259,13 @@ mod tests {
|
||||
use stream::{self, Opener, Stream};
|
||||
use testutil::{self, TestDb, TEST_CAMERA_ID};
|
||||
|
||||
fn fill_slice(slice: &mut [u8], e: &http_entity::Entity<Body>, start: u64) {
|
||||
fn fill_slice<E: http_entity::Entity>(slice: &mut [u8], e: &E, start: u64) {
|
||||
let mut p = 0;
|
||||
e.get_range(start .. start + slice.len() as u64)
|
||||
.for_each(|chunk| {
|
||||
slice[p .. p + chunk.len()].copy_from_slice(&chunk);
|
||||
p += chunk.len();
|
||||
let c: &[u8] = chunk.as_ref();
|
||||
slice[p .. p + c.len()].copy_from_slice(c);
|
||||
p += c.len();
|
||||
Ok::<_, ::hyper::Error>(())
|
||||
})
|
||||
.wait()
|
||||
@ -1271,10 +1273,11 @@ mod tests {
|
||||
}
|
||||
|
||||
/// Returns the SHA-1 digest of the given `Entity`.
|
||||
fn digest(e: &http_entity::Entity<Body>) -> hash::DigestBytes {
|
||||
fn digest<E: http_entity::Entity>(e: &E) -> hash::DigestBytes {
|
||||
e.get_range(0 .. e.len())
|
||||
.fold(hash::Hasher::new(hash::MessageDigest::sha1()).unwrap(), |mut sha1, chunk| {
|
||||
sha1.update(&chunk).unwrap();
|
||||
let c: &[u8] = chunk.as_ref();
|
||||
sha1.update(c).unwrap();
|
||||
Ok::<_, ::hyper::Error>(sha1)
|
||||
})
|
||||
.wait()
|
||||
@ -1770,14 +1773,13 @@ mod bench {
|
||||
extern crate reqwest;
|
||||
extern crate test;
|
||||
|
||||
use futures::Stream;
|
||||
use futures::future;
|
||||
use futures::stream::BoxStream;
|
||||
use hyper;
|
||||
use http_entity;
|
||||
use recording;
|
||||
use reffers::ARefs;
|
||||
use self::test::Bencher;
|
||||
use std::str;
|
||||
use super::tests::create_mp4_from_db;
|
||||
use testutil::{self, TestDb};
|
||||
use url::Url;
|
||||
@ -1821,7 +1823,8 @@ mod bench {
|
||||
|
||||
impl hyper::server::Service for MyService {
|
||||
type Request = hyper::server::Request;
|
||||
type Response = hyper::server::Response<BoxStream<ARefs<'static, [u8]>, hyper::Error>>;
|
||||
type Response = hyper::server::Response<
|
||||
Box<Stream<Item = ARefs<'static, [u8]>, Error = hyper::Error> + Send>>;
|
||||
type Error = hyper::Error;
|
||||
type Future = future::FutureResult<Self::Response, Self::Error>;
|
||||
|
||||
@ -1873,6 +1876,7 @@ mod bench {
|
||||
use self::reqwest::header::{Range, ByteRangeSpec};
|
||||
let mut resp =
|
||||
client.get(server.url.clone())
|
||||
.unwrap()
|
||||
.header(Range::Bytes(vec![ByteRangeSpec::FromTo(0, p - 1)]))
|
||||
.send()
|
||||
.unwrap();
|
||||
|
@ -28,8 +28,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate uuid;
|
||||
|
||||
use coding::{append_varint32, decode_varint32, unzigzag32, zigzag32};
|
||||
use core::str::FromStr;
|
||||
use db;
|
||||
|
@ -31,13 +31,13 @@
|
||||
//! Tools for implementing a `http_entity::Entity` body composed from many "slices".
|
||||
|
||||
use reffers::ARefs;
|
||||
use futures::stream::{self, BoxStream};
|
||||
use futures::stream;
|
||||
use futures::Stream;
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
|
||||
pub type Chunk = ARefs<'static, [u8]>;
|
||||
pub type Body = stream::BoxStream<Chunk, ::hyper::Error>;
|
||||
pub type Body = Box<Stream<Item = Chunk, Error = ::hyper::Error> + Send>;
|
||||
|
||||
/// Writes a byte range to the given `io::Write` given a context argument; meant for use with
|
||||
/// `Slices`.
|
||||
@ -53,7 +53,7 @@ pub trait Slice : Sync + Sized + 'static {
|
||||
/// The additional argument `ctx` is as supplied to the `Slices`.
|
||||
/// The additional argument `l` is the length of this slice, as determined by the `Slices`.
|
||||
fn get_range(&self, ctx: &Self::Ctx, r: Range<u64>, len: u64)
|
||||
-> stream::BoxStream<Self::Chunk, ::hyper::Error>;
|
||||
-> Box<Stream<Item = Self::Chunk, Error = ::hyper::Error> + Send>;
|
||||
|
||||
fn get_slices(ctx: &Self::Ctx) -> &Slices<Self>;
|
||||
}
|
||||
@ -108,10 +108,10 @@ impl<S> Slices<S> where S: Slice {
|
||||
/// Writes `range` to `out`.
|
||||
/// This interface mirrors `http_entity::Entity::write_to`, with the additional `ctx` argument.
|
||||
pub fn get_range(&self, ctx: &S::Ctx, range: Range<u64>)
|
||||
-> BoxStream<S::Chunk, ::hyper::Error> {
|
||||
-> Box<Stream<Item = S::Chunk, Error = ::hyper::Error> + Send> {
|
||||
if range.start > range.end || range.end > self.len {
|
||||
error!("Bad range {:?} for slice of length {}", range, self.len);
|
||||
return stream::once(Err(::hyper::Error::Incomplete)).boxed();
|
||||
return Box::new(stream::once(Err(::hyper::Error::Incomplete)));
|
||||
}
|
||||
|
||||
// Binary search for the first slice of the range to write, determining its index and
|
||||
@ -139,14 +139,14 @@ impl<S> Slices<S> where S: Slice {
|
||||
};
|
||||
Some(Ok::<_, ::hyper::Error>((body, (c, i+1, 0, end))))
|
||||
});
|
||||
bodies.flatten().boxed()
|
||||
Box::new(bodies.flatten())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use futures::{Future, Stream};
|
||||
use futures::stream::{self, BoxStream};
|
||||
use futures::stream;
|
||||
use std::ops::Range;
|
||||
use super::{Slice, Slices};
|
||||
use testutil;
|
||||
@ -169,8 +169,8 @@ mod tests {
|
||||
fn end(&self) -> u64 { self.end }
|
||||
|
||||
fn get_range(&self, _ctx: &&'static Slices<FakeSlice>, r: Range<u64>, _l: u64)
|
||||
-> BoxStream<FakeChunk, ::hyper::Error> {
|
||||
stream::once(Ok(FakeChunk{slice: self.name, range: r})).boxed()
|
||||
-> Box<Stream<Item = FakeChunk, Error = ::hyper::Error> + Send> {
|
||||
Box::new(stream::once(Ok(FakeChunk{slice: self.name, range: r})))
|
||||
}
|
||||
|
||||
fn get_slices(ctx: &&'static Slices<FakeSlice>) -> &'static Slices<Self> { *ctx }
|
||||
|
38
src/web.rs
38
src/web.rs
@ -35,11 +35,10 @@ use core::str::FromStr;
|
||||
use db;
|
||||
use dir::SampleFileDir;
|
||||
use error::Error;
|
||||
use futures::Stream;
|
||||
use futures::{future, stream};
|
||||
use json;
|
||||
use http_entity;
|
||||
use hyper::{header, status};
|
||||
use hyper::header;
|
||||
use hyper::server::{self, Request, Response};
|
||||
use mime;
|
||||
use mp4;
|
||||
@ -224,10 +223,11 @@ impl Service {
|
||||
}
|
||||
|
||||
fn not_found(&self) -> Result<Response<slices::Body>, Error> {
|
||||
let body: slices::Body = Box::new(stream::once(Ok(ARefs::new(&b"not found"[..]))));
|
||||
Ok(Response::new()
|
||||
.with_status(status::StatusCode::NotFound)
|
||||
.with_status(hyper::StatusCode::NotFound)
|
||||
.with_header(header::ContentType(mime::TEXT_PLAIN))
|
||||
.with_body(stream::once(Ok(ARefs::new(&b"not found"[..]))).boxed()))
|
||||
.with_body(body))
|
||||
}
|
||||
|
||||
fn list_cameras(&self, req: &Request) -> Result<Response<slices::Body>, Error> {
|
||||
@ -240,11 +240,13 @@ impl Service {
|
||||
self.list_cameras_html(db)?
|
||||
}
|
||||
};
|
||||
let len = buf.len();
|
||||
let body: slices::Body = Box::new(stream::once(Ok(ARefs::new(buf))));
|
||||
Ok(Response::new()
|
||||
.with_header(header::ContentType(if json { mime::APPLICATION_JSON }
|
||||
else { mime::TEXT_HTML }))
|
||||
.with_header(header::ContentLength(buf.len() as u64))
|
||||
.with_body(stream::once(Ok(ARefs::new(buf))).boxed()))
|
||||
.with_header(header::ContentLength(len as u64))
|
||||
.with_body(body))
|
||||
}
|
||||
|
||||
fn list_cameras_html(&self, db: MutexGuard<db::LockedDatabase>) -> Result<Vec<u8>, Error> {
|
||||
@ -294,11 +296,13 @@ impl Service {
|
||||
self.camera_html(db, query, uuid)?
|
||||
}
|
||||
};
|
||||
let len = buf.len();
|
||||
let body: slices::Body = Box::new(stream::once(Ok(ARefs::new(buf))));
|
||||
Ok(Response::new()
|
||||
.with_header(header::ContentType(if json { mime::APPLICATION_JSON }
|
||||
else { mime::TEXT_HTML }))
|
||||
.with_header(header::ContentLength(buf.len() as u64))
|
||||
.with_body(stream::once(Ok(ARefs::new(buf))).boxed()))
|
||||
.with_header(header::ContentLength(len as u64))
|
||||
.with_body(body))
|
||||
}
|
||||
|
||||
fn camera_html(&self, db: MutexGuard<db::LockedDatabase>, query: Option<&str>,
|
||||
@ -398,10 +402,11 @@ impl Service {
|
||||
-> Result<Response<slices::Body>, Error> {
|
||||
let r = Service::get_optional_range(query)?;
|
||||
if !is_json(req) {
|
||||
let body: slices::Body = Box::new(stream::once(
|
||||
Ok(ARefs::new(&b"only available for JSON requests"[..]))));
|
||||
return Ok(Response::new()
|
||||
.with_status(status::StatusCode::NotAcceptable)
|
||||
.with_body(stream::once(
|
||||
Ok(ARefs::new(&b"only available for JSON requests"[..]))).boxed()));
|
||||
.with_status(hyper::StatusCode::NotAcceptable)
|
||||
.with_body(body));
|
||||
}
|
||||
let mut out = json::ListRecordings{recordings: Vec::new()};
|
||||
{
|
||||
@ -423,10 +428,12 @@ impl Service {
|
||||
})?;
|
||||
}
|
||||
let buf = serde_json::to_vec(&out)?;
|
||||
let len = buf.len();
|
||||
let body: slices::Body = Box::new(stream::once(Ok(ARefs::new(buf))));
|
||||
Ok(Response::new()
|
||||
.with_header(header::ContentType(mime::APPLICATION_JSON))
|
||||
.with_header(header::ContentLength(buf.len() as u64))
|
||||
.with_body(stream::once(Ok(ARefs::new(buf))).boxed()))
|
||||
.with_header(header::ContentLength(len as u64))
|
||||
.with_body(body))
|
||||
}
|
||||
|
||||
fn camera_view_mp4(&self, uuid: Uuid, query: Option<&str>, req: &Request)
|
||||
@ -614,7 +621,6 @@ mod bench {
|
||||
|
||||
use hyper;
|
||||
use self::test::Bencher;
|
||||
use std::str;
|
||||
use testutil::{self, TestDb};
|
||||
|
||||
struct Server {
|
||||
@ -653,8 +659,8 @@ mod bench {
|
||||
let mut buf = Vec::new();
|
||||
let client = reqwest::Client::new().unwrap();
|
||||
let mut f = || {
|
||||
let mut resp = client.get(url.clone()).send().unwrap();
|
||||
assert_eq!(*resp.status(), reqwest::StatusCode::Ok);
|
||||
let mut resp = client.get(url.clone()).unwrap().send().unwrap();
|
||||
assert_eq!(resp.status(), reqwest::StatusCode::Ok);
|
||||
buf.clear();
|
||||
use std::io::Read;
|
||||
resp.read_to_end(&mut buf).unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user