Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(examples): use cbor codec in file-sharing example #4036

Merged
merged 13 commits into from
Jun 6, 2023
Merged
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion examples/file-sharing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ publish = false
license = "MIT"

[dependencies]
libp2p-request-response = { workspace = true, features = ["cbor"] }
thomaseizinger marked this conversation as resolved.
Show resolved Hide resolved
serde = { version = "1.0", features = ["derive"] }
async-std = { version = "1.12", features = ["attributes"] }
async-trait = "0.1"
clap = { version = "4.3.1", features = ["derive"] }
either = "1.8"
env_logger = "0.10"
Expand Down
93 changes: 9 additions & 84 deletions examples/file-sharing/src/network.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
use async_std::io;
use async_trait::async_trait;
use either::Either;
use futures::channel::{mpsc, oneshot};
use futures::prelude::*;

use libp2p::{
core::{
upgrade::{read_length_prefixed, write_length_prefixed},
Multiaddr,
},
core::Multiaddr,
identity,
kad::{
record::store::MemoryStore, GetProvidersOk, Kademlia, KademliaEvent, QueryId, QueryResult,
Expand All @@ -22,9 +18,9 @@ use libp2p::{

use libp2p::core::upgrade::Version;
use libp2p::StreamProtocol;
use serde::{Deserialize, Serialize};
use std::collections::{hash_map, HashMap, HashSet};
use std::error::Error;
use std::iter;

/// Creates the network components, namely:
///
Expand Down Expand Up @@ -60,13 +56,12 @@ pub(crate) async fn new(
transport,
ComposedBehaviour {
kademlia: Kademlia::new(peer_id, MemoryStore::new(peer_id)),
request_response: request_response::Behaviour::with_codec(
FileExchangeCodec(),
iter::once((
request_response: request_response::cbor::Behaviour::new(
[(
StreamProtocol::new("/file-exchange/1"),
ProtocolSupport::Full,
)),
Default::default(),
)],
request_response::Config::default(),
),
},
peer_id,
Expand Down Expand Up @@ -413,7 +408,7 @@ impl EventLoop {
#[derive(NetworkBehaviour)]
#[behaviour(to_swarm = "ComposedEvent")]
struct ComposedBehaviour {
request_response: request_response::Behaviour<FileExchangeCodec>,
request_response: request_response::cbor::Behaviour<FileRequest, FileResponse>,
kademlia: Kademlia<MemoryStore>,
}

Expand Down Expand Up @@ -474,77 +469,7 @@ pub(crate) enum Event {
}

// Simple file exchange protocol

#[derive(Clone)]
struct FileExchangeCodec();
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
struct FileRequest(String);
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct FileResponse(Vec<u8>);

#[async_trait]
impl request_response::Codec for FileExchangeCodec {
type Protocol = StreamProtocol;
type Request = FileRequest;
type Response = FileResponse;

async fn read_request<T>(&mut self, _: &StreamProtocol, io: &mut T) -> io::Result<Self::Request>
where
T: AsyncRead + Unpin + Send,
{
let vec = read_length_prefixed(io, 1_000_000).await?;

if vec.is_empty() {
return Err(io::ErrorKind::UnexpectedEof.into());
}

Ok(FileRequest(String::from_utf8(vec).unwrap()))
}

async fn read_response<T>(
&mut self,
_: &StreamProtocol,
io: &mut T,
) -> io::Result<Self::Response>
where
T: AsyncRead + Unpin + Send,
{
let vec = read_length_prefixed(io, 500_000_000).await?; // update transfer maximum

if vec.is_empty() {
return Err(io::ErrorKind::UnexpectedEof.into());
}

Ok(FileResponse(vec))
}

async fn write_request<T>(
&mut self,
_: &StreamProtocol,
io: &mut T,
FileRequest(data): FileRequest,
) -> io::Result<()>
where
T: AsyncWrite + Unpin + Send,
{
write_length_prefixed(io, data).await?;
io.close().await?;

Ok(())
}

async fn write_response<T>(
&mut self,
_: &StreamProtocol,
io: &mut T,
FileResponse(data): FileResponse,
) -> io::Result<()>
where
T: AsyncWrite + Unpin + Send,
{
write_length_prefixed(io, data).await?;
io.close().await?;

Ok(())
}
}