use data::{Data, DataRequest};
use id::{PublicId, FullId};
use xor_name::XorName;
use error::RoutingError;
use sodiumoxide::crypto::{box_, sign, hash};
use authority::Authority;
use maidsafe_utilities::serialisation::serialise;
use rustc_serialize::{Decoder, Encoder};
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub enum Message {
DirectMessage(DirectMessage),
HopMessage(HopMessage),
}
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub enum DirectMessage {
BootstrapIdentify {
public_id: ::id::PublicId,
current_quorum_size: usize,
},
ClientIdentify {
serialised_public_id: Vec<u8>,
signature: sign::Signature,
},
NodeIdentify {
serialised_public_id: Vec<u8>,
signature: sign::Signature,
},
Churn {
close_group: Vec<XorName>,
},
}
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct HopMessage {
content: SignedMessage,
name: XorName,
signature: sign::Signature,
}
impl HopMessage {
pub fn new(content: SignedMessage,
name: XorName,
sign_key: &sign::SecretKey)
-> Result<HopMessage, RoutingError> {
let bytes_to_sign = try!(serialise(&(&content, &name)));
Ok(HopMessage {
content: content,
name: name,
signature: sign::sign_detached(&bytes_to_sign, sign_key),
})
}
pub fn verify(&self, verification_key: &sign::PublicKey) -> Result<(), RoutingError> {
let signed_bytes = try!(serialise(&(&self.content, &self.name)));
if sign::verify_detached(&self.signature, &signed_bytes, verification_key) {
Ok(())
} else {
Err(RoutingError::FailedSignature)
}
}
pub fn extract(&self) -> (SignedMessage, XorName) {
(self.content.clone(), self.name.clone())
}
pub fn name(&self) -> &XorName {
&self.name
}
}
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct SignedMessage {
content: RoutingMessage,
public_id: PublicId,
signature: sign::Signature,
}
impl SignedMessage {
pub fn new(content: RoutingMessage, full_id: &FullId) -> Result<SignedMessage, RoutingError> {
let bytes_to_sign = try!(serialise(&(&content, full_id.public_id())));
Ok(SignedMessage {
content: content,
public_id: full_id.public_id().clone(),
signature: sign::sign_detached(&bytes_to_sign, full_id.signing_private_key()),
})
}
pub fn check_integrity(&self) -> Result<(), RoutingError> {
let signed_bytes = try!(serialise(&(&self.content, &self.public_id)));
if sign::verify_detached(&self.signature,
&signed_bytes,
self.public_id().signing_public_key()) {
Ok(())
} else {
Err(RoutingError::FailedSignature)
}
}
pub fn content(&self) -> &RoutingMessage {
&self.content
}
pub fn public_id(&self) -> &PublicId {
&self.public_id
}
}
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum RoutingMessage {
Request(RequestMessage),
Response(ResponseMessage),
}
impl RoutingMessage {
pub fn src(&self) -> &Authority {
match *self {
RoutingMessage::Request(ref msg) => &msg.src,
RoutingMessage::Response(ref msg) => &msg.src,
}
}
pub fn dst(&self) -> &Authority {
match *self {
RoutingMessage::Request(ref msg) => &msg.dst,
RoutingMessage::Response(ref msg) => &msg.dst,
}
}
}
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct RequestMessage {
pub src: Authority,
pub dst: Authority,
pub content: RequestContent,
}
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct ResponseMessage {
pub src: Authority,
pub dst: Authority,
pub content: ResponseContent,
}
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum RequestContent {
GetNetworkName {
current_id: PublicId,
},
ExpectCloseNode {
expect_id: PublicId,
},
GetCloseGroup,
Connect,
Endpoints {
encrypted_endpoints: Vec<u8>,
nonce_bytes: [u8; box_::NONCEBYTES],
},
GetPublicId,
GetPublicIdWithEndpoints {
encrypted_endpoints: Vec<u8>,
nonce_bytes: [u8; box_::NONCEBYTES],
},
Refresh {
type_tag: u64,
message: Vec<u8>,
cause: XorName,
},
Get(DataRequest),
Put(Data),
Post(Data),
Delete(Data),
}
#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
pub enum ResponseContent {
GetNetworkName {
relocated_id: PublicId,
},
GetPublicId {
public_id: PublicId,
},
GetPublicIdWithEndpoints {
public_id: PublicId,
encrypted_endpoints: Vec<u8>,
nonce_bytes: [u8; box_::NONCEBYTES],
},
GetCloseGroup {
close_group_ids: Vec<PublicId>,
},
GetSuccess(Data),
PutSuccess(hash::sha512::Digest),
PostSuccess(hash::sha512::Digest),
DeleteSuccess(hash::sha512::Digest),
GetFailure {
request: RequestMessage,
external_error_indicator: Vec<u8>,
},
PutFailure {
request: RequestMessage,
external_error_indicator: Vec<u8>,
},
PostFailure {
request: RequestMessage,
external_error_indicator: Vec<u8>,
},
DeleteFailure {
request: RequestMessage,
external_error_indicator: Vec<u8>,
},
}