helpful things
Diff
src/main.rs | 35 +++++++++++++++++++++++++++++++++--
src/git/codec.rs | 16 ++++++++++++++++
src/git/mod.rs | 25 +++++++++++++++++++++++--
src/git/packfile.rs | 26 ++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 15 deletions(-)
@@ -85,13 +85,13 @@
session.close(channel);
} else {
session.data(channel, PktLine(b"version 2\n").into());
session.data(channel, PktLine(b"agent=chartered/0.1.0\n").into());
session.data(channel, PktLine(b"ls-refs=unborn\n").into());
session.data(channel, PktLine(b"fetch=shallow wait-for-done\n").into());
session.data(channel, PktLine(b"server-option\n").into());
session.data(channel, PktLine(b"object-info\n").into());
session.data(channel, CryptoVec::from_slice(git::END_OF_MESSAGE));
session.data(channel, PktLine::Data(b"version 2\n").into());
session.data(channel, PktLine::Data(b"agent=chartered/0.1.0\n").into());
session.data(channel, PktLine::Data(b"ls-refs=unborn\n").into());
session.data(channel, PktLine::Data(b"fetch=shallow wait-for-done\n").into());
session.data(channel, PktLine::Data(b"server-option\n").into());
session.data(channel, PktLine::Data(b"object-info\n").into());
session.data(channel, PktLine::Flush.into());
}
futures::future::ready(Ok((self, session)))
@@ -112,11 +112,30 @@
self.finished_auth(server::Auth::Accept)
}
fn data(mut self, _channel: ChannelId, data: &[u8], session: Session) -> Self::FutureUnit {
fn data(mut self, channel: ChannelId, data: &[u8], mut session: Session) -> Self::FutureUnit {
self.input_bytes.extend_from_slice(data);
let mut ls_refs = false;
while let Some(frame) = self.codec.decode(&mut self.input_bytes).unwrap() {
eprintln!("data: {:x?}", frame);
if frame.as_ref() == "command=ls-refs".as_bytes() {
ls_refs = true;
}
}
if ls_refs {
session.data(channel, PktLine::Data(b"1a1b25ae7c87a0e87b7a9aa478a6bc4331c6b954 HEAD symref-target:refs/heads/master\n").into());
session.data(channel, PktLine::Flush.into());
}
futures::future::ready(Ok((self, session)))
@@ -21,11 +21,12 @@
|| length == 1
|| length == 2
{
eprintln!("pkt: {}", length);
src.advance(4);
return self.decode(src);
}
if length > 65520 || length <= 4 {
if length > 65520 || length < 4 {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "protocol abuse").into());
}
@@ -62,7 +63,20 @@
assert_eq!(res, None);
bytes.write_char('\n').unwrap();
bytes.write_str("0002").unwrap();
bytes.write_str("0004").unwrap();
bytes.write_str("0005a").unwrap();
let res = codec.decode(&mut bytes).unwrap();
assert_eq!(res.as_deref(), Some("agent=git/2.32.0".as_bytes()));
let res = codec.decode(&mut bytes).unwrap();
assert_eq!(res.as_deref(), Some("".as_bytes()));
let res = codec.decode(&mut bytes).unwrap();
assert_eq!(res.as_deref(), Some("a".as_bytes()));
let res = codec.decode(&mut bytes).unwrap();
assert_eq!(res.as_deref(), None);
}
}
@@ -1,17 +1,30 @@
pub mod codec;
pub mod packfile;
use thrussh::CryptoVec;
pub const END_OF_MESSAGE: &'static [u8] = b"0000";
pub struct PktLine<'a>(pub &'a [u8]);
pub enum PktLine<'a> {
Data(&'a [u8]),
Flush,
Delimiter,
ResponseEnd,
}
impl PktLine<'_> {
pub fn encode(&self) -> Vec<u8> {
let mut v = Vec::new();
v.extend_from_slice(format!("{:04x}", self.0.len() + 4).as_ref());
v.extend_from_slice(self.0);
match self {
Self::Data(data) => {
v.extend_from_slice(format!("{:04x}", data.len() + 4).as_ref());
v.extend_from_slice(data);
},
Self::Flush => v.extend_from_slice(b"0000"),
Self::Delimiter => v.extend_from_slice(b"0001"),
Self::ResponseEnd => v.extend_from_slice(b"0002"),
}
v
}
}
@@ -24,7 +37,7 @@
impl<'a> From<&'a str> for PktLine<'a> {
fn from(val: &'a str) -> Self {
PktLine(val.as_bytes())
PktLine::Data(val.as_bytes())
}
}
@@ -1,0 +1,26 @@
pub struct PackFileIndex<const S: usize> {
pub magic: [u8; 4],
pub version: [u8; 4],
pub fanout: [[u8; 4]; 255],
pub size: u16,
pub sha1: [[u8; 20]; S],
pub crc: [[u8; 4]; S],
pub offset: [[u8; 4]; S],
pub packfile_checksum: [u8; 20],
pub idxfiel_checksum: [u8; 20],
}