pub trait NetworkNotification {
// Required methods
fn write_notification(
&self,
target: PeerId,
protocol: ProtocolName,
message: Vec<u8>
);
fn notification_sender(
&self,
target: PeerId,
protocol: ProtocolName
) -> Result<Box<dyn NotificationSender>, NotificationSenderError>;
}
Expand description
Provides ability to send network notifications.
Required Methods§
sourcefn write_notification(
&self,
target: PeerId,
protocol: ProtocolName,
message: Vec<u8>
)
fn write_notification( &self, target: PeerId, protocol: ProtocolName, message: Vec<u8> )
Appends a notification to the buffer of pending outgoing notifications with the given peer. Has no effect if the notifications channel with this protocol name is not open.
If the buffer of pending outgoing notifications with that peer is full, the notification is silently dropped and the connection to the remote will start being shut down. This happens if you call this method at a higher rate than the rate at which the peer processes these notifications, or if the available network bandwidth is too low.
For this reason, this method is considered soft-deprecated. You are encouraged to use
NetworkNotification::notification_sender
instead.
Note: The reason why this is a no-op in the situation where we have no channel is that we don’t guarantee message delivery anyway. Networking issues can cause connections to drop at any time, and higher-level logic shouldn’t differentiate between the remote voluntarily closing a substream or a network error preventing the message from being delivered.
The protocol must have been registered with
crate::config::NetworkConfiguration::notifications_protocols
.
sourcefn notification_sender(
&self,
target: PeerId,
protocol: ProtocolName
) -> Result<Box<dyn NotificationSender>, NotificationSenderError>
fn notification_sender( &self, target: PeerId, protocol: ProtocolName ) -> Result<Box<dyn NotificationSender>, NotificationSenderError>
Obtains a NotificationSender
for a connected peer, if it exists.
A NotificationSender
is scoped to a particular connection to the peer that holds
a receiver. With a NotificationSender
at hand, sending a notification is done in two
steps:
NotificationSender::ready
is used to wait for the sender to become ready for another notification, yielding aNotificationSenderReady
token.NotificationSenderReady::send
enqueues the notification for sending. This operation can only fail if the underlying notification substream or connection has suddenly closed.
An error is returned by NotificationSenderReady::send
if there exists no open
notifications substream with that combination of peer and protocol, or if the remote
has asked to close the notifications substream. If that happens, it is guaranteed that an
Event::NotificationStreamClosed
has been generated on the stream returned by
NetworkEventStream::event_stream
.
If the remote requests to close the notifications substream, all notifications successfully
enqueued using NotificationSenderReady::send
will finish being sent out before the
substream actually gets closed, but attempting to enqueue more notifications will now
return an error. It is however possible for the entire connection to be abruptly closed,
in which case enqueued notifications will be lost.
The protocol must have been registered with
crate::config::NetworkConfiguration::notifications_protocols
.
Usage
This method returns a struct that allows waiting until there is space available in the buffer of messages towards the given peer. If the peer processes notifications at a slower rate than we send them, this buffer will quickly fill up.
As such, you should never do something like this:
// Do NOT do this
for peer in peers {
if let Ok(n) = network.notification_sender(peer, ...) {
if let Ok(s) = n.ready().await {
let _ = s.send(...);
}
}
}
Doing so would slow down all peers to the rate of the slowest one. A malicious or malfunctioning peer could intentionally process notifications at a very slow rate.
Instead, you are encouraged to maintain your own buffer of notifications on top of the one
maintained by sc-network
, and use notification_sender
to progressively send out
elements from your buffer. If this additional buffer is full (which will happen at some
point if the peer is too slow to process notifications), appropriate measures can be taken,
such as removing non-critical notifications from the buffer or disconnecting the peer
using NetworkPeers::disconnect_peer
.
Notifications Per-peer buffer
broadcast +—––> of notifications +–> notification_sender
+–> Internet
^ (not covered by
| sc-network)
+
Notifications should be dropped
if buffer is full
See also the sc-network-gossip
crate for a higher-level way to send notifications.