+++ /dev/null
-use bytes::BytesMut;
-use nom;
-use std;
-use std::io;
-use tokio_io::codec::{Decoder, Encoder};
-
-use parser::header;
-use parser::top_line;
-use types::{Header, Method, RequestLine, StatusLine, TopLine};
-
-const SPACE: u8 = b' ';
-const TAB: u8 = b'\t';
-const LF: u8 = b'\n';
-const CR: u8 = b'\r';
-
-impl Header {
- fn parse(line: UnparsedLine) -> Option<(Header, UnparsedLine)> {
- match header(line.as_bytes()) {
- nom::IResult::Done(_, h) => Some((h, line.clone())),
- result => {
- warn!("Failed to parse header: {:?} - {:?}", line, result);
- None
- }
- }
- }
-}
-
-#[derive(Clone, Debug)]
-struct UnparsedLine {
- value: BytesMut,
-}
-
-impl UnparsedLine {
- fn new(value: BytesMut) -> UnparsedLine {
- UnparsedLine { value: value }
- }
-
- fn add(&mut self, value: &BytesMut) {
- self.value.extend_from_slice(value);
- }
-
- fn as_bytes(&self) -> &[u8] {
- &self.value
- }
-}
-
-pub struct SipCodec {
- message: Option<PartialMessage>,
- headers: Vec<UnparsedLine>,
- top_line: Option<UnparsedLine>,
- latest_header: Option<UnparsedLine>,
-}
-
-impl SipCodec {
- pub fn new() -> SipCodec {
- SipCodec {
- message: None,
- headers: Vec::new(),
- top_line: None,
- latest_header: None,
- }
- }
-
- fn parse_message(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
- loop {
- trace!("Gathering headers from {:?}", std::str::from_utf8(&buf));
-
- let mut done = false;
- let mut total = 0;
-
- {
- let mut search: Box<Iterator<Item = &u8>> = Box::new(buf.iter());
-
- while !done {
- trace!("Gathering CRLF");
-
- if let Some(cr) = search.position(|&b| b == CR) {
- trace!("Found CR at {}", cr);
-
- total += cr;
-
- let next = search.next();
-
- trace!("Got {:?} after CR", next);
-
- if let Some(&LF) = next {
- done = true;
- }
- } else {
- return Ok(None);
- }
- }
- }
-
- // We've got a line terminating in \r\n.
- let line = buf.split_to(total + 2);
-
- trace!("Using line: {:?}", std::str::from_utf8(&line));
-
- match (
- &mut self.top_line,
- chartype(line.first()),
- &mut self.latest_header,
- ) {
- // Ignore empty top lines
- (&mut None, CharType::Line, _) => {
- trace!("Ignoring empty top line");
- }
-
- // Top line beginnning with whitespace - ignore
- (&mut None, CharType::Whitespace, _) => {
- trace!(
- "Got top line beginning with whitespace - ignore: {:?}",
- line
- );
- }
-
- // Top line with no headers! Discard.
- (top_line @ &mut None, CharType::Other, _) => {
- trace!("Got new top line of request: {:?}", line);
-
- top_line.get_or_insert(UnparsedLine::new(line));
- }
-
- // Top line with no headers! Discard.
- (top_line @ &mut Some(_), CharType::Line, &mut None) => {
- warn!("Got request with no headers - discarding");
- top_line.take();
- }
-
- // Whitespace wrapped req line
- (&mut Some(ref mut top_line), CharType::Whitespace, &mut None) => {
- top_line.add(&line)
- }
-
- // Whitespace wrapped header
- (&mut Some(_), CharType::Whitespace, &mut Some(ref mut latest_header)) => {
- latest_header.add(&line)
- }
-
- // First header
- (&mut Some(_), CharType::Other, latest_header @ &mut None) => {
- latest_header.get_or_insert(UnparsedLine::new(line));
- }
-
- // New header
- (&mut Some(_), CharType::Other, latest_header @ &mut Some(_)) => {
- self.headers.push(latest_header.take().unwrap());
- latest_header.get_or_insert(UnparsedLine::new(line));
- }
-
- // End of headers
- (top_line @ &mut Some(_), CharType::Line, old_header @ &mut Some(_)) => {
- self.headers.push(old_header.take().unwrap());
-
- trace!("Got end of headers");
-
- if let Ok(new_message) =
- PartialMessage::new(top_line.take().unwrap(), &mut self.headers)
- {
- debug!("Got partial message: {:?}", new_message);
-
- self.headers.clear();
-
- let length = new_message.body_length();
-
- if length == 0 {
- if let Some(message) = Message::new(new_message) {
- debug!("Got message without body: {:?}", message);
-
- return Ok(Some(message));
- } else {
- debug!("Failed to parse message with no body!");
- }
- } else if length > buf.len() {
- self.message.get_or_insert(new_message);
- return Ok(None);
- } else {
- let body = buf.split_to(length);
- if let Some(message) = Message::new_with_body(new_message, body) {
- debug!("Got message with body: {:?}", message);
-
- return Ok(Some(message));
- } else {
- warn!("Failed to parse message with body!");
- }
- }
- } else {
- warn!("Failed to parse partial message!");
-
- // Message failed to parse
- top_line.take();
- self.headers.clear();
- }
- }
- }
- }
- }
-}
-
-#[derive(Debug)]
-struct PartialMessage {
- headers: Vec<(Header, UnparsedLine)>,
- top_line: UnparsedLine,
-}
-
-impl PartialMessage {
- fn new(
- top_line: UnparsedLine,
- headers: &mut Vec<UnparsedLine>,
- ) -> Result<PartialMessage, std::str::Utf8Error> {
- Ok(PartialMessage {
- top_line: top_line,
- headers: headers
- .drain(..)
- .filter_map(|line| Header::parse(line))
- .collect(),
- })
- }
-
- fn body_length(&self) -> usize {
- let body_length = 0;
-
- body_length
- }
-}
-
-#[derive(Debug)]
-pub enum Message {
- Request(Request),
- Response(Response),
-}
-
-#[derive(Debug)]
-pub struct Response {
- status_line: (StatusLine, UnparsedLine),
- headers: Vec<(Header, UnparsedLine)>,
- body: Option<BytesMut>,
-}
-
-impl Response {
- fn as_bytes(&self) -> &[u8] {
- return self.status_line.1.as_bytes();
- }
-}
-
-#[derive(Debug)]
-pub struct Request {
- request_line: (RequestLine, UnparsedLine),
- headers: Vec<(Header, UnparsedLine)>,
- body: Option<BytesMut>,
-}
-
-impl Request {
- fn as_bytes(&self) -> &[u8] {
- return self.request_line.1.as_bytes();
- }
-
- pub fn method(&self) -> &Method {
- &self.request_line.0.method
- }
-}
-
-impl Message {
- fn new(message: PartialMessage) -> Option<Message> {
- Message::parse(message, None)
- }
-
- fn parse(message: PartialMessage, body: Option<BytesMut>) -> Option<Message> {
- match top_line(message.top_line.as_bytes()) {
- nom::IResult::Done(_, TopLine::RequestLine(r)) => Some(Message::Request(Request {
- headers: message.headers,
- request_line: (r, message.top_line.clone()),
- body: body,
- })),
- nom::IResult::Done(_, TopLine::StatusLine(s)) => Some(Message::Response(Response {
- headers: message.headers,
- status_line: (s, message.top_line.clone()),
- body: body,
- })),
- result => {
- warn!("Failed to parse top line: {:?}", result);
- None
- }
- }
- }
-
- fn new_with_body(message: PartialMessage, body: BytesMut) -> Option<Message> {
- Message::parse(message, Some(body))
- }
-
- fn as_bytes<'a>(&'a self) -> &'a [u8] {
- match self {
- &Message::Request(ref r) => r.as_bytes(),
- &Message::Response(ref r) => r.as_bytes(),
- }
- }
-}
-
-impl Decoder for SipCodec {
- type Item = Message;
- type Error = io::Error;
-
- fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
- if let Some(_) = self.message {
- trace!("Gathering body");
-
- let length = self.message.iter().map(|m| m.body_length()).next().unwrap();
-
- if length > buf.len() {
- return Ok(None);
- } else if let Some(message) =
- Message::new_with_body(self.message.take().unwrap(), buf.split_to(length))
- {
- return Ok(Some(message));
- } else {
- warn!("Failed to parse message with no body!");
- }
- }
-
- self.parse_message(buf)
- }
-}
-
-impl Encoder for SipCodec {
- type Item = Message;
- type Error = io::Error;
-
- fn encode(&mut self, msg: Message, buf: &mut BytesMut) -> io::Result<()> {
- buf.extend(msg.as_bytes());
- Ok(())
- }
-}
-
-#[derive(PartialEq, Debug)]
-enum CharType {
- Line,
- Whitespace,
- Other,
-}
-
-fn chartype(char: Option<&u8>) -> CharType {
- match char {
- None | Some(&LF) | Some(&CR) => CharType::Line,
- Some(&SPACE) | Some(&TAB) => CharType::Whitespace,
- Some(_) => CharType::Other,
- }
-}
-
-#[cfg(test)]
-mod tests {
-
- use super::*;
-
- #[test]
- fn test_chartype_none() {
- assert_eq!(chartype(None), CharType::Line);
- }
-
- #[test]
- fn test_chartype_cr() {
- assert_eq!(chartype(Some(&LF)), CharType::Line);
- }
-
- #[test]
- fn test_chartype_lf() {
- assert_eq!(chartype(Some(&CR)), CharType::Line);
- }
-
- #[test]
- fn test_chartype_space() {
- assert_eq!(chartype(Some(&SPACE)), CharType::Whitespace);
- }
-
- #[test]
- fn test_chartype_tab() {
- assert_eq!(chartype(Some(&TAB)), CharType::Whitespace);
- }
-
- #[test]
- fn test_chartype_alpha() {
- const A: u8 = b'a';
- assert_eq!(chartype(Some(&A)), CharType::Other);
- }
-
- #[test]
- fn test_chartype_number() {
- const ONE: u8 = b'1';
- assert_eq!(chartype(Some(&ONE)), CharType::Other);
- }
-}
--- /dev/null
+const SPACE: u8 = b' ';
+const TAB: u8 = b'\t';
+pub const LF: u8 = b'\n';
+pub const CR: u8 = b'\r';
+
+#[derive(PartialEq, Debug)]
+pub enum CharType {
+ Line,
+ Whitespace,
+ Other,
+}
+
+pub fn chartype(char: Option<&u8>) -> CharType {
+ match char {
+ None | Some(&LF) | Some(&CR) => CharType::Line,
+ Some(&SPACE) | Some(&TAB) => CharType::Whitespace,
+ Some(_) => CharType::Other,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_chartype_none() {
+ assert_eq!(chartype(None), CharType::Line);
+ }
+
+ #[test]
+ fn test_chartype_cr() {
+ assert_eq!(chartype(Some(&LF)), CharType::Line);
+ }
+
+ #[test]
+ fn test_chartype_lf() {
+ assert_eq!(chartype(Some(&CR)), CharType::Line);
+ }
+
+ #[test]
+ fn test_chartype_space() {
+ assert_eq!(chartype(Some(&SPACE)), CharType::Whitespace);
+ }
+
+ #[test]
+ fn test_chartype_tab() {
+ assert_eq!(chartype(Some(&TAB)), CharType::Whitespace);
+ }
+
+ #[test]
+ fn test_chartype_alpha() {
+ const A: u8 = b'a';
+ assert_eq!(chartype(Some(&A)), CharType::Other);
+ }
+
+ #[test]
+ fn test_chartype_number() {
+ const ONE: u8 = b'1';
+ assert_eq!(chartype(Some(&ONE)), CharType::Other);
+ }
+}
--- /dev/null
+use bytes::BytesMut;
+use nom;
+use std;
+use std::io;
+use tokio_io::codec::{Decoder, Encoder};
+
+mod chartype;
+
+use self::chartype::{chartype, CharType, CR, LF};
+use parser::header;
+use parser::top_line;
+use types::{Header, Method, RequestLine, StatusLine, TopLine};
+
+impl Header {
+ fn parse(line: UnparsedLine) -> Option<(Header, UnparsedLine)> {
+ match header(line.as_bytes()) {
+ nom::IResult::Done(_, h) => Some((h, line.clone())),
+ result => {
+ warn!("Failed to parse header: {:?} - {:?}", line, result);
+ None
+ }
+ }
+ }
+}
+
+#[derive(Clone, Debug)]
+struct UnparsedLine {
+ value: BytesMut,
+}
+
+impl UnparsedLine {
+ fn new(value: BytesMut) -> UnparsedLine {
+ UnparsedLine { value: value }
+ }
+
+ fn add(&mut self, value: &BytesMut) {
+ self.value.extend_from_slice(value);
+ }
+
+ fn as_bytes(&self) -> &[u8] {
+ &self.value
+ }
+}
+
+pub struct SipCodec {
+ message: Option<PartialMessage>,
+ headers: Vec<UnparsedLine>,
+ top_line: Option<UnparsedLine>,
+ latest_header: Option<UnparsedLine>,
+}
+
+impl SipCodec {
+ pub fn new() -> SipCodec {
+ SipCodec {
+ message: None,
+ headers: Vec::new(),
+ top_line: None,
+ latest_header: None,
+ }
+ }
+
+ fn parse_message(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
+ loop {
+ trace!("Gathering headers from {:?}", std::str::from_utf8(&buf));
+
+ let mut done = false;
+ let mut total = 0;
+
+ {
+ let mut search: Box<Iterator<Item = &u8>> = Box::new(buf.iter());
+
+ while !done {
+ trace!("Gathering CRLF");
+
+ if let Some(cr) = search.position(|&b| b == CR) {
+ trace!("Found CR at {}", cr);
+
+ total += cr;
+
+ let next = search.next();
+
+ trace!("Got {:?} after CR", next);
+
+ if let Some(&LF) = next {
+ done = true;
+ }
+ } else {
+ return Ok(None);
+ }
+ }
+ }
+
+ // We've got a line terminating in \r\n.
+ let line = buf.split_to(total + 2);
+
+ trace!("Using line: {:?}", std::str::from_utf8(&line));
+
+ match (
+ &mut self.top_line,
+ chartype(line.first()),
+ &mut self.latest_header,
+ ) {
+ // Ignore empty top lines
+ (&mut None, CharType::Line, _) => {
+ trace!("Ignoring empty top line");
+ }
+
+ // Top line beginnning with whitespace - ignore
+ (&mut None, CharType::Whitespace, _) => {
+ trace!(
+ "Got top line beginning with whitespace - ignore: {:?}",
+ line
+ );
+ }
+
+ // Top line with no headers! Discard.
+ (top_line @ &mut None, CharType::Other, _) => {
+ trace!("Got new top line of request: {:?}", line);
+
+ top_line.get_or_insert(UnparsedLine::new(line));
+ }
+
+ // Top line with no headers! Discard.
+ (top_line @ &mut Some(_), CharType::Line, &mut None) => {
+ warn!("Got request with no headers - discarding");
+ top_line.take();
+ }
+
+ // Whitespace wrapped req line
+ (&mut Some(ref mut top_line), CharType::Whitespace, &mut None) => {
+ top_line.add(&line)
+ }
+
+ // Whitespace wrapped header
+ (&mut Some(_), CharType::Whitespace, &mut Some(ref mut latest_header)) => {
+ latest_header.add(&line)
+ }
+
+ // First header
+ (&mut Some(_), CharType::Other, latest_header @ &mut None) => {
+ latest_header.get_or_insert(UnparsedLine::new(line));
+ }
+
+ // New header
+ (&mut Some(_), CharType::Other, latest_header @ &mut Some(_)) => {
+ self.headers.push(latest_header.take().unwrap());
+ latest_header.get_or_insert(UnparsedLine::new(line));
+ }
+
+ // End of headers
+ (top_line @ &mut Some(_), CharType::Line, old_header @ &mut Some(_)) => {
+ self.headers.push(old_header.take().unwrap());
+
+ trace!("Got end of headers");
+
+ if let Ok(new_message) =
+ PartialMessage::new(top_line.take().unwrap(), &mut self.headers)
+ {
+ debug!("Got partial message: {:?}", new_message);
+
+ self.headers.clear();
+
+ let length = new_message.body_length();
+
+ if length == 0 {
+ if let Some(message) = Message::new(new_message) {
+ debug!("Got message without body: {:?}", message);
+
+ return Ok(Some(message));
+ } else {
+ debug!("Failed to parse message with no body!");
+ }
+ } else if length > buf.len() {
+ self.message.get_or_insert(new_message);
+ return Ok(None);
+ } else {
+ let body = buf.split_to(length);
+ if let Some(message) = Message::new_with_body(new_message, body) {
+ debug!("Got message with body: {:?}", message);
+
+ return Ok(Some(message));
+ } else {
+ warn!("Failed to parse message with body!");
+ }
+ }
+ } else {
+ warn!("Failed to parse partial message!");
+
+ // Message failed to parse
+ top_line.take();
+ self.headers.clear();
+ }
+ }
+ }
+ }
+ }
+}
+
+#[derive(Debug)]
+struct PartialMessage {
+ headers: Vec<(Header, UnparsedLine)>,
+ top_line: UnparsedLine,
+}
+
+impl PartialMessage {
+ fn new(
+ top_line: UnparsedLine,
+ headers: &mut Vec<UnparsedLine>,
+ ) -> Result<PartialMessage, std::str::Utf8Error> {
+ Ok(PartialMessage {
+ top_line: top_line,
+ headers: headers
+ .drain(..)
+ .filter_map(|line| Header::parse(line))
+ .collect(),
+ })
+ }
+
+ fn body_length(&self) -> usize {
+ let body_length = 0;
+
+ body_length
+ }
+}
+
+#[derive(Debug)]
+pub enum Message {
+ Request(Request),
+ Response(Response),
+}
+
+#[derive(Debug)]
+pub struct Response {
+ status_line: (StatusLine, UnparsedLine),
+ headers: Vec<(Header, UnparsedLine)>,
+ body: Option<BytesMut>,
+}
+
+impl Response {
+ fn as_bytes(&self) -> &[u8] {
+ return self.status_line.1.as_bytes();
+ }
+}
+
+#[derive(Debug)]
+pub struct Request {
+ request_line: (RequestLine, UnparsedLine),
+ headers: Vec<(Header, UnparsedLine)>,
+ body: Option<BytesMut>,
+}
+
+impl Request {
+ fn as_bytes(&self) -> &[u8] {
+ return self.request_line.1.as_bytes();
+ }
+
+ pub fn method(&self) -> &Method {
+ &self.request_line.0.method
+ }
+}
+
+impl Message {
+ fn new(message: PartialMessage) -> Option<Message> {
+ Message::parse(message, None)
+ }
+
+ fn parse(message: PartialMessage, body: Option<BytesMut>) -> Option<Message> {
+ match top_line(message.top_line.as_bytes()) {
+ nom::IResult::Done(_, TopLine::RequestLine(r)) => Some(Message::Request(Request {
+ headers: message.headers,
+ request_line: (r, message.top_line.clone()),
+ body: body,
+ })),
+ nom::IResult::Done(_, TopLine::StatusLine(s)) => Some(Message::Response(Response {
+ headers: message.headers,
+ status_line: (s, message.top_line.clone()),
+ body: body,
+ })),
+ result => {
+ warn!("Failed to parse top line: {:?}", result);
+ None
+ }
+ }
+ }
+
+ fn new_with_body(message: PartialMessage, body: BytesMut) -> Option<Message> {
+ Message::parse(message, Some(body))
+ }
+
+ fn as_bytes<'a>(&'a self) -> &'a [u8] {
+ match self {
+ &Message::Request(ref r) => r.as_bytes(),
+ &Message::Response(ref r) => r.as_bytes(),
+ }
+ }
+}
+
+impl Decoder for SipCodec {
+ type Item = Message;
+ type Error = io::Error;
+
+ fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<Message>> {
+ if let Some(_) = self.message {
+ trace!("Gathering body");
+
+ let length = self.message.iter().map(|m| m.body_length()).next().unwrap();
+
+ if length > buf.len() {
+ return Ok(None);
+ } else if let Some(message) =
+ Message::new_with_body(self.message.take().unwrap(), buf.split_to(length))
+ {
+ return Ok(Some(message));
+ } else {
+ warn!("Failed to parse message with no body!");
+ }
+ }
+
+ self.parse_message(buf)
+ }
+}
+
+impl Encoder for SipCodec {
+ type Item = Message;
+ type Error = io::Error;
+
+ fn encode(&mut self, msg: Message, buf: &mut BytesMut) -> io::Result<()> {
+ buf.extend(msg.as_bytes());
+ Ok(())
+ }
+}