687 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Protocol Buffer
		
	
	
	
	
	
			
		
		
	
	
			687 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Protocol Buffer
		
	
	
	
	
	
| 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;
 | |
|     EncodedVideoFrames vp8s = 12;
 | |
|     EncodedVideoFrames av1s = 13;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 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;
 | |
|   bool cursor_embedded = 7;
 | |
|   Resolution original_resolution = 8;
 | |
| }
 | |
| 
 | |
| message PortForward {
 | |
|   string host = 1;
 | |
|   int32 port = 2;
 | |
| }
 | |
| 
 | |
| message FileTransfer {
 | |
|   string dir = 1;
 | |
|   bool show_hidden = 2;
 | |
| }
 | |
| 
 | |
| message OSLogin {
 | |
|   string username = 1;
 | |
|   string password = 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;
 | |
|   OSLogin os_login = 12;
 | |
| }
 | |
| 
 | |
| message ChatMessage { string text = 1; }
 | |
| 
 | |
| message Features {
 | |
|   bool privacy_mode = 1;
 | |
| }
 | |
| 
 | |
| message SupportedEncoding {
 | |
|   bool h264 = 1;
 | |
|   bool h265 = 2;
 | |
|   bool vp8 = 3;
 | |
|   bool av1 = 4;
 | |
| }
 | |
| 
 | |
| 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;
 | |
|   SupportedResolutions resolutions = 11;
 | |
|   // Use JSON's key-value format which is friendly for peer to handle.
 | |
|   string platform_additions = 12;
 | |
| }
 | |
| 
 | |
| 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;
 | |
|     // position key code. win: scancode, linux: key code, macos: key code
 | |
|     uint32 chr = 4;
 | |
|     uint32 unicode = 5;
 | |
|     string seq = 6;
 | |
|     // high word. virtual keycode
 | |
|     // low word. unicode
 | |
|     uint32 win2win_hotkey = 7;
 | |
|   }
 | |
|   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;
 | |
|   bool is_identical = 6;
 | |
| }
 | |
| 
 | |
| 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 {
 | |
| }
 | |
| 
 | |
| message CliprdrFormat {
 | |
|   int32 id = 2;
 | |
|   string format = 3;
 | |
| }
 | |
| 
 | |
| message CliprdrServerFormatList {
 | |
|   repeated CliprdrFormat formats = 2;
 | |
| }
 | |
| 
 | |
| message CliprdrServerFormatListResponse {
 | |
|   int32 msg_flags = 2;
 | |
| }
 | |
| 
 | |
| message CliprdrServerFormatDataRequest {
 | |
|   int32 requested_format_id = 2;
 | |
| }
 | |
| 
 | |
| message CliprdrServerFormatDataResponse {
 | |
|   int32 msg_flags = 2;
 | |
|   bytes format_data = 3;
 | |
| }
 | |
| 
 | |
| message CliprdrFileContentsRequest {
 | |
|   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 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 Resolution {
 | |
|   int32 width = 1;
 | |
|   int32 height = 2;
 | |
| }
 | |
| 
 | |
| message SupportedResolutions { repeated Resolution resolutions = 1; }
 | |
| 
 | |
| message SwitchDisplay {
 | |
|   int32 display = 1;
 | |
|   sint32 x = 2;
 | |
|   sint32 y = 3;
 | |
|   int32 width = 4;
 | |
|   int32 height = 5;
 | |
|   bool cursor_embedded = 6;
 | |
|   SupportedResolutions resolutions = 7;
 | |
|   // Do not care about the origin point for now.
 | |
|   Resolution original_resolution = 8;
 | |
| }
 | |
| 
 | |
| message PermissionInfo {
 | |
|   enum Permission {
 | |
|     Keyboard = 0;
 | |
|     Clipboard = 2;
 | |
|     Audio = 3;
 | |
|     File = 4;
 | |
|     Restart = 5;
 | |
|     Recording = 6;
 | |
|   }
 | |
| 
 | |
|   Permission permission = 1;
 | |
|   bool enabled = 2;
 | |
| }
 | |
| 
 | |
| enum ImageQuality {
 | |
|   NotSet = 0;
 | |
|   Low = 2;
 | |
|   Balanced = 3;
 | |
|   Best = 4;
 | |
| }
 | |
| 
 | |
| message SupportedDecoding {
 | |
|   enum PreferCodec {
 | |
|     Auto = 0;
 | |
|     VP9 = 1;
 | |
|     H264 = 2;
 | |
|     H265 = 3;
 | |
|     VP8 = 4;
 | |
|     AV1 = 5;
 | |
|   }
 | |
| 
 | |
|   int32 ability_vp9 = 1;
 | |
|   int32 ability_h264 = 2;
 | |
|   int32 ability_h265 = 3;
 | |
|   PreferCodec prefer = 4;
 | |
|   int32 ability_vp8 = 5;
 | |
|   int32 ability_av1 = 6;
 | |
| }
 | |
| 
 | |
| 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;
 | |
|   SupportedDecoding supported_decoding = 10;
 | |
|   int32 custom_fps = 11;
 | |
|   BoolOption disable_keyboard = 12;
 | |
|   Resolution custom_resolution = 13;
 | |
| }
 | |
| 
 | |
| 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; 
 | |
| }
 | |
| 
 | |
| // Notify peer to show message box.
 | |
| message MessageBox {
 | |
|   // Message type. Refer to flutter/lib/common.dart/msgBox().
 | |
|   string msgtype = 1;
 | |
|   string title = 2;
 | |
|   // English
 | |
|   string text = 3;
 | |
|   // If not empty, msgbox provides a button to following the link.
 | |
|   // The link here can't be directly http url.
 | |
|   // It must be the key of http url configed in peer side or "rustdesk://*" (jump in app).
 | |
|   string link = 4;
 | |
| }
 | |
| 
 | |
| 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 ElevationRequestWithLogon {
 | |
|   string username = 1;
 | |
|   string password = 2;
 | |
| }
 | |
| 
 | |
| message ElevationRequest {
 | |
|   oneof union {
 | |
|     bool direct = 1;
 | |
|     ElevationRequestWithLogon logon = 2;
 | |
|   }
 | |
| }
 | |
| 
 | |
| message SwitchSidesRequest {
 | |
|   bytes uuid = 1;
 | |
| }
 | |
| 
 | |
| message SwitchSidesResponse {
 | |
|   bytes uuid = 1;
 | |
|   LoginRequest lr = 2;
 | |
| }
 | |
| 
 | |
| message SwitchBack {}
 | |
| 
 | |
| message PluginRequest {
 | |
|   string id = 1;
 | |
|   bytes content = 2;
 | |
| }
 | |
| 
 | |
| message PluginFailure {
 | |
|   string id = 1;
 | |
|   string name = 2;
 | |
|   string msg = 3;
 | |
| }
 | |
| 
 | |
| 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;
 | |
|     bool uac = 15;
 | |
|     bool foreground_window_elevated = 16;
 | |
|     bool stop_service = 17;
 | |
|     ElevationRequest elevation_request = 18;
 | |
|     string elevation_response = 19;
 | |
|     bool portable_service_running = 20;
 | |
|     SwitchSidesRequest switch_sides_request = 21;
 | |
|     SwitchBack switch_back = 22;
 | |
|     Resolution change_resolution = 24;
 | |
|     PluginRequest plugin_request = 25;
 | |
|     PluginFailure plugin_failure = 26;
 | |
|   }
 | |
| }
 | |
| 
 | |
| message VoiceCallRequest {
 | |
|   int64 req_timestamp = 1;
 | |
|   // Indicates whether the request is a connect action or a disconnect action.
 | |
|   bool is_connect = 2;
 | |
| }
 | |
| 
 | |
| message VoiceCallResponse {
 | |
|   bool accepted = 1;
 | |
|   int64 req_timestamp = 2; // Should copy from [VoiceCallRequest::req_timestamp].
 | |
|   int64 ack_timestamp = 3;
 | |
| }
 | |
| 
 | |
| 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;
 | |
|     MessageBox message_box = 21;
 | |
|     SwitchSidesResponse switch_sides_response = 22;
 | |
|     VoiceCallRequest voice_call_request = 23;
 | |
|     VoiceCallResponse voice_call_response = 24;
 | |
|     PeerInfo peer_info = 25;
 | |
|   }
 | |
| }
 |