imitating the coax structure a little, adding the protos api + part of the JSON API definiton
This commit is contained in:
10
Cargo.toml
10
Cargo.toml
@@ -7,8 +7,18 @@ license = "MIT"
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.50"
|
bindgen = "0.50"
|
||||||
|
protoc-rust = "2.8.1"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["dylib"]
|
crate-type = ["dylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
diesel = { version = "1.4.2", features=["sqlite"] }
|
||||||
|
cryptobox = { git = "https://github.com/wireapp/cryptobox.git", branch = "develop" }
|
||||||
|
proteus = { git = "https://github.com/wireapp/proteus", branch = "develop" }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
protobuf = "2.8.1"
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
uuid = { version = "0.7", features = ["serde", "v4"] }
|
||||||
|
base64 = "0.10.1"
|
||||||
|
|||||||
18
build.rs
18
build.rs
@@ -1,11 +1,12 @@
|
|||||||
extern crate bindgen;
|
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
|
use protoc_rust::Customize;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
// C bindings
|
||||||
let server_rec = "
|
let server_rec = "
|
||||||
typedef struct _WireServerRec {
|
typedef struct _WireServerRec {
|
||||||
int x;
|
int x;
|
||||||
@@ -17,9 +18,9 @@ typedef struct _WireServerRec {
|
|||||||
|
|
||||||
|
|
||||||
// Generate bindings for headers.h
|
// Generate bindings for headers.h
|
||||||
|
eprintln!("Generating C bindings");
|
||||||
let mut irssi_path = "-I".to_string();
|
let mut irssi_path = "-I".to_string();
|
||||||
irssi_path.push_str(env::var("IRSSI_INCLUDE").unwrap().as_str());
|
irssi_path.push_str(env::var("IRSSI_INCLUDE").unwrap().as_str());
|
||||||
println!("I AM IRSSI PATH: {}", irssi_path);
|
|
||||||
let bindings = bindgen::Builder::default()
|
let bindings = bindgen::Builder::default()
|
||||||
.header("headers.h")
|
.header("headers.h")
|
||||||
.clang_arg("-I/usr/include/glib-2.0/")
|
.clang_arg("-I/usr/include/glib-2.0/")
|
||||||
@@ -32,4 +33,15 @@ typedef struct _WireServerRec {
|
|||||||
bindings
|
bindings
|
||||||
.write_to_file(out_path.join("bindings.rs"))
|
.write_to_file(out_path.join("bindings.rs"))
|
||||||
.expect("Couldn't write bindings!");
|
.expect("Couldn't write bindings!");
|
||||||
|
|
||||||
|
eprintln!("Generating protobuf code");
|
||||||
|
// Protobuffer code generation
|
||||||
|
protoc_rust::run(protoc_rust::Args {
|
||||||
|
out_dir: "src/net/protos",
|
||||||
|
input: &["wire-api.proto"],
|
||||||
|
includes: &[],
|
||||||
|
customize: Customize {
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
}).expect("Couln't generate code from protobuffers for wire api");
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/irssi/mod.rs
Normal file
1
src/irssi/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod bindings;
|
||||||
19
src/lib.rs
19
src/lib.rs
@@ -1,8 +1,13 @@
|
|||||||
use std::os::raw::{c_char, c_int};
|
use std::os::raw::c_int;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
mod bindings;
|
use std::thread;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use bindings::*;
|
mod irssi;
|
||||||
|
mod net;
|
||||||
|
mod storage;
|
||||||
|
|
||||||
|
use irssi::bindings::*;
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn wire_core_abicheck(version: *mut c_int) {
|
pub extern fn wire_core_abicheck(version: *mut c_int) {
|
||||||
@@ -17,6 +22,14 @@ pub extern fn wire_core_init() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
module_register_full(CString::new("wire").unwrap().as_ptr(), CString::new("core").unwrap().as_ptr(), CString::new("wire/core").unwrap().as_ptr());
|
module_register_full(CString::new("wire").unwrap().as_ptr(), CString::new("core").unwrap().as_ptr(), CString::new("wire/core").unwrap().as_ptr());
|
||||||
}
|
}
|
||||||
|
thread::spawn(|| {
|
||||||
|
let mut i = 0;
|
||||||
|
loop {
|
||||||
|
thread::sleep(Duration::from_secs(10));
|
||||||
|
println!("{} iteration", i);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
2
src/net/mod.rs
Normal file
2
src/net/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub(crate) mod protos;
|
||||||
|
pub(crate) mod model;
|
||||||
97
src/net/model/client.rs
Normal file
97
src/net/model/client.rs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::net::model::prekeys::{PreKey, LastPreKey};
|
||||||
|
// Client
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct Client {
|
||||||
|
pub id: String,
|
||||||
|
pub class: Option<Class>,
|
||||||
|
pub time: Option<DateTime<Utc>>,
|
||||||
|
pub r#type: Option<ClientType>,
|
||||||
|
pub cookie_label: Option<String>,
|
||||||
|
pub label: Option<String>,
|
||||||
|
pub model: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
|
||||||
|
pub enum Class {
|
||||||
|
phone,
|
||||||
|
tablet,
|
||||||
|
desktop
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
|
||||||
|
pub enum ClientType {
|
||||||
|
permanent,
|
||||||
|
temporary
|
||||||
|
}
|
||||||
|
|
||||||
|
// PubClientView
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct PubClientView {
|
||||||
|
pub id: String,
|
||||||
|
pub class: Class
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignalingKeys
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct SignalingKeys {
|
||||||
|
#[serde(serialize_with = "b64_encode", deserialize_with = "b64_decode")]
|
||||||
|
pub enc: Vec<u8>,
|
||||||
|
#[serde(serialize_with = "b64_encode", deserialize_with = "b64_decode")]
|
||||||
|
pub mac: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b64_encode<'a, S>(bytes: &'a Vec<u8>, serialzer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
serialzer.serialize_str(&base64::encode(&bytes))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b64_decode<'de, D>(deserialzer: D) -> Result<Vec<u8>, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
use serde::de::Error;
|
||||||
|
|
||||||
|
String::deserialize(deserialzer)
|
||||||
|
.and_then(|string|
|
||||||
|
base64::decode(&string)
|
||||||
|
.map_err(|e| Error::custom(e.to_string()))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct User2Clients {
|
||||||
|
pub value: HashMap<Uuid, HashSet<String>>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct ClientMismatch {
|
||||||
|
pub time: DateTime<Utc>,
|
||||||
|
pub redundant: User2Clients,
|
||||||
|
pub missing: User2Clients,
|
||||||
|
pub deleted: User2Clients
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct RegisterParams{
|
||||||
|
pub prekeys: Vec<PreKey>,
|
||||||
|
pub last_prekey: LastPreKey,
|
||||||
|
pub sig_keys: SignalingKeys,
|
||||||
|
pub ctype: ClientType,
|
||||||
|
pub class: Class,
|
||||||
|
pub cookie_label: String,
|
||||||
|
pub label: Option<String>,
|
||||||
|
pub password: Option<String>,
|
||||||
|
pub model: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
struct DeleteParams {
|
||||||
|
password: String
|
||||||
|
}
|
||||||
0
src/net/model/events.rs
Normal file
0
src/net/model/events.rs
Normal file
0
src/net/model/messages.rs
Normal file
0
src/net/model/messages.rs
Normal file
2
src/net/model/mod.rs
Normal file
2
src/net/model/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod client;
|
||||||
|
pub mod prekeys;
|
||||||
28
src/net/model/prekeys.rs
Normal file
28
src/net/model/prekeys.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use proteus::keys::PreKeyBundle;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct PreKeyMap {
|
||||||
|
pub value: HashMap<Uuid, HashMap<String, Option<PreKey>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct PreKey {
|
||||||
|
pub key: PreKeyBundle
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct LastPreKey(PreKey);
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct ClientPreKey {
|
||||||
|
pub id: String,
|
||||||
|
pub key: PreKey
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct ClientPreKeys(Vec<ClientPreKey>);
|
||||||
0
src/net/model/token.rs
Normal file
0
src/net/model/token.rs
Normal file
0
src/net/model/user.rs
Normal file
0
src/net/model/user.rs
Normal file
1
src/net/protos/mod.rs
Normal file
1
src/net/protos/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod wire_api;
|
||||||
10758
src/net/protos/wire_api.rs
Normal file
10758
src/net/protos/wire_api.rs
Normal file
File diff suppressed because it is too large
Load Diff
0
src/storage/mod.rs
Normal file
0
src/storage/mod.rs
Normal file
269
wire-api.proto
Normal file
269
wire-api.proto
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
// syntax = "proto2";
|
||||||
|
option java_package = "com.waz.model";
|
||||||
|
|
||||||
|
message GenericMessage {
|
||||||
|
required string message_id = 1; // client generated random id, preferably UUID
|
||||||
|
oneof content {
|
||||||
|
Text text = 2;
|
||||||
|
ImageAsset image = 3; // deprecated in favour of Asset
|
||||||
|
Knock knock = 4;
|
||||||
|
LastRead lastRead = 6;
|
||||||
|
Cleared cleared = 7;
|
||||||
|
External external = 8;
|
||||||
|
ClientAction clientAction = 9;
|
||||||
|
Calling calling = 10;
|
||||||
|
Asset asset = 11;
|
||||||
|
MessageHide hidden = 12;
|
||||||
|
Location location = 13;
|
||||||
|
MessageDelete deleted = 14;
|
||||||
|
MessageEdit edited = 15;
|
||||||
|
Confirmation confirmation = 16;
|
||||||
|
Reaction reaction = 17;
|
||||||
|
Ephemeral ephemeral = 18;
|
||||||
|
Availability availability = 19;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Availability {
|
||||||
|
enum Type {
|
||||||
|
NONE = 0;
|
||||||
|
AVAILABLE = 1;
|
||||||
|
AWAY = 2;
|
||||||
|
BUSY = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
required Type type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Ephemeral {
|
||||||
|
required int64 expire_after_millis = 1;
|
||||||
|
oneof content {
|
||||||
|
Text text = 2;
|
||||||
|
ImageAsset image = 3; // deprecated in favour of Asset
|
||||||
|
Knock knock = 4;
|
||||||
|
Asset asset = 5;
|
||||||
|
Location location = 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Text {
|
||||||
|
required string content = 1;
|
||||||
|
// reserved 2; // reserved keyword is not available in older protoc versions
|
||||||
|
repeated LinkPreview link_preview = 3;
|
||||||
|
repeated Mention mentions = 4;
|
||||||
|
optional Quote quote = 5; // if this Text is part of a MessageEdit, this field is ignored
|
||||||
|
optional bool expects_read_confirmation = 6 [default = false]; // whether the sender is expecting to receive a read confirmation
|
||||||
|
optional LegalHoldStatus legal_hold_status = 7 [default = UNKNOWN]; // whether this message was sent to legal hold
|
||||||
|
}
|
||||||
|
|
||||||
|
message Knock {
|
||||||
|
required bool hot_knock = 1 [default = false];
|
||||||
|
optional bool expects_read_confirmation = 2 [default = false]; // whether the sender is expecting to receive a read confirmation
|
||||||
|
optional LegalHoldStatus legal_hold_status = 3 [default = UNKNOWN]; // whether this message was sent to legal hold
|
||||||
|
}
|
||||||
|
|
||||||
|
message LinkPreview {
|
||||||
|
required string url = 1;
|
||||||
|
required int32 url_offset = 2; // url offset from beginning of text message
|
||||||
|
|
||||||
|
oneof preview {
|
||||||
|
Article article = 3; // deprecated - use meta_data
|
||||||
|
}
|
||||||
|
|
||||||
|
optional string permanent_url = 5;
|
||||||
|
optional string title = 6;
|
||||||
|
optional string summary = 7;
|
||||||
|
optional Asset image = 8;
|
||||||
|
|
||||||
|
oneof meta_data {
|
||||||
|
Tweet tweet = 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Tweet {
|
||||||
|
optional string author = 1;
|
||||||
|
optional string username = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// deprecated - use the additional fields in LinkPreview
|
||||||
|
message Article {
|
||||||
|
required string permanent_url = 1;
|
||||||
|
optional string title = 2;
|
||||||
|
optional string summary = 3;
|
||||||
|
optional Asset image = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Mention {
|
||||||
|
required int32 start = 1; // offset from beginning of the message counting in utf16 characters
|
||||||
|
required int32 length = 2;
|
||||||
|
oneof mention_type {
|
||||||
|
string user_id = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message LastRead {
|
||||||
|
required string conversation_id = 1;
|
||||||
|
required int64 last_read_timestamp = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Cleared {
|
||||||
|
required string conversation_id = 1;
|
||||||
|
required int64 cleared_timestamp = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageHide {
|
||||||
|
required string conversation_id = 1;
|
||||||
|
required string message_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageDelete {
|
||||||
|
required string message_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MessageEdit {
|
||||||
|
required string replacing_message_id = 1;
|
||||||
|
oneof content {
|
||||||
|
Text text = 2;
|
||||||
|
// Reply can also be edited, but the edit will only affect the Text part
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Quote {
|
||||||
|
required string quoted_message_id = 1;
|
||||||
|
optional bytes quoted_message_sha256 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Confirmation {
|
||||||
|
enum Type {
|
||||||
|
DELIVERED = 0;
|
||||||
|
READ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
required Type type = 2;
|
||||||
|
required string first_message_id = 1;
|
||||||
|
repeated string more_message_ids = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Location {
|
||||||
|
required float longitude = 1;
|
||||||
|
required float latitude = 2;
|
||||||
|
optional string name = 3; // location description/name
|
||||||
|
optional int32 zoom = 4; // google maps zoom level (check maps api documentation)
|
||||||
|
optional bool expects_read_confirmation = 5 [default = false]; // whether the sender is expecting to receive a read confirmation
|
||||||
|
optional LegalHoldStatus legal_hold_status = 6 [default = UNKNOWN]; // whether this message was sent to legal hold
|
||||||
|
}
|
||||||
|
|
||||||
|
// deprecated in favour of Asset.Original.ImageMetaData
|
||||||
|
message ImageAsset {
|
||||||
|
required string tag = 1;
|
||||||
|
required int32 width = 2;
|
||||||
|
required int32 height = 3;
|
||||||
|
required int32 original_width = 4;
|
||||||
|
required int32 original_height = 5;
|
||||||
|
required string mime_type = 6;
|
||||||
|
required int32 size = 7;
|
||||||
|
optional bytes otr_key = 8;
|
||||||
|
optional bytes mac_key = 9; // deprecated - use sha256
|
||||||
|
optional bytes mac = 10; // deprecated - use sha256
|
||||||
|
optional bytes sha256 = 11; // sha256 of ciphertext
|
||||||
|
}
|
||||||
|
|
||||||
|
message Asset {
|
||||||
|
message Original {
|
||||||
|
required string mime_type = 1;
|
||||||
|
required uint64 size = 2;
|
||||||
|
optional string name = 3;
|
||||||
|
oneof meta_data {
|
||||||
|
ImageMetaData image = 4;
|
||||||
|
VideoMetaData video = 5;
|
||||||
|
AudioMetaData audio = 6;
|
||||||
|
}
|
||||||
|
optional string source = 7; // link to source e.g. http://giphy.com/234245
|
||||||
|
optional string caption = 8; // caption of the asset, e.g. "dog" for a Giphy "dog" search result
|
||||||
|
}
|
||||||
|
|
||||||
|
message Preview {
|
||||||
|
required string mime_type = 1;
|
||||||
|
required uint64 size = 2;
|
||||||
|
optional RemoteData remote = 3;
|
||||||
|
oneof meta_data {
|
||||||
|
ImageMetaData image = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ImageMetaData {
|
||||||
|
required int32 width = 1;
|
||||||
|
required int32 height = 2;
|
||||||
|
optional string tag = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VideoMetaData {
|
||||||
|
optional int32 width = 1;
|
||||||
|
optional int32 height = 2;
|
||||||
|
optional uint64 duration_in_millis = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AudioMetaData {
|
||||||
|
optional uint64 duration_in_millis = 1;
|
||||||
|
// repeated float normalized_loudness = 2 [packed=true]; // deprecated - Switched to bytes instead
|
||||||
|
optional bytes normalized_loudness = 3; // each byte represent one loudness value as a byte (char) value.
|
||||||
|
// e.g. a 100-bytes field here represents 100 loudness values.
|
||||||
|
// Values are in chronological order and range from 0 to 255.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NotUploaded {
|
||||||
|
CANCELLED = 0;
|
||||||
|
FAILED = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RemoteData {
|
||||||
|
required bytes otr_key = 1;
|
||||||
|
required bytes sha256 = 2; // obsolete but required for backward compatibility
|
||||||
|
optional string asset_id = 3;
|
||||||
|
// optional bytes asset_token = 4; // deprecated - changed type to string
|
||||||
|
optional string asset_token = 5;
|
||||||
|
optional EncryptionAlgorithm encryption = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional Original original = 1;
|
||||||
|
// optional Preview preview = 2; // deprecated - preview was completely replaced
|
||||||
|
oneof status {
|
||||||
|
NotUploaded not_uploaded = 3;
|
||||||
|
RemoteData uploaded = 4;
|
||||||
|
}
|
||||||
|
optional Preview preview = 5;
|
||||||
|
optional bool expects_read_confirmation = 6 [default = false]; // whether the sender is expecting to receive a read confirmation
|
||||||
|
optional LegalHoldStatus legal_hold_status = 7 [default = UNKNOWN]; // whether this message was sent to legal hold
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actual message is encrypted with AES and sent as additional data
|
||||||
|
message External {
|
||||||
|
required bytes otr_key = 1;
|
||||||
|
optional bytes sha256 = 2; // sha256 of ciphertext, obsolete but required for backward compatibility
|
||||||
|
optional EncryptionAlgorithm encryption = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Reaction {
|
||||||
|
optional string emoji = 1; // some emoji reaction or the empty string to remove previous reaction(s)
|
||||||
|
required string message_id = 2;
|
||||||
|
optional LegalHoldStatus legal_hold_status = 3 [default = UNKNOWN]; // whether this message was sent to legal hold
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ClientAction {
|
||||||
|
RESET_SESSION = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Calling {
|
||||||
|
required string content = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EncryptionAlgorithm {
|
||||||
|
AES_CBC = 0;
|
||||||
|
AES_GCM = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LegalHoldStatus {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
DISABLED = 1;
|
||||||
|
ENABLED = 2;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user