libp2p_plaintext/
handshake.rs1use std::io::{Error as IoError, ErrorKind as IoErrorKind};
22
23use asynchronous_codec::{Framed, FramedParts};
24use bytes::Bytes;
25use futures::prelude::*;
26use libp2p_identity::{PeerId, PublicKey};
27
28use crate::{
29 error::{DecodeError, Error},
30 proto::Exchange,
31 Config,
32};
33
34pub(crate) async fn handshake<S>(socket: S, config: Config) -> Result<(S, PublicKey, Bytes), Error>
35where
36 S: AsyncRead + AsyncWrite + Send + Unpin,
37{
38 let mut framed_socket = Framed::new(socket, quick_protobuf_codec::Codec::<Exchange>::new(100));
40
41 tracing::trace!("sending exchange to remote");
42 framed_socket
43 .send(Exchange {
44 id: Some(config.local_public_key.to_peer_id().to_bytes()),
45 pubkey: Some(config.local_public_key.encode_protobuf()),
46 })
47 .await
48 .map_err(DecodeError)?;
49
50 tracing::trace!("receiving the remote's exchange");
51 let public_key = match framed_socket
52 .next()
53 .await
54 .transpose()
55 .map_err(DecodeError)?
56 {
57 Some(remote) => {
58 let public_key = PublicKey::try_decode_protobuf(&remote.pubkey.unwrap_or_default())?;
59 let peer_id = PeerId::from_bytes(&remote.id.unwrap_or_default())?;
60
61 if peer_id != public_key.to_peer_id() {
62 return Err(Error::PeerIdMismatch);
63 }
64
65 public_key
66 }
67 None => {
68 tracing::debug!("unexpected eof while waiting for remote's exchange");
69 let err = IoError::new(IoErrorKind::BrokenPipe, "unexpected eof");
70 return Err(err.into());
71 }
72 };
73
74 tracing::trace!(?public_key, "received exchange from remote");
75
76 let FramedParts {
77 io,
78 read_buffer,
79 write_buffer,
80 ..
81 } = framed_socket.into_parts();
82 assert!(write_buffer.is_empty());
83 Ok((io, public_key, read_buffer.freeze()))
84}