libquassel/message/handshake/clientinit.rs
1use crate::error::ProtocolError;
2use crate::primitive::{StringList, Variant, VariantMap};
3use crate::{HandshakeDeserialize, HandshakeSerialize};
4
5use failure::Error;
6
7/// ClientInit is the Initial message send to the core after establishing a base layer comunication.
8///
9/// Features
10///
11/// | Flag | Name | Description |
12/// | ---- | ---- | ----------- |
13/// | 0x00000001 | SynchronizedMarkerLine | -- |
14/// | 0x00000002 | SaslAuthentication | -- |
15/// | 0x00000004 | SaslExternal | -- |
16/// | 0x00000008 | HideInactiveNetworks | -- |
17/// | 0x00000010 | PasswordChange | -- |
18/// | 0x00000020 | CapNegotiation | IRCv3 capability negotiation, account tracking |
19/// | 0x00000040 | VerifyServerSSL | IRC server SSL validation |
20/// | 0x00000080 | CustomRateLimits | IRC server custom message rate limits |
21/// | 0x00000100 | DccFileTransfer | Currently not supported |
22/// | 0x00000200 | AwayFormatTimestamp | Timestamp formatting in away (e.g. %%hh:mm%%) |
23/// | 0x00000400 | Authenticators | Support for exchangeable auth backends |
24/// | 0x00000800 | BufferActivitySync | Sync buffer activity status |
25/// | 0x00001000 | CoreSideHighlights | Core-Side highlight configuration and matching |
26/// | 0x00002000 | SenderPrefixes | Show prefixes for senders in backlog |
27/// | 0x00004000 | RemoteDisconnect | Supports RPC call disconnectFromCore to remotely disconnect a client |
28/// | 0x00008000 | ExtendedFeatures | Transmit features as list of strings |
29/// | -- | LongTime | Serialize message time as 64-bit |
30/// | -- | RichMessages | Real Name and Avatar URL in backlog |
31/// | -- | BacklogFilterType | Backlogmanager supports filtering backlog by messagetype |
32/// | -- | EcdsaCertfpKeys | ECDSA keys for CertFP in identities |
33/// | -- | LongMessageId | 64-bit IDs for messages |
34/// | -- | SyncedCoreInfo | CoreInfo dynamically updated using signals |
35#[derive(Debug)]
36pub struct ClientInit {
37 /// Version of the client
38 pub client_version: String,
39 /// Build date of the client
40 pub client_date: String,
41 /// supported features as bitflags
42 pub client_features: u32,
43 /// List of supported extended features
44 pub feature_list: StringList,
45}
46
47impl HandshakeSerialize for ClientInit {
48 fn serialize(&self) -> Result<Vec<u8>, Error> {
49 let mut values: VariantMap = VariantMap::with_capacity(5);
50 values.insert(
51 "MsgType".to_string(),
52 Variant::String("ClientInit".to_string()),
53 );
54 values.insert(
55 "ClientVersion".to_string(),
56 Variant::String(self.client_version.clone()),
57 );
58 values.insert(
59 "ClientDate".to_string(),
60 Variant::String(self.client_date.clone()),
61 );
62 values.insert("Features".to_string(), Variant::u32(self.client_features));
63 values.insert(
64 "FeatureList".to_string(),
65 Variant::StringList(self.feature_list.clone()),
66 );
67 return HandshakeSerialize::serialize(&values);
68 }
69}
70
71impl HandshakeDeserialize for ClientInit {
72 fn parse(b: &[u8]) -> Result<(usize, Self), Error> {
73 let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?;
74
75 let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8);
76
77 if msgtype == "ClientInit" {
78 return Ok((
79 len,
80 Self {
81 client_version: match_variant!(values["ClientVersion"], Variant::String),
82 client_date: match_variant!(values["ClientDate"], Variant::String),
83 feature_list: match_variant!(values["FeatureList"], Variant::StringList),
84 client_features: match_variant!(values["Features"], Variant::u32),
85 },
86 ));
87 } else {
88 bail!(ProtocolError::WrongMsgType);
89 }
90 }
91}