1use binprot_derive::{BinProtRead, BinProtWrite};
2use derive_more::From;
3use malloc_size_of_derive::MallocSizeOf;
4use openmina_core::ChainId;
5use serde::{Deserialize, Serialize};
6
7use crate::identity::{EncryptableType, PeerId, PublicKey};
8
9use super::{ConnectionAuth, Host};
10
11#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone, MallocSizeOf)]
12pub struct Offer {
13 pub sdp: String,
14 #[ignore_malloc_size_of = "doesn't allocate"]
15 pub chain_id: ChainId,
16 #[ignore_malloc_size_of = "doesn't allocate"]
18 pub identity_pub_key: PublicKey,
19 pub target_peer_id: PeerId,
21 #[ignore_malloc_size_of = "neglectible"]
24 pub host: Host,
25 pub listen_port: Option<u16>,
27}
28
29#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone, MallocSizeOf)]
30pub struct Answer {
31 pub sdp: String,
32 #[ignore_malloc_size_of = "doesn't allocate"]
34 pub identity_pub_key: PublicKey,
35 pub target_peer_id: PeerId,
37}
38
39#[derive(Serialize, Deserialize, From, Eq, PartialEq, Debug, Clone)]
40pub enum Signal {
41 Offer(Offer),
42 Answer(Answer),
43}
44
45#[derive(
46 Serialize, Deserialize, Eq, PartialEq, Debug, Clone, Copy, thiserror::Error, MallocSizeOf,
47)]
48pub enum RejectionReason {
49 #[error("peer is on a different chain")]
50 ChainIdMismatch,
51 #[error("peer_id does not match peer's public key")]
52 PeerIdAndPublicKeyMismatch,
53 #[error("target peer_id is not local node's peer_id")]
54 TargetPeerIdNotMe,
55 #[error("too many peers")]
56 PeerCapacityFull,
57 #[error("peer already connected")]
58 AlreadyConnected,
59 #[error("self connection detected")]
60 ConnectingToSelf,
61}
62
63#[derive(Serialize, Deserialize, Debug, Clone)]
64pub enum P2pConnectionResponse {
65 Accepted(Box<Answer>),
66 Rejected(RejectionReason),
67 SignalDecryptionFailed,
68 InternalError,
69}
70
71fn sdp_hash(sdp: &str) -> [u8; 32] {
72 use sha2::{Digest, Sha256};
73 let mut hasher = Sha256::new();
74 hasher.update(sdp);
75 hasher.finalize().into()
76}
77
78impl Offer {
79 pub fn sdp_hash(&self) -> [u8; 32] {
80 sdp_hash(&self.sdp)
81 }
82
83 pub fn conn_auth(&self, answer: &Answer) -> ConnectionAuth {
84 ConnectionAuth::new(self, answer)
85 }
86}
87
88impl Answer {
89 pub fn sdp_hash(&self) -> [u8; 32] {
90 sdp_hash(&self.sdp)
91 }
92}
93
94impl RejectionReason {
95 pub fn is_bad(&self) -> bool {
96 match self {
97 Self::ChainIdMismatch => false,
98 Self::PeerIdAndPublicKeyMismatch => true,
99 Self::TargetPeerIdNotMe => true,
100 Self::PeerCapacityFull => false,
101 Self::AlreadyConnected => true,
102 Self::ConnectingToSelf => false,
103 }
104 }
105}
106
107impl P2pConnectionResponse {
108 pub fn internal_error_str() -> &'static str {
109 "InternalError"
110 }
111
112 pub fn internal_error_json_str() -> &'static str {
113 "\"InternalError\""
114 }
115}
116
117#[derive(BinProtWrite, BinProtRead, Serialize, Deserialize, From, Debug, Clone)]
119pub struct EncryptedOffer(Vec<u8>);
120
121#[derive(BinProtWrite, BinProtRead, Serialize, Deserialize, From, Debug, Clone)]
123pub struct EncryptedAnswer(Vec<u8>);
124
125impl AsRef<[u8]> for EncryptedOffer {
126 fn as_ref(&self) -> &[u8] {
127 self.0.as_ref()
128 }
129}
130
131impl AsRef<[u8]> for EncryptedAnswer {
132 fn as_ref(&self) -> &[u8] {
133 self.0.as_ref()
134 }
135}
136
137impl EncryptableType for Offer {
138 type Encrypted = EncryptedOffer;
139}
140
141impl EncryptableType for P2pConnectionResponse {
142 type Encrypted = EncryptedAnswer;
143}