1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
pub mod client_channels;
/** STATE MACHINE **/
pub mod client_connection;

// re-export
pub use client_channels::*;
pub use client_connection::*;

use crate::{
    error::ProtoError,
    message::{AuthType, ChannelName, NowCapset, NowChannelDef, NowMessage, NowVirtualChannel},
};
use std::{cell::RefCell, rc::Rc};

// === connection sequence ===

pub type ConnectionSMSharedDataRc = Rc<RefCell<ConnectionSMSharedData>>;
pub type ConnectionSMResult<'a> = Result<Option<NowMessage<'a>>, ProtoError>;

pub trait ConnectionSM {
    fn set_shared_data(&mut self, shared_data: ConnectionSMSharedDataRc);
    fn get_shared_data(&self) -> Option<ConnectionSMSharedDataRc>;
    fn is_terminated(&self) -> bool;
    fn waiting_for_packet(&self) -> bool;
    fn update_without_message<'msg>(&mut self) -> ConnectionSMResult<'msg>;
    fn update_with_message<'msg: 'a, 'a>(&mut self, message: &'a NowMessage<'msg>) -> ConnectionSMResult<'msg>;
    fn is_running(&self) -> bool {
        !self.is_terminated()
    }
}

sa::assert_obj_safe!(ConnectionSM);

pub struct ConnectionSMSharedData {
    pub available_auth_types: Vec<AuthType>,
    pub capabilities: Vec<NowCapset<'static>>,
    pub channels: Vec<NowChannelDef>,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ConnectionState {
    Handshake,
    Negotiate,
    Authenticate,
    Associate,
    Capabilities,
    Channels,
    Final,
}

pub trait ConnectionSeqCallbackTrait {
    fn on_handshake_completed(&mut self, shared_data: &ConnectionSMSharedData) {
        #![allow(unused_variables)]
    }

    fn on_negotiate_completed(&mut self, shared_data: &ConnectionSMSharedData) {
        #![allow(unused_variables)]
    }

    fn on_authenticate_completed(&mut self, shared_data: &ConnectionSMSharedData) {
        #![allow(unused_variables)]
    }

    fn on_associate_completed(&mut self, shared_data: &ConnectionSMSharedData) {
        #![allow(unused_variables)]
    }

    fn on_capabilities_completed(&mut self, shared_data: &ConnectionSMSharedData) {
        #![allow(unused_variables)]
    }

    fn on_connection_completed(&mut self, shared_data: &ConnectionSMSharedData) {
        #![allow(unused_variables)]
    }
}

sa::assert_obj_safe!(ConnectionSeqCallbackTrait);

pub struct DummyConnectionSeqCallback;
impl ConnectionSeqCallbackTrait for DummyConnectionSeqCallback {}

pub struct DummyConnectionSM;
impl ConnectionSM for DummyConnectionSM {
    fn set_shared_data(&mut self, _: ConnectionSMSharedDataRc) {
        log::warn!("call to `DummyConnectionSM::set_shared_data`");
    }

    fn get_shared_data(&self) -> Option<ConnectionSMSharedDataRc> {
        log::warn!("call to `DummyConnectionSM::get_shared_data`");
        None
    }

    fn is_terminated(&self) -> bool {
        log::warn!("call to `DummyConnectionSM::is_terminated`");
        true
    }

    fn waiting_for_packet(&self) -> bool {
        log::warn!("call to `DummyConnectionSM::waiting_for_packet`");
        false
    }

    fn update_without_message<'msg>(&mut self) -> ConnectionSMResult<'msg> {
        log::warn!("call to `DummyConnectionSM::update_without_message`");
        Ok(None)
    }

    fn update_with_message<'msg: 'a, 'a>(&mut self, _msg: &'a NowMessage<'msg>) -> ConnectionSMResult<'msg> {
        log::warn!("call to `DummyConnectionSM::update_with_message`");
        Ok(None)
    }
}

// === virtual channels ===

pub type VirtChannelSMResult<'a> = Result<Option<NowVirtualChannel<'a>>, ProtoError>;

pub trait VirtualChannelSM {
    fn get_channel_name(&self) -> ChannelName;
    fn is_terminated(&self) -> bool;
    fn waiting_for_packet(&self) -> bool;
    fn update_without_chan_msg<'msg>(&mut self) -> VirtChannelSMResult<'msg>;
    fn update_with_chan_msg<'msg: 'a, 'a>(
        &mut self,
        chan_msg: &'a NowVirtualChannel<'msg>,
    ) -> VirtChannelSMResult<'msg>;
    fn is_running(&self) -> bool {
        !self.is_terminated()
    }
}

sa::assert_obj_safe!(VirtualChannelSM);

pub struct DummyVirtChannelSM;
impl VirtualChannelSM for DummyVirtChannelSM {
    fn get_channel_name(&self) -> ChannelName {
        log::warn!("call to `DummyVirtChannelSM::get_channel_name`");
        ChannelName::Unknown("Dummy".into())
    }

    fn is_terminated(&self) -> bool {
        log::warn!("call to `DummyVirtChannelSM::is_terminated`");
        true
    }

    fn waiting_for_packet(&self) -> bool {
        log::warn!("call to `DummyVirtChannelSM::waiting_for_packet`");
        false
    }

    fn update_without_chan_msg<'msg>(&mut self) -> VirtChannelSMResult<'msg> {
        log::warn!("call to `DummyVirtChannelSM::update_without_virt_msg`");
        Ok(None)
    }

    fn update_with_chan_msg<'msg: 'a, 'a>(&mut self, _: &'a NowVirtualChannel<'msg>) -> VirtChannelSMResult<'msg> {
        log::warn!("call to `DummyVirtChannelSM::update_with_chan_msg`");
        Ok(None)
    }
}