diff --git a/src/http/conn.rs b/src/http/conn.rs index 0324e12691..c50cad818d 100644 --- a/src/http/conn.rs +++ b/src/http/conn.rs @@ -669,206 +669,195 @@ impl, T: Transport> fmt::Debug for State { } impl, T: Transport> State { - fn update(&mut self, next: Next, factory: &F) where F: MessageHandlerFactory, K: Key { - let timeout = next.timeout; - let state = mem::replace(self, State::Closed); - let new_state = match (state, next.interest) { - (_, Next_::Remove) => State::Closed, - (State::Closed, _) => State::Closed, - (State::Init { timeout, .. }, e) => State::Init { - interest: e, - timeout: timeout, - }, - (State::Http1(http1), Next_::End) => { - let reading = match http1.reading { - Reading::Body(ref decoder) | - Reading::Wait(ref decoder) if decoder.is_eof() => { - if http1.keep_alive { - Reading::KeepAlive - } else { - Reading::Closed - } - }, - Reading::KeepAlive => http1.reading, - _ => Reading::Closed, - }; - let writing = match http1.writing { - Writing::Wait(encoder) | - Writing::Ready(encoder) => { - if encoder.is_eof() { - if http1.keep_alive { - Writing::KeepAlive - } else { - Writing::Closed + fn update(&mut self, next: Next, factory: &F) + where F: MessageHandlerFactory, + K: Key + { + let timeout = next.timeout; + let state = mem::replace(self, State::Closed); + match (state, next.interest) { + (_, Next_::Remove) | + (State::Closed, _) => return, // Keep State::Closed. + (State::Init { .. }, e) => { + mem::replace(self, + State::Init { + interest: e, + timeout: timeout, + }); + } + (State::Http1(mut http1), next_) => { + match next_ { + Next_::Remove => unreachable!(), // Covered in (_, Next_::Remove) case above. + Next_::End => { + let reading = match http1.reading { + Reading::Body(ref decoder) | + Reading::Wait(ref decoder) if decoder.is_eof() => { + if http1.keep_alive { + Reading::KeepAlive + } else { + Reading::Closed + } + } + Reading::KeepAlive => http1.reading, + _ => Reading::Closed, + }; + let mut writing = Writing::Closed; + let encoder = match http1.writing { + Writing::Wait(enc) | + Writing::Ready(enc) => Some(enc), + Writing::Chunk(mut chunk) => { + if chunk.is_written() { + Some(chunk.next.0) + } else { + chunk.next.1 = next; + writing = Writing::Chunk(chunk); + None + } + } + _ => return, // Keep State::Closed. + }; + if let Some(encoder) = encoder { + if encoder.is_eof() { + if http1.keep_alive { + writing = Writing::KeepAlive + } + } else if let Some(buf) = encoder.finish() { + writing = Writing::Chunk(Chunk { + buf: buf.bytes, + pos: buf.pos, + next: (h1::Encoder::length(0), Next::end()), + }) + } + }; + + match (reading, writing) { + (Reading::KeepAlive, Writing::KeepAlive) => { + let next = factory.keep_alive_interest(); + mem::replace(self, + State::Init { + interest: next.interest, + timeout: next.timeout, + }); + return; + } + (reading, Writing::Chunk(chunk)) => { + http1.reading = reading; + http1.writing = Writing::Chunk(chunk); + } + _ => return, // Keep State::Closed. } - } else if let Some(buf) = encoder.finish() { - Writing::Chunk(Chunk { - buf: buf.bytes, - pos: buf.pos, - next: (h1::Encoder::length(0), Next::end()) - }) - } else { - Writing::Closed } - } - Writing::Chunk(mut chunk) => { - if chunk.is_written() { - let encoder = chunk.next.0; - //TODO: de-dupe this code and from Writing::Ready - if encoder.is_eof() { - if http1.keep_alive { - Writing::KeepAlive - } else { - Writing::Closed + Next_::Read => { + http1.reading = match http1.reading { + Reading::Init => Reading::Parse, + Reading::Wait(decoder) => Reading::Body(decoder), + same => same, + }; + + http1.writing = match http1.writing { + Writing::Ready(encoder) => { + if encoder.is_eof() { + if http1.keep_alive { + Writing::KeepAlive + } else { + Writing::Closed + } + } else if encoder.is_closed() { + if let Some(buf) = encoder.finish() { + Writing::Chunk(Chunk { + buf: buf.bytes, + pos: buf.pos, + next: (h1::Encoder::length(0), Next::wait()), + }) + } else { + Writing::Closed + } + } else { + Writing::Wait(encoder) + } } - } else if let Some(buf) = encoder.finish() { - Writing::Chunk(Chunk { - buf: buf.bytes, - pos: buf.pos, - next: (h1::Encoder::length(0), Next::end()) - }) - } else { - Writing::Closed - } - } else { - chunk.next.1 = next; - Writing::Chunk(chunk) + Writing::Chunk(chunk) => { + if chunk.is_written() { + Writing::Wait(chunk.next.0) + } else { + Writing::Chunk(chunk) + } + } + same => same, + }; } - }, - _ => Writing::Closed, - }; - match (reading, writing) { - (Reading::KeepAlive, Writing::KeepAlive) => { - let next = factory.keep_alive_interest(); - State::Init { - interest: next.interest, - timeout: next.timeout, + Next_::Write => { + http1.writing = match http1.writing { + Writing::Wait(encoder) => Writing::Ready(encoder), + Writing::Init => Writing::Head, + Writing::Chunk(chunk) => { + if chunk.is_written() { + Writing::Ready(chunk.next.0) + } else { + Writing::Chunk(chunk) + } + } + same => same, + }; + + http1.reading = match http1.reading { + Reading::Body(decoder) => { + if decoder.is_eof() { + if http1.keep_alive { + Reading::KeepAlive + } else { + Reading::Closed + } + } else { + Reading::Wait(decoder) + } + } + same => same, + }; } - }, - (reading, Writing::Chunk(chunk)) => { - State::Http1(Http1 { - reading: reading, - writing: Writing::Chunk(chunk), - .. http1 - }) - } - _ => State::Closed - } - }, - (State::Http1(mut http1), Next_::Read) => { - http1.reading = match http1.reading { - Reading::Init => Reading::Parse, - Reading::Wait(decoder) => Reading::Body(decoder), - same => same - }; - - http1.writing = match http1.writing { - Writing::Ready(encoder) => { - if encoder.is_eof() { - if http1.keep_alive { - Writing::KeepAlive - } else { - Writing::Closed - } - } else if encoder.is_closed() { - if let Some(buf) = encoder.finish() { - Writing::Chunk(Chunk { - buf: buf.bytes, - pos: buf.pos, - next: (h1::Encoder::length(0), Next::wait()) - }) - } else { - Writing::Closed - } - } else { - Writing::Wait(encoder) + Next_::ReadWrite => { + http1.reading = match http1.reading { + Reading::Init => Reading::Parse, + Reading::Wait(decoder) => Reading::Body(decoder), + same => same, + }; + http1.writing = match http1.writing { + Writing::Wait(encoder) => Writing::Ready(encoder), + Writing::Init => Writing::Head, + Writing::Chunk(chunk) => { + if chunk.is_written() { + Writing::Ready(chunk.next.0) + } else { + Writing::Chunk(chunk) + } + } + same => same, + }; } - }, - Writing::Chunk(chunk) => if chunk.is_written() { - Writing::Wait(chunk.next.0) - } else { - Writing::Chunk(chunk) - }, - same => same - }; - - State::Http1(http1) - }, - (State::Http1(mut http1), Next_::Write) => { - http1.writing = match http1.writing { - Writing::Wait(encoder) => Writing::Ready(encoder), - Writing::Init => Writing::Head, - Writing::Chunk(chunk) => if chunk.is_written() { - Writing::Ready(chunk.next.0) - } else { - Writing::Chunk(chunk) - }, - same => same - }; - - http1.reading = match http1.reading { - Reading::Body(decoder) => if decoder.is_eof() { - if http1.keep_alive { - Reading::KeepAlive - } else { - Reading::Closed + Next_::Wait => { + http1.reading = match http1.reading { + Reading::Body(decoder) => Reading::Wait(decoder), + same => same, + }; + + http1.writing = match http1.writing { + Writing::Ready(encoder) => Writing::Wait(encoder), + Writing::Chunk(chunk) => { + if chunk.is_written() { + Writing::Wait(chunk.next.0) + } else { + Writing::Chunk(chunk) + } + } + same => same, + }; } - } else { - Reading::Wait(decoder) - }, - same => same - }; - State::Http1(http1) - }, - (State::Http1(mut http1), Next_::ReadWrite) => { - http1.reading = match http1.reading { - Reading::Init => Reading::Parse, - Reading::Wait(decoder) => Reading::Body(decoder), - same => same - }; - http1.writing = match http1.writing { - Writing::Wait(encoder) => Writing::Ready(encoder), - Writing::Init => Writing::Head, - Writing::Chunk(chunk) => if chunk.is_written() { - Writing::Ready(chunk.next.0) - } else { - Writing::Chunk(chunk) - }, - same => same - }; - State::Http1(http1) - }, - (State::Http1(mut http1), Next_::Wait) => { - http1.reading = match http1.reading { - Reading::Body(decoder) => Reading::Wait(decoder), - same => same - }; - - http1.writing = match http1.writing { - Writing::Ready(encoder) => Writing::Wait(encoder), - Writing::Chunk(chunk) => if chunk.is_written() { - Writing::Wait(chunk.next.0) - } else { - Writing::Chunk(chunk) - }, - same => same - }; - State::Http1(http1) - } - }; - let new_state = match new_state { - State::Init { interest, .. } => State::Init { - timeout: timeout, - interest: interest, - }, - State::Http1(mut http1) => { - http1.timeout = timeout; - State::Http1(http1) - } - other => other - }; - mem::replace(self, new_state); - } + } + http1.timeout = timeout; + mem::replace(self, State::Http1(http1)); + } + }; + } } // These Reading and Writing stuff should probably get moved into h1/message.rs