codec.rs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
  2. use shannon::Shannon;
  3. use std::io;
  4. use tokio_core::io::{Codec, EasyBuf};
  5. const HEADER_SIZE: usize = 3;
  6. const MAC_SIZE: usize = 4;
  7. #[derive(Debug)]
  8. enum DecodeState {
  9. Header,
  10. Payload(u8, usize),
  11. }
  12. pub struct APCodec {
  13. encode_nonce: u32,
  14. encode_cipher: Shannon,
  15. decode_nonce: u32,
  16. decode_cipher: Shannon,
  17. decode_state: DecodeState,
  18. }
  19. impl APCodec {
  20. pub fn new(send_key: &[u8], recv_key: &[u8]) -> APCodec {
  21. APCodec {
  22. encode_nonce: 0,
  23. encode_cipher: Shannon::new(send_key),
  24. decode_nonce: 0,
  25. decode_cipher: Shannon::new(recv_key),
  26. decode_state: DecodeState::Header,
  27. }
  28. }
  29. }
  30. impl Codec for APCodec {
  31. type Out = (u8, Vec<u8>);
  32. type In = (u8, EasyBuf);
  33. fn encode(&mut self, item: (u8, Vec<u8>), buf: &mut Vec<u8>) -> io::Result<()> {
  34. let (cmd, payload) = item;
  35. let offset = buf.len();
  36. buf.write_u8(cmd).unwrap();
  37. buf.write_u16::<BigEndian>(payload.len() as u16).unwrap();
  38. buf.extend_from_slice(&payload);
  39. self.encode_cipher.nonce_u32(self.encode_nonce);
  40. self.encode_nonce += 1;
  41. self.encode_cipher.encrypt(&mut buf[offset..]);
  42. let mac = self.encode_cipher.finish(MAC_SIZE as u32);
  43. buf.extend_from_slice(&mac);
  44. Ok(())
  45. }
  46. fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<(u8, EasyBuf)>> {
  47. if let DecodeState::Header = self.decode_state {
  48. if buf.len() >= HEADER_SIZE {
  49. let mut header = [0u8; HEADER_SIZE];
  50. header.copy_from_slice(buf.drain_to(HEADER_SIZE).as_slice());
  51. self.decode_cipher.nonce_u32(self.decode_nonce);
  52. self.decode_nonce += 1;
  53. self.decode_cipher.decrypt(&mut header);
  54. let cmd = header[0];
  55. let size = BigEndian::read_u16(&header[1..]) as usize;
  56. self.decode_state = DecodeState::Payload(cmd, size);
  57. }
  58. }
  59. if let DecodeState::Payload(cmd, size) = self.decode_state {
  60. if buf.len() >= size + MAC_SIZE {
  61. self.decode_state = DecodeState::Header;
  62. let mut payload = buf.drain_to(size + MAC_SIZE);
  63. self.decode_cipher.decrypt(&mut payload.get_mut()[..size]);
  64. let mac = payload.split_off(size);
  65. self.decode_cipher.check_mac(mac.as_slice())?;
  66. return Ok(Some((cmd, payload)));
  67. }
  68. }
  69. Ok(None)
  70. }
  71. }