SessionManager

Struct SessionManager 

Source
pub struct SessionManager<T> { /* private fields */ }

Implementations§

Source§

impl<T> SessionManager<T>
where T: ServiceHandler,

Source

pub fn new(options: SessionManagerOptions<T>) -> Arc<Self>

Source

pub fn get_session_or_default<'a, 'b>( &'a self, key: &'b Identifier, ) -> ReadLock<'b, 'a, Identifier, Table<Identifier, Session>>

Get session for addr.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

// get_session always creates a new session if it doesn't exist
{
    assert!(sessions.get_session(&addr).get_ref().is_none());
}

// get_session always creates a new session if it doesn't exist
{
    let lock = sessions.get_session_or_default(&addr);
    let session = lock.get_ref().unwrap();
    match session {
        Session::New { .. } => {},
        _ => panic!("Expected new session"),
    }
}

sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on();

{
    let lock = sessions.get_session(&addr);
    let session = lock.get_ref().unwrap();
    match session {
        Session::Authenticated { username, allocate_port, allocate_channels, .. } => {
            assert_eq!(username, "test");
            assert_eq!(allocate_port, &None);
            assert_eq!(allocate_channels.len(), 0);
        }
        _ => panic!("Expected authenticated session"),
    }
}
Source

pub fn get_session<'a, 'b>( &'a self, key: &'b Identifier, ) -> ReadLock<'b, 'a, Identifier, Table<Identifier, Session>>

Source

pub async fn get_password( &self, addr: &Identifier, username: &str, algorithm: PasswordAlgorithm, ) -> Option<Password>

Get digest for addr.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

// First call get_session to create a new session
{
    sessions.get_session(&addr);
}
assert_eq!(pollster::block_on(sessions.get_password(&addr, "test1", PasswordAlgorithm::Md5)), None);

// Create a new session for the next test
{
    sessions.get_session(&addr);
}
assert_eq!(sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on(), Some(digest));

// The third call should return cached digest
assert_eq!(sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on(), Some(digest));
Source

pub fn allocated(&self) -> usize

Source

pub fn allocate(&self, addr: &Identifier, lifetime: Option<u32>) -> Option<u16>

Assign a port number to the session.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on();

{
    let lock = sessions.get_session(&addr);
    let session = lock.get_ref().unwrap();
    match session {
        Session::Authenticated { username, allocate_port, allocate_channels, .. } => {
            assert_eq!(username, "test");
            assert_eq!(allocate_port, &None);
            assert_eq!(allocate_channels.len(), 0);
        }
        _ => panic!("Expected authenticated session"),
    }
}

let port = sessions.allocate(&addr, None).unwrap();
{
    let lock = sessions.get_session(&addr);
    let session = lock.get_ref().unwrap();
    match session {
        Session::Authenticated { username, allocate_port, allocate_channels, .. } => {
            assert_eq!(username, "test");
            assert_eq!(allocate_port, &Some(port));
            assert_eq!(allocate_channels.len(), 0);
        }
        _ => panic!("Expected authenticated session"),
    }
}

assert_eq!(sessions.allocate(&addr, None), Some(port));
Source

pub fn create_permission( &self, addr: &Identifier, endpoint: &SocketAddr, ports: &[u16], ) -> bool

Create permission for session.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let endpoint = "127.0.0.1:3478".parse().unwrap();
let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let peer_addr = Identifier {
    source: "127.0.0.1:8081".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on();
sessions.get_password(&peer_addr, "test", PasswordAlgorithm::Md5).block_on();

let port = sessions.allocate(&addr, None).unwrap();
let peer_port = sessions.allocate(&peer_addr, None).unwrap();

assert!(!sessions.create_permission(&addr, &endpoint, &[port]));
assert!(sessions.create_permission(&addr, &endpoint, &[peer_port]));

assert!(!sessions.create_permission(&peer_addr, &endpoint, &[peer_port]));
assert!(sessions.create_permission(&peer_addr, &endpoint, &[port]));
Source

pub fn bind_channel( &self, addr: &Identifier, endpoint: &SocketAddr, port: u16, channel: u16, ) -> bool

Binding a channel to the session.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let endpoint = "127.0.0.1:3478".parse().unwrap();
let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let peer_addr = Identifier {
    source: "127.0.0.1:8081".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on();
sessions.get_password(&peer_addr, "test", PasswordAlgorithm::Md5).block_on();

let port = sessions.allocate(&addr, None).unwrap();
let peer_port = sessions.allocate(&peer_addr, None).unwrap();
{
    assert_eq!(
        match sessions.get_session(&addr).get_ref().unwrap() {
            Session::Authenticated { allocate_channels, .. } => allocate_channels.len(),
            _ => panic!("Expected authenticated session"),
        },
        0
    );
}

{
    assert_eq!(
        match sessions.get_session(&peer_addr).get_ref().unwrap() {
            Session::Authenticated { allocate_channels, .. } => allocate_channels.len(),
            _ => panic!("Expected authenticated session"),
        },
        0
    );
}

assert!(sessions.bind_channel(&addr, &endpoint, peer_port, 0x4000));
assert!(sessions.bind_channel(&peer_addr, &endpoint, port, 0x4000));

{
    assert_eq!(
        match sessions.get_session(&addr).get_ref().unwrap() {
            Session::Authenticated { allocate_channels, .. } => allocate_channels.clone(),
            _ => panic!("Expected authenticated session"),
        },
        vec![0x4000]
    );
}

{
    assert_eq!(
        match sessions.get_session(&peer_addr).get_ref().unwrap() {
            Session::Authenticated { allocate_channels, .. } => allocate_channels.clone(),
            _ => panic!("Expected authenticated session"),
        },
        vec![0x4000]
    );
}
Source

pub fn get_channel_relay_address( &self, addr: &Identifier, channel: u16, ) -> Option<Endpoint>

Gets the peer of the current session bound channel.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let endpoint = "127.0.0.1:3478".parse().unwrap();
let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let peer_addr = Identifier {
    source: "127.0.0.1:8081".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on();
sessions.get_password(&peer_addr, "test", PasswordAlgorithm::Md5).block_on();

let port = sessions.allocate(&addr, None).unwrap();
let peer_port = sessions.allocate(&peer_addr, None).unwrap();

assert!(sessions.bind_channel(&addr, &endpoint, peer_port, 0x4000));
assert!(sessions.bind_channel(&peer_addr, &endpoint, port, 0x4000));
assert_eq!(
    sessions
        .get_channel_relay_address(&addr, 0x4000)
        .unwrap()
        .endpoint,
    endpoint
);

assert_eq!(
    sessions
        .get_channel_relay_address(&peer_addr, 0x4000)
        .unwrap()
        .endpoint,
    endpoint
);
Source

pub fn get_relay_address( &self, addr: &Identifier, port: u16, ) -> Option<Endpoint>

Get the address of the port binding.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let endpoint = "127.0.0.1:3478".parse().unwrap();
let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let peer_addr = Identifier {
    source: "127.0.0.1:8081".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on();
sessions.get_password(&peer_addr, "test", PasswordAlgorithm::Md5).block_on();

let port = sessions.allocate(&addr, None).unwrap();
let peer_port = sessions.allocate(&peer_addr, None).unwrap();

assert!(sessions.create_permission(&addr, &endpoint, &[peer_port]));
assert!(sessions.create_permission(&peer_addr, &endpoint, &[port]));

assert_eq!(
    sessions
        .get_relay_address(&addr, peer_port)
        .unwrap()
        .endpoint,
    endpoint
);

assert_eq!(
    sessions
        .get_relay_address(&peer_addr, port)
        .unwrap()
        .endpoint,
    endpoint
);
Source

pub fn refresh(&self, addr: &Identifier, lifetime: u32) -> bool

Refresh the session for addr.

§Test
use turn_server::service::session::*;
use turn_server::service::*;
use turn_server::codec::message::attributes::PasswordAlgorithm;
use turn_server::codec::crypto::Password;
use pollster::FutureExt;

#[derive(Clone)]
struct ServiceHandlerTest;

impl ServiceHandler for ServiceHandlerTest {
    async fn get_password(&self, username: &str, algorithm: PasswordAlgorithm) -> Option<Password> {
        if username == "test" {
            Some(turn_server::codec::crypto::generate_password(username, "test", "test", algorithm))
        } else {
            None
        }
    }
}

let addr = Identifier {
    source: "127.0.0.1:8080".parse().unwrap(),
    interface: "127.0.0.1:3478".parse().unwrap(),
};

let digest = Password::Md5([
    174, 238, 187, 253, 117, 209, 73, 157, 36, 56, 143, 91, 155, 16, 224,
    239,
]);

let sessions = SessionManager::new(SessionManagerOptions {
    port_range: (49152..65535).into(),
    handler: ServiceHandlerTest,
});

// get_session always creates a new session if it doesn't exist
{
    let lock = sessions.get_session_or_default(&addr);
    let session = lock.get_ref().unwrap();
    match session {
        Session::New { .. } => {},
        _ => panic!("Expected new session"),
    }
}

sessions.get_password(&addr, "test", PasswordAlgorithm::Md5).block_on();

{
    let lock = sessions.get_session(&addr);
    let expires = match lock.get_ref().unwrap() {
        Session::Authenticated { expires, .. } => *expires,
        _ => panic!("Expected authenticated session"),
    };

    assert!(expires == 600 || expires == 601 || expires == 602);
}

assert!(sessions.refresh(&addr, 0));

// After refresh with lifetime 0, session should be removed
{
    assert!(sessions.get_session(&addr).get_ref().is_none());
}

Auto Trait Implementations§

§

impl<T> !Freeze for SessionManager<T>

§

impl<T> !RefUnwindSafe for SessionManager<T>

§

impl<T> Send for SessionManager<T>
where T: Send,

§

impl<T> Sync for SessionManager<T>
where T: Sync,

§

impl<T> Unpin for SessionManager<T>
where T: Unpin,

§

impl<T> UnwindSafe for SessionManager<T>
where T: UnwindSafe,

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<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> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
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> ErasedDestructor for T
where T: 'static,