syntax = "proto3";
package hbb;

message EncodedVideoFrame {
  bytes data = 1;
  bool key = 2;
  int64 pts = 3;
}

message EncodedVideoFrames { repeated EncodedVideoFrame frames = 1; }

message RGB { bool compress = 1; }

// planes data send directly in binary for better use arraybuffer on web
message YUV {
  bool compress = 1;
  int32 stride = 2;
}

message VideoFrame {
  oneof union {
    EncodedVideoFrames vp9s = 6;
    RGB rgb = 7;
    YUV yuv = 8;
    EncodedVideoFrames h264s = 10;
    EncodedVideoFrames h265s = 11;
  }
  int64 timestamp = 9;
}

message IdPk {
  string id = 1;
  bytes pk = 2;
}

message DisplayInfo {
  sint32 x = 1;
  sint32 y = 2;
  int32 width = 3;
  int32 height = 4;
  string name = 5;
  bool online = 6;
}

message PortForward {
  string host = 1;
  int32 port = 2;
}

message FileTransfer {
  string dir = 1;
  bool show_hidden = 2;
}

message LoginRequest {
  string username = 1;
  bytes password = 2;
  string my_id = 4;
  string my_name = 5;
  OptionMessage option = 6;
  oneof union {
    FileTransfer file_transfer = 7;
    PortForward port_forward = 8;
  }
  bool video_ack_required = 9;
  uint64 session_id = 10;
  string version = 11;
}

message ChatMessage { string text = 1; }

message Features {
  bool privacy_mode = 1;
}

message SupportedEncoding {
  bool h264 = 1;
  bool h265 = 2;
}

message PeerInfo {
  string username = 1;
  string hostname = 2;
  string platform = 3;
  repeated DisplayInfo displays = 4;
  int32 current_display = 5;
  bool sas_enabled = 6;
  string version = 7;
  int32 conn_id = 8;
  Features features = 9;
  SupportedEncoding encoding = 10;
}

message LoginResponse {
  oneof union {
    string error = 1;
    PeerInfo peer_info = 2;
  }
}

message MouseEvent {
  int32 mask = 1;
  sint32 x = 2;
  sint32 y = 3;
  repeated ControlKey modifiers = 4;
}

enum KeyboardMode{
  Legacy = 0;
  Map = 1;
  Translate = 2;
  Auto = 3;
}

enum ControlKey {
  Unknown = 0;
  Alt = 1;
  Backspace = 2;
  CapsLock = 3;
  Control = 4;
  Delete = 5;
  DownArrow = 6;
  End = 7;
  Escape = 8;
  F1 = 9;
  F10 = 10;
  F11 = 11;
  F12 = 12;
  F2 = 13;
  F3 = 14;
  F4 = 15;
  F5 = 16;
  F6 = 17;
  F7 = 18;
  F8 = 19;
  F9 = 20;
  Home = 21;
  LeftArrow = 22;
  /// meta key (also known as "windows"; "super"; and "command")
  Meta = 23;
  /// option key on macOS (alt key on Linux and Windows)
  Option = 24; // deprecated, use Alt instead
  PageDown = 25;
  PageUp = 26;
  Return = 27;
  RightArrow = 28;
  Shift = 29;
  Space = 30;
  Tab = 31;
  UpArrow = 32;
  Numpad0 = 33;
  Numpad1 = 34;
  Numpad2 = 35;
  Numpad3 = 36;
  Numpad4 = 37;
  Numpad5 = 38;
  Numpad6 = 39;
  Numpad7 = 40;
  Numpad8 = 41;
  Numpad9 = 42;
  Cancel = 43;
  Clear = 44;
  Menu = 45; // deprecated, use Alt instead
  Pause = 46;
  Kana = 47;
  Hangul = 48;
  Junja = 49;
  Final = 50;
  Hanja = 51;
  Kanji = 52;
  Convert = 53;
  Select = 54;
  Print = 55;
  Execute = 56;
  Snapshot = 57;
  Insert = 58;
  Help = 59;
  Sleep = 60;
  Separator = 61;
  Scroll = 62;
  NumLock = 63;
  RWin = 64;
  Apps = 65;
  Multiply = 66;
  Add = 67;
  Subtract = 68;
  Decimal = 69;
  Divide = 70;
  Equals = 71;
  NumpadEnter = 72;
  RShift = 73;
  RControl = 74;
  RAlt = 75;
  CtrlAltDel = 100;
  LockScreen = 101;
}

message KeyEvent {
  bool down = 1;
  bool press = 2;
  oneof union {
    ControlKey control_key = 3;
    uint32 chr = 4;
    uint32 unicode = 5;
    string seq = 6;
  }
  repeated ControlKey modifiers = 8;
  KeyboardMode mode = 9;
}

message CursorData {
  uint64 id = 1;
  sint32 hotx = 2;
  sint32 hoty = 3;
  int32 width = 4;
  int32 height = 5;
  bytes colors = 6;
}

message CursorPosition {
  sint32 x = 1;
  sint32 y = 2;
}

message Hash {
  string salt = 1;
  string challenge = 2;
}

message Clipboard {
  bool compress = 1;
  bytes content = 2;
}

enum FileType {
  Dir = 0;
  DirLink = 2;
  DirDrive = 3;
  File = 4;
  FileLink = 5;
}

message FileEntry {
  FileType entry_type = 1;
  string name = 2;
  bool is_hidden = 3;
  uint64 size = 4;
  uint64 modified_time = 5;
}

message FileDirectory {
  int32 id = 1;
  string path = 2;
  repeated FileEntry entries = 3;
}

message ReadDir {
  string path = 1;
  bool include_hidden = 2;
}

message ReadAllFiles {
  int32 id = 1;
  string path = 2;
  bool include_hidden = 3;
}

message FileAction {
  oneof union {
    ReadDir read_dir = 1;
    FileTransferSendRequest send = 2;
    FileTransferReceiveRequest receive = 3;
    FileDirCreate create = 4;
    FileRemoveDir remove_dir = 5;
    FileRemoveFile remove_file = 6;
    ReadAllFiles all_files = 7;
    FileTransferCancel cancel = 8;
    FileTransferSendConfirmRequest send_confirm = 9;
  }
}

message FileTransferCancel { int32 id = 1; }

message FileResponse {
  oneof union {
    FileDirectory dir = 1;
    FileTransferBlock block = 2;
    FileTransferError error = 3;
    FileTransferDone done = 4;
    FileTransferDigest digest = 5;
  }
}

message FileTransferDigest {
  int32 id = 1;
  sint32 file_num = 2;
  uint64 last_modified = 3;
  uint64 file_size = 4;
  bool is_upload = 5;
}

message FileTransferBlock {
  int32 id = 1;
  sint32 file_num = 2;
  bytes data = 3;
  bool compressed = 4;
  uint32 blk_id = 5;
}

message FileTransferError {
  int32 id = 1;
  string error = 2;
  sint32 file_num = 3;
}

message FileTransferSendRequest {
  int32 id = 1;
  string path = 2;
  bool include_hidden = 3;
  int32 file_num = 4;
}

message FileTransferSendConfirmRequest {
  int32 id = 1;
  sint32 file_num = 2;
  oneof union {
    bool skip = 3;
    uint32 offset_blk = 4;
  }
}

message FileTransferDone {
  int32 id = 1;
  sint32 file_num = 2;
}

message FileTransferReceiveRequest {
  int32 id = 1;
  string path = 2; // path written to
  repeated FileEntry files = 3;
  int32 file_num = 4;
}

message FileRemoveDir {
  int32 id = 1;
  string path = 2;
  bool recursive = 3;
}

message FileRemoveFile {
  int32 id = 1;
  string path = 2;
  sint32 file_num = 3;
}

message FileDirCreate {
  int32 id = 1;
  string path = 2;
}

// main logic from freeRDP
message CliprdrMonitorReady {
  int32 conn_id = 1;
}

message CliprdrFormat {
  int32 conn_id = 1;
  int32 id = 2;
  string format = 3;
}

message CliprdrServerFormatList {
  int32 conn_id = 1;
  repeated CliprdrFormat formats = 2;
}

message CliprdrServerFormatListResponse {
  int32 conn_id = 1;
  int32 msg_flags = 2;
}

message CliprdrServerFormatDataRequest {
  int32 conn_id = 1;
  int32 requested_format_id = 2;
}

message CliprdrServerFormatDataResponse {
  int32 conn_id = 1;
  int32 msg_flags = 2;
  bytes format_data = 3;
}

message CliprdrFileContentsRequest {
  int32 conn_id = 1;
  int32 stream_id = 2;
  int32 list_index = 3;
  int32 dw_flags = 4;
  int32 n_position_low = 5;
  int32 n_position_high = 6;
  int32 cb_requested = 7;
  bool have_clip_data_id = 8;
  int32 clip_data_id = 9;
}

message CliprdrFileContentsResponse {
  int32 conn_id = 1;
  int32 msg_flags = 3;
  int32 stream_id = 4;
  bytes requested_data = 5;
}

message Cliprdr {
  oneof union {
    CliprdrMonitorReady ready = 1;
    CliprdrServerFormatList format_list = 2;
    CliprdrServerFormatListResponse format_list_response = 3;
    CliprdrServerFormatDataRequest format_data_request = 4;
    CliprdrServerFormatDataResponse format_data_response = 5;
    CliprdrFileContentsRequest file_contents_request = 6;
    CliprdrFileContentsResponse file_contents_response = 7;
  }
}

message SwitchDisplay {
  int32 display = 1;
  sint32 x = 2;
  sint32 y = 3;
  int32 width = 4;
  int32 height = 5;
}

message PermissionInfo {
  enum Permission {
    Keyboard = 0;
    Clipboard = 2;
    Audio = 3;
    File = 4;
    Restart = 5;
  }

  Permission permission = 1;
  bool enabled = 2;
}

enum ImageQuality {
  NotSet = 0;
  Low = 2;
  Balanced = 3;
  Best = 4;
}

message VideoCodecState {
  enum PerferCodec {
    Auto = 0;
    VPX = 1;
    H264 = 2;
    H265 = 3;
  }

  int32 score_vpx = 1;
  int32 score_h264 = 2;
  int32 score_h265 = 3;
  PerferCodec perfer = 4;
}

message OptionMessage {
  enum BoolOption {
    NotSet = 0;
    No = 1;
    Yes = 2;
  }
  ImageQuality image_quality = 1;
  BoolOption lock_after_session_end = 2;
  BoolOption show_remote_cursor = 3;
  BoolOption privacy_mode = 4;
  BoolOption block_input = 5;
  int32 custom_image_quality = 6;
  BoolOption disable_audio = 7;
  BoolOption disable_clipboard = 8;
  BoolOption enable_file_transfer = 9;
  VideoCodecState video_codec_state = 10;
}

message TestDelay {
  int64 time = 1;
  bool from_client = 2;
  uint32 last_delay = 3;
  uint32 target_bitrate = 4;
}

message PublicKey {
  bytes asymmetric_value = 1;
  bytes symmetric_value = 2;
}

message SignedId { bytes id = 1; }

message AudioFormat {
  uint32 sample_rate = 1;
  uint32 channels = 2;
}

message AudioFrame { 
  bytes data = 1; 
  int64 timestamp = 2;
}

message BackNotification {
  // no need to consider block input by someone else
  enum BlockInputState {
    BlkStateUnknown = 0;
    BlkOnSucceeded = 2;
    BlkOnFailed = 3;
    BlkOffSucceeded = 4;
    BlkOffFailed = 5;
  }
  enum PrivacyModeState {
    PrvStateUnknown = 0;
    // Privacy mode on by someone else
    PrvOnByOther = 2;
    // Privacy mode is not supported on the remote side
    PrvNotSupported = 3;
    // Privacy mode on by self
    PrvOnSucceeded = 4;
    // Privacy mode on by self, but denied
    PrvOnFailedDenied = 5;
    // Some plugins are not found
    PrvOnFailedPlugin = 6;
    // Privacy mode on by self, but failed
    PrvOnFailed = 7;
    // Privacy mode off by self
    PrvOffSucceeded = 8;
    // Ctrl + P
    PrvOffByPeer = 9;
    // Privacy mode off by self, but failed
    PrvOffFailed = 10;
    PrvOffUnknown = 11;
  }

  oneof union {
    PrivacyModeState privacy_mode_state = 1;
    BlockInputState block_input_state = 2;
  }
}

message Misc {
  oneof union {
    ChatMessage chat_message = 4;
    SwitchDisplay switch_display = 5;
    PermissionInfo permission_info = 6;
    OptionMessage option = 7;
    AudioFormat audio_format = 8;
    string close_reason = 9;
    bool refresh_video = 10;
    bool video_received = 12;
    BackNotification back_notification = 13;
    bool restart_remote_device = 14;
  }
}

message Message {
  oneof union {
    SignedId signed_id = 3;
    PublicKey public_key = 4;
    TestDelay test_delay = 5;
    VideoFrame video_frame = 6;
    LoginRequest login_request = 7;
    LoginResponse login_response = 8;
    Hash hash = 9;
    MouseEvent mouse_event = 10;
    AudioFrame audio_frame = 11;
    CursorData cursor_data = 12;
    CursorPosition cursor_position = 13;
    uint64 cursor_id = 14;
    KeyEvent key_event = 15;
    Clipboard clipboard = 16;
    FileAction file_action = 17;
    FileResponse file_response = 18;
    Misc misc = 19;
    Cliprdr cliprdr = 20;
  }
}
