use crate::util::{
logger,
ser::{LengthLimitedRead, LengthReadable, Readable, WithoutLength, Writeable, Writer},
};
use crate::{encode_tlv_stream, ln::types::ChannelId, socket_addr::SocketAddress};
use bitcoin::blockdata::constants::ChainHash;
use lightning_types::features::InitFeatures;
use std::io;
#[derive(Clone, Debug)]
pub struct LightningError {
pub err: String,
pub action: ErrorAction,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum DecodeError {
UnknownVersion,
UnknownRequiredFeature,
InvalidValue,
ShortRead,
BadLengthDescriptor,
Io(std::io::ErrorKind),
}
impl From<std::io::Error> for DecodeError {
fn from(err: std::io::Error) -> Self {
DecodeError::Io(err.kind())
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Init {
pub global_features: Vec<u8>,
pub features: Vec<u8>,
pub networks: Option<Vec<ChainHash>>,
pub remote_network_address: Option<SocketAddress>,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct ErrorMessage {
pub channel_id: ChannelId,
pub data: String,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct WarningMessage {
pub channel_id: ChannelId,
pub data: String,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Ping {
pub ponglen: u16,
pub byteslen: u16,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Pong {
pub byteslen: u16,
}
#[derive(Clone, Debug, Hash, PartialEq)]
pub enum ErrorAction {
DisconnectPeer {
msg: Option<ErrorMessage>,
},
DisconnectPeerWithWarning {
msg: WarningMessage,
},
IgnoreError,
IgnoreDuplicateGossip,
SendErrorMessage {
msg: ErrorMessage,
},
SendWarningMessage {
msg: WarningMessage,
log_level: logger::Level,
},
}
impl Writeable for Init {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), std::io::Error> {
self.global_features.write(w)?;
self.features.write(w)?;
encode_tlv_stream!(w, {
(1, self.networks.as_ref().map(WithoutLength), option),
(3, self.remote_network_address, option),
});
Ok(())
}
}
macro_rules! impl_feature_len_prefixed_write {
($features: ident) => {
impl Writeable for $features {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
let bytes = self.le_flags();
(bytes.len() as u16).write(w)?;
write_be(w, bytes)
}
}
impl Readable for $features {
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
Ok(Self::from_be_bytes(Vec::<u8>::read(r)?))
}
}
};
}
impl_feature_len_prefixed_write!(InitFeatures);
fn write_be<W: Writer>(w: &mut W, le_flags: &[u8]) -> Result<(), io::Error> {
for f in le_flags.iter().rev() {
f.write(w)?;
}
Ok(())
}
impl Writeable for ErrorMessage {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
self.channel_id.write(w)?;
(self.data.len() as u16).write(w)?;
w.write_all(self.data.as_bytes())?;
Ok(())
}
}
impl LengthReadable for ErrorMessage {
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
Ok(Self {
channel_id: Readable::read(r)?,
data: {
let sz: usize = <u16 as Readable>::read(r)? as usize;
let mut data = vec![0; sz];
r.read_exact(&mut data)?;
match String::from_utf8(data) {
Ok(s) => s,
Err(_) => return Err(DecodeError::InvalidValue),
}
},
})
}
}
impl Writeable for WarningMessage {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
self.channel_id.write(w)?;
(self.data.len() as u16).write(w)?;
w.write_all(self.data.as_bytes())?;
Ok(())
}
}
impl LengthReadable for WarningMessage {
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
Ok(Self {
channel_id: Readable::read(r)?,
data: {
let sz: usize = <u16 as Readable>::read(r)? as usize;
let mut data = vec![0; sz];
r.read_exact(&mut data)?;
match String::from_utf8(data) {
Ok(s) => s,
Err(_) => return Err(DecodeError::InvalidValue),
}
},
})
}
}
impl Writeable for Pong {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
vec![0u8; self.byteslen as usize].write(w)?; Ok(())
}
}
impl LengthReadable for Pong {
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
Ok(Pong {
byteslen: {
let byteslen = Readable::read(r)?;
r.read_exact(&mut vec![0u8; byteslen as usize][..])?;
byteslen
},
})
}
}
impl Writeable for Ping {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
self.ponglen.write(w)?;
vec![0u8; self.byteslen as usize].write(w)?; Ok(())
}
}
impl LengthReadable for Ping {
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
Ok(Ping {
ponglen: Readable::read(r)?,
byteslen: {
let byteslen = Readable::read(r)?;
r.read_exact(&mut vec![0u8; byteslen as usize][..])?;
byteslen
},
})
}
}
impl LengthReadable for Init {
fn read_from_fixed_length_buffer<R: LengthLimitedRead>(r: &mut R) -> Result<Self, DecodeError> {
let global_features: Vec<u8> = Readable::read(r)?;
let features: Vec<u8> = Readable::read(r)?;
let mut buf = Vec::with_capacity(r.remaining_bytes() as usize);
r.read_to_end(&mut buf)?;
Ok(Init {
global_features,
features,
networks: None,
remote_network_address: None,
})
}
}