Enum Protocol

Source
pub enum Protocol {
    Ping,
    WhatTimeIsIt,
    Quit,
    Identity,
    Http {
        id: String,
    },
    Socks5 {
        id: String,
    },
    Tcp {
        id: String,
    },
}
Expand description

§why are we handling protocols ourselves and not using the built-in APNS feature?

first, I would re-emphasize that we could have used APNS feature of iroh1, they have built in protocol handling support. but it does not work because if you want to use more than one protocol, you have to create more than one connection with the peer.

why would we want that? say a peer wants to do multiple types of things at the same time. for example, do a ping to check if connection is open, or to send both http and tcp proxy at the same time. consider I am on call with you but also browsing a folder you have shared.

from the docs it is not clear if creating another connection, after one connection is already established is a cheap operation or not. in my opinion, it cannot be cheap because ALPN is used as part of TLS connection handshake process.

this is how the client hello message looks like during initial TLS connection handshake:

Handshake Type: Client Hello (1) Length: 141 Version: TLS 1.2 (0x0303) Random: dd67b5943e5efd0740519f38071008b59efbd68ab3114587… Session ID Length: 0 Cipher Suites Length: 10 Cipher Suites (5 suites) Compression Methods Length: 1 Compression Methods (1 method) Extensions Length: 90 [other extensions omitted] Extension: application_layer_protocol_negotiation (len=14) Type: application_layer_protocol_negotiation (16) Length: 14 ALPN Extension Length: 12 ALPN Protocol ALPN string length: 2 ALPN Next Protocol: h2 ALPN string length: 8 ALPN Next Protocol: http/1.1

as you see, the ALPN is part of the client hello message, and it is sent during the initial connection handshake. so if we want to use more than one protocol, we have to do one more client hello hand-shake proces.

so we are using multiple bidirectional streams over a single connection. each new stream con be used for a same or different protocol.

note: this is not a settled decision. if we are doing audio video streaming, we may not get the optimal performance, and we may have to use multiple connections; this approach is to be verified in the future.

§the protocol “protocol”

the protocol: the peer / side that wants to communicate will be considered the “client”, and will initiate the bidirectional stream using iroh::Connection::open_bi() method. the server will have an infinite loop to accept incoming bidirectional streams. for the loop to end, the client must send a “quit” message and wait for ack from the server before closing the connection.

the bidirectional stream will contain new line terminal JSON text indicating the protocol, and the rest of the message will be handled by the protocol-specific handler.

the protocol JSON line will be called header line, or stream header.

the stream header can contain protocol-specific information also, e.g., the request to proxy to a server may include information about the server to proxy to in the protocol header. so that the lower level protocol handler need not worry about further ways to extract protocol-specific data.

§security philosophy: more protocols, more liabilities

the goal of the FTNet is to make sure there are only a few protocols. all protocol handlers are security risk, they are written in Rust, possibly using C and other libraries. their code has to be reviewed for potential security issues.

this is why fastn is a full stack web application. fastn programs are compiled in JS code, and in future to webassembly, and JS engines have decent security sandbox. we do not allow npm/deno etc., and only run the most sandboxed, browser like JS code. fastn applications can also use webassembly compiled code, which again is sandboxed.

Variants§

§

Ping

client can send this message to check if the connection is open / healthy.

§

WhatTimeIsIt

client may not be using NTP, or may only have p2p access and no other internet access, in which case it can ask for the time from the peers and try to create a consensus.

§

Quit

client is done and want to end close the connection

§

Identity

connect with the identity server. this means connect with the fastn service as part of the identity server.

§

Http

client wants to make an HTTP request to a device whose ID is specified. note that the exact ip:port is not known to peers, they only the “device id” for the service. server will figure out the ip:port from the device id.

Fields

§

Socks5

if the client wants their traffic to route via this server, they can send this. for this to work, the person owning the device must have created a SOCKS5 device, and allowed this peer to access it.

Fields

§

Tcp

Fields

Trait Implementations§

Source§

impl Debug for Protocol

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Protocol

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Protocol

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> ErasedDestructor for T
where T: 'static,