From 80e36c9df834bc1c3c564949b2fda880af18dbf8 Mon Sep 17 00:00:00 2001 From: George Date: Tue, 5 May 2026 16:29:56 +0530 Subject: [PATCH] feat: --Added Auth for mumble server --- Mumble.proto | 639 +++++++++++++++++++++++++ Mumble_pb2.py | 115 +++++ __pycache__/Mumble_pb2.cpython-312.pyc | Bin 0 -> 10448 bytes experimental.py | 14 +- sniffer.py | 119 +++++ 5 files changed, 883 insertions(+), 4 deletions(-) create mode 100644 Mumble.proto create mode 100644 Mumble_pb2.py create mode 100644 __pycache__/Mumble_pb2.cpython-312.pyc create mode 100644 sniffer.py diff --git a/Mumble.proto b/Mumble.proto new file mode 100644 index 0000000..deb6c17 --- /dev/null +++ b/Mumble.proto @@ -0,0 +1,639 @@ +// Copyright The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +syntax = "proto2"; + +package MumbleProto; + +option optimize_for = SPEED; + +message Version { + // Legacy version number format. + optional uint32 version_v1 = 1; + // New version number format. + // Necessary since patch level may exceed 255. (See https://github.com/mumble-voip/mumble/issues/5827) + optional uint64 version_v2 = 5; + + // Client release name. + optional string release = 2; + // Client OS name. + optional string os = 3; + // Client OS version. + optional string os_version = 4; +} + +// Not used. Not even for tunneling UDP through TCP. +message UDPTunnel { + // Not used. + required bytes packet = 1; +} + +// Used by the client to send the authentication credentials to the server. +message Authenticate { + // UTF-8 encoded username. + optional string username = 1; + // Server or user password. + optional string password = 2; + // Additional access tokens for server ACL groups. + repeated string tokens = 3; + // A list of CELT bitstream version constants supported by the client. + repeated int32 celt_versions = 4; + optional bool opus = 5 [default = false]; + // 0 = REGULAR, 1 = BOT + optional int32 client_type = 6 [default = 0]; +} + +// Sent by the client to notify the server that the client is still alive. +// Server must reply to the packet with the same timestamp and its own +// good/late/lost/resync numbers. None of the fields is strictly required. +message Ping { + // Client timestamp. Server should not attempt to decode. + optional uint64 timestamp = 1; + // The amount of good packets received. + optional uint32 good = 2; + // The amount of late packets received. + optional uint32 late = 3; + // The amount of packets never received. + optional uint32 lost = 4; + // The amount of nonce resyncs. + optional uint32 resync = 5; + // The total amount of UDP packets received. + optional uint32 udp_packets = 6; + // The total amount of TCP packets received. + optional uint32 tcp_packets = 7; + // UDP ping average. + optional float udp_ping_avg = 8; + // UDP ping variance. + optional float udp_ping_var = 9; + // TCP ping average. + optional float tcp_ping_avg = 10; + // TCP ping variance. + optional float tcp_ping_var = 11; +} + +// Sent by the server when it rejects the user connection. +message Reject { + enum RejectType { + // The rejection reason is unknown (details should be available + // in Reject.reason). + None = 0; + // The client attempted to connect with an incompatible version. + WrongVersion = 1; + // The user name supplied by the client was invalid. + InvalidUsername = 2; + // The client attempted to authenticate as a user with a password but it + // was wrong. + WrongUserPW = 3; + // The client attempted to connect to a passworded server but the password + // was wrong. + WrongServerPW = 4; + // Supplied username is already in use. + UsernameInUse = 5; + // Server is currently full and cannot accept more users. + ServerFull = 6; + // The user did not provide a certificate but one is required. + NoCertificate = 7; + AuthenticatorFail = 8; + // The server is currently not accepting new connections + NoNewConnections = 9; + } + // Rejection type. + optional RejectType type = 1; + // Human readable rejection reason. + optional string reason = 2; +} + +// ServerSync message is sent by the server when it has authenticated the user +// and finished synchronizing the server state. +message ServerSync { + // The session of the current user. + optional uint32 session = 1; + // Maximum bandwidth that the user should use. + optional uint32 max_bandwidth = 2; + // Server welcome text. + optional string welcome_text = 3; + // Current user permissions in the root channel. + // Note: The permissions data type usually is uin32 (e.g. in PermissionQuery and PermissionDenied messages). Here + // it is uint64 because of an oversight in the past. Nonetheless it should never exceed the uin32 range. + // See also: https://github.com/mumble-voip/mumble/issues/5139 + optional uint64 permissions = 4; +} + +// Sent by the client when it wants a channel removed. Sent by the server when +// a channel has been removed and clients should be notified. +message ChannelRemove { + required uint32 channel_id = 1; +} + +// Used to communicate channel properties between the client and the server. +// Sent by the server during the login process or when channel properties are +// updated. Client may use this message to update said channel properties. +message ChannelState { + // Unique ID for the channel within the server. + optional uint32 channel_id = 1; + // channel_id of the parent channel. + optional uint32 parent = 2; + // UTF-8 encoded channel name. + optional string name = 3; + // A collection of channel id values of the linked channels. Absent during + // the first channel listing. + repeated uint32 links = 4; + // UTF-8 encoded channel description. Only if the description is less than + // 128 bytes + optional string description = 5; + // A collection of channel_id values that should be added to links. + repeated uint32 links_add = 6; + // A collection of channel_id values that should be removed from links. + repeated uint32 links_remove = 7; + // True if the channel is temporary. + optional bool temporary = 8 [default = false]; + // Position weight to tweak the channel position in the channel list. + optional int32 position = 9 [default = 0]; + // SHA1 hash of the description if the description is 128 bytes or more. + optional bytes description_hash = 10; + // Maximum number of users allowed in the channel. If this value is zero, + // the maximum number of users allowed in the channel is given by the + // server's "usersperchannel" setting. + optional uint32 max_users = 11; + // Whether this channel has enter restrictions (ACL denying ENTER) set + optional bool is_enter_restricted = 12; + // Whether the receiver of this msg is considered to be able to enter this channel + optional bool can_enter = 13; +} + +// Used to communicate user leaving or being kicked. May be sent by the client +// when it attempts to kick a user. Sent by the server when it informs the +// clients that a user is not present anymore. +message UserRemove { + // The user who is being kicked, identified by their session, not present + // when no one is being kicked. + required uint32 session = 1; + // The user who initiated the removal. Either the user who performs the kick + // or the user who is currently leaving. + optional uint32 actor = 2; + // Reason for the kick, stored as the ban reason if the user is banned. + optional string reason = 3; + // True if the user shall be banned, false if the user shall be kicked + optional bool ban = 4; + // True if the user shall be banned by certificate. + optional bool ban_certificate = 5; + // True if the user shall be banned by IP. + optional bool ban_ip = 6; +} + +// Sent by the server when it communicates new and changed users to client. +// First seen during login procedure. May be sent by the client when it wishes +// to alter its state. +message UserState { + message VolumeAdjustment { + optional uint32 listening_channel = 1; + optional float volume_adjustment = 2; + } + + // Unique user session ID of the user whose state this is, may change on + // reconnect. + optional uint32 session = 1; + // The session of the user who is updating this user. + optional uint32 actor = 2; + // User name, UTF-8 encoded. + optional string name = 3; + // Registered user ID if the user is registered. + optional uint32 user_id = 4; + // Channel on which the user is. + optional uint32 channel_id = 5; + // True if the user is muted by admin. + optional bool mute = 6; + // True if the user is deafened by admin. + optional bool deaf = 7; + // True if the user has been suppressed from talking by a reason other than + // being muted. + optional bool suppress = 8; + // True if the user has muted self. + optional bool self_mute = 9; + // True if the user has deafened self. + optional bool self_deaf = 10; + // User image if it is less than 128 bytes. + optional bytes texture = 11; + // The positional audio plugin identifier. + // Positional audio information is only sent to users who share + // identical plugin contexts. + // + // This value is not transmitted to clients. + optional bytes plugin_context = 12; + // The user's plugin-specific identity. + // This value is not transmitted to clients. + optional string plugin_identity = 13; + // User comment if it is less than 128 bytes. + optional string comment = 14; + // The hash of the user certificate. + optional string hash = 15; + // SHA1 hash of the user comment if it 128 bytes or more. + optional bytes comment_hash = 16; + // SHA1 hash of the user picture if it 128 bytes or more. + optional bytes texture_hash = 17; + // True if the user is a priority speaker. + optional bool priority_speaker = 18; + // True if the user is currently recording. + optional bool recording = 19; + // A list of temporary access tokens to be respected when processing this request. + repeated string temporary_access_tokens = 20; + // A list of channels the user wants to start listening to. + repeated uint32 listening_channel_add = 21; + // a list of channels the user does no longer want to listen to. + repeated uint32 listening_channel_remove = 22; + // A list of volume adjustments the user has applied to listeners + repeated VolumeAdjustment listening_volume_adjustment = 23; +} + +// Relays information on the bans. The client may send the BanList message to +// either modify the list of bans or query them from the server. The server +// sends this list only after a client queries for it. +message BanList { + message BanEntry { + // Banned IP address. + required bytes address = 1; + // The length of the subnet mask for the ban. + required uint32 mask = 2; + // User name for identification purposes (does not affect the ban). + optional string name = 3; + // The certificate hash of the banned user. + optional string hash = 4; + // Reason for the ban (does not affect the ban). + optional string reason = 5; + // Ban start time. + optional string start = 6; + // Ban duration in seconds. + optional uint32 duration = 7; + } + // List of ban entries currently in place. + repeated BanEntry bans = 1; + // True if the server should return the list, false if it should replace old + // ban list with the one provided. + optional bool query = 2 [default = false]; +} + +// Used to send and broadcast text messages. +message TextMessage { + // The message sender, identified by its session. + optional uint32 actor = 1; + // Target users for the message, identified by their session. + repeated uint32 session = 2; + // The channels to which the message is sent, identified by their + // channel_ids. + repeated uint32 channel_id = 3; + // The root channels when sending message recursively to several channels, + // identified by their channel_ids. + repeated uint32 tree_id = 4; + // The UTF-8 encoded message. May be HTML if the server allows. + required string message = 5; +} + +message PermissionDenied { + enum DenyType { + // Operation denied for other reason, see reason field. + Text = 0; + // Permissions were denied. + Permission = 1; + // Cannot modify SuperUser. + SuperUser = 2; + // Invalid channel name. + ChannelName = 3; + // Text message too long. + TextTooLong = 4; + // The flux capacitor was spelled wrong. + H9K = 5; + // Operation not permitted in temporary channel. + TemporaryChannel = 6; + // Operation requires certificate. + MissingCertificate = 7; + // Invalid username. + UserName = 8; + // Channel is full. + ChannelFull = 9; + // Channels are nested too deeply. + NestingLimit = 10; + // Maximum channel count reached. + ChannelCountLimit = 11; + // Amount of listener objects for this channel has been reached + ChannelListenerLimit = 12; + // Amount of listener proxies for the user has been reached + UserListenerLimit = 13; + } + // The denied permission when type is Permission. + optional uint32 permission = 1; + // channel_id for the channel where the permission was denied when type is + // Permission. + optional uint32 channel_id = 2; + // The user who was denied permissions, identified by session. + optional uint32 session = 3; + // Textual reason for the denial. + optional string reason = 4; + // Type of the denial. + optional DenyType type = 5; + // The name that is invalid when type is UserName. + optional string name = 6; +} + +message ACL { + message ChanGroup { + // Name of the channel group, UTF-8 encoded. + required string name = 1; + // True if the group has been inherited from the parent (Read only). + optional bool inherited = 2 [default = true]; + // True if the group members are inherited. + optional bool inherit = 3 [default = true]; + // True if the group can be inherited by sub channels. + optional bool inheritable = 4 [default = true]; + // Users explicitly included in this group, identified by user_id. + repeated uint32 add = 5; + // Users explicitly removed from this group in this channel if the group + // has been inherited, identified by user_id. + repeated uint32 remove = 6; + // Users inherited, identified by user_id. + repeated uint32 inherited_members = 7; + } + message ChanACL { + // True if this ACL applies to the current channel. + optional bool apply_here = 1 [default = true]; + // True if this ACL applies to the sub channels. + optional bool apply_subs = 2 [default = true]; + // True if the ACL has been inherited from the parent. + optional bool inherited = 3 [default = true]; + // ID of the user that is affected by this ACL. + optional uint32 user_id = 4; + // ID of the group that is affected by this ACL. + optional string group = 5; + // Bit flag field of the permissions granted by this ACL. + optional uint32 grant = 6; + // Bit flag field of the permissions denied by this ACL. + optional uint32 deny = 7; + } + // Channel ID of the channel this message affects. + required uint32 channel_id = 1; + // True if the channel inherits its parent's ACLs. + optional bool inherit_acls = 2 [default = true]; + // User group specifications. + repeated ChanGroup groups = 3; + // ACL specifications. + repeated ChanACL acls = 4; + // True if the message is a query for ACLs instead of setting them. + optional bool query = 5 [default = false]; +} + +// Client may use this message to refresh its registered user information. The +// client should fill the IDs or Names of the users it wants to refresh. The +// server fills the missing parts and sends the message back. +message QueryUsers { + // user_ids. + repeated uint32 ids = 1; + // User names in the same order as ids. + repeated string names = 2; +} + +// Used to initialize and resync the UDP encryption. Either side may request a +// resync by sending the message without any values filled. The resync is +// performed by sending the message with only the client or server nonce +// filled. +message CryptSetup { + // Encryption key. + optional bytes key = 1; + // Client nonce. + optional bytes client_nonce = 2; + // Server nonce. + optional bytes server_nonce = 3; +} + +// Used to add or remove custom context menu item on client-side. +message ContextActionModify { + enum Context { + // Action is applicable to the server. + Server = 0x01; + // Action can target a Channel. + Channel = 0x02; + // Action can target a User. + User = 0x04; + } + enum Operation { + Add = 0; + Remove = 1; + } + // The action identifier. Used later to initiate an action. + required string action = 1; + // The display name of the action. + optional string text = 2; + // Context bit flags defining where the action should be displayed. + // Flags can be OR-ed to combine different types. + optional uint32 context = 3; + // Choose either to add or to remove the context action. + // Note: This field only exists after Mumble 1.2.4-beta1 release. + // The message will be recognized as Add regardless of this field + // before said release. + optional Operation operation = 4; +} + +// Sent by the client when it wants to initiate a Context action. +message ContextAction { + // The target User for the action, identified by session. + optional uint32 session = 1; + // The target Channel for the action, identified by channel_id. + optional uint32 channel_id = 2; + // The action that should be executed. + required string action = 3; +} + +// Lists the registered users. +message UserList { + message User { + // Registered user ID. + required uint32 user_id = 1; + // Registered user name. + optional string name = 2; + optional string last_seen = 3; + optional uint32 last_channel = 4; + } + // A list of registered users. + repeated User users = 1; +} + +// Sent by the client when it wants to register or clear whisper targets. +// +// Note: The first available target ID is 1 as 0 is reserved for normal +// talking. Maximum target ID is 30. +message VoiceTarget { + message Target { + // Users that are included as targets. + repeated uint32 session = 1; + // Channel that is included as a target. + optional uint32 channel_id = 2; + // ACL group that is included as a target. + optional string group = 3; + // True if the voice should follow links from the specified channel. + optional bool links = 4 [default = false]; + // True if the voice should also be sent to children of the specific + // channel. + optional bool children = 5 [default = false]; + } + // Voice target ID. + optional uint32 id = 1; + // The receivers that this voice target includes. + repeated Target targets = 2; +} + +// Sent by the client when it wants permissions for a certain channel. Sent by +// the server when it replies to the query or wants the user to resync all +// channel permissions. +message PermissionQuery { + // channel_id of the channel for which the permissions are queried. + optional uint32 channel_id = 1; + // Channel permissions. + optional uint32 permissions = 2; + // True if the client should drop its current permission information for all + // channels. + optional bool flush = 3 [default = false]; +} + +// Sent by the server to notify the users of the version of the CELT codec they +// should use. This may change during the connection when new users join. +message CodecVersion { + // The version of the CELT Alpha codec. + required int32 alpha = 1; + // The version of the CELT Beta codec. + required int32 beta = 2; + // True if the user should prefer Alpha over Beta. + required bool prefer_alpha = 3 [default = true]; + optional bool opus = 4 [default = false]; +} + +// Used to communicate user stats between the server and clients. +message UserStats { + message Stats { + // The amount of good packets received. + optional uint32 good = 1; + // The amount of late packets received. + optional uint32 late = 2; + // The amount of packets never received. + optional uint32 lost = 3; + // The amount of nonce resyncs. + optional uint32 resync = 4; + } + + message RollingStats { + // Rolling packet statistics time window as defined on the server. + optional uint32 time_window = 1; + // Rolling packet statistics for packets received from the client. + optional Stats from_client = 2; + // Rolling packet statistics for packets sent by the server. + optional Stats from_server = 3; + } + + // User whose stats these are. + optional uint32 session = 1; + // True if the message contains only mutable stats (packets, ping). + optional bool stats_only = 2 [default = false]; + // Full user certificate chain of the user certificate in DER format. + repeated bytes certificates = 3; + // Packet statistics for packets received from the client. + optional Stats from_client = 4; + // Packet statistics for packets sent by the server. + optional Stats from_server = 5; + + // Amount of UDP packets sent. + optional uint32 udp_packets = 6; + // Amount of TCP packets sent. + optional uint32 tcp_packets = 7; + // UDP ping average. + optional float udp_ping_avg = 8; + // UDP ping variance. + optional float udp_ping_var = 9; + // TCP ping average. + optional float tcp_ping_avg = 10; + // TCP ping variance. + optional float tcp_ping_var = 11; + + // Client version. + optional Version version = 12; + // A list of CELT bitstream version constants supported by the client of this + // user. + repeated int32 celt_versions = 13; + // Client IP address. + optional bytes address = 14; + // Bandwidth used by this client. + optional uint32 bandwidth = 15; + // Connection duration. + optional uint32 onlinesecs = 16; + // Duration since last activity. + optional uint32 idlesecs = 17; + // True if the user has a strong certificate. + optional bool strong_certificate = 18 [default = false]; + optional bool opus = 19 [default = false]; + + // Rolling packet statistics + optional RollingStats rolling_stats = 20; +} + +// Used by the client to request binary data from the server. By default large +// comments or textures are not sent within standard messages but instead the +// hash is. If the client does not recognize the hash it may request the +// resource when it needs it. The client does so by sending a RequestBlob +// message with the correct fields filled with the user sessions or channel_ids +// it wants to receive. The server replies to this by sending a new +// UserState/ChannelState message with the resources filled even if they would +// normally be transmitted as hashes. +message RequestBlob { + // sessions of the requested UserState textures. + repeated uint32 session_texture = 1; + // sessions of the requested UserState comments. + repeated uint32 session_comment = 2; + // channel_ids of the requested ChannelState descriptions. + repeated uint32 channel_description = 3; +} + +// Sent by the server when it informs the clients on server configuration +// details. +message ServerConfig { + // The maximum bandwidth the clients should use. + optional uint32 max_bandwidth = 1; + // Server welcome text. + optional string welcome_text = 2; + // True if the server allows HTML. + optional bool allow_html = 3; + // Maximum text message length. + optional uint32 message_length = 4; + // Maximum image message length. + optional uint32 image_message_length = 5; + // The maximum number of users allowed on the server. + optional uint32 max_users = 6; + // Whether using Mumble's recording feature is allowed on the server + optional bool recording_allowed = 7; +} + +// Sent by the server to inform the clients of suggested client configuration +// specified by the server administrator. +message SuggestConfig { + // Suggested client version in the legacy format. + optional uint32 version_v1 = 1; + // Suggested client version in the new format. + // Necessary since patch level may exceed 255. (See https://github.com/mumble-voip/mumble/issues/5827) + optional uint64 version_v2 = 4; + + // True if the administrator suggests positional audio to be used on this + // server. + optional bool positional = 2; + // True if the administrator suggests push to talk to be used on this server. + optional bool push_to_talk = 3; +} + +// Used to send plugin messages between clients +message PluginDataTransmission { + // The session ID of the client this message was sent from + optional uint32 senderSession = 1; + // The session IDs of the clients that should receive this message + repeated uint32 receiverSessions = 2 [packed = true]; + // The data that is sent + optional bytes data = 3; + // The ID of the sent data. This will be used by plugins to check whether they will + // process it or not + optional string dataID = 4; +} diff --git a/Mumble_pb2.py b/Mumble_pb2.py new file mode 100644 index 0000000..bdcc223 --- /dev/null +++ b/Mumble_pb2.py @@ -0,0 +1,115 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# NO CHECKED-IN PROTOBUF GENCODE +# source: Mumble.proto +# Protobuf Python Version: 6.31.1 +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import runtime_version as _runtime_version +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import builder as _builder +_runtime_version.ValidateProtobufRuntimeVersion( + _runtime_version.Domain.PUBLIC, + 6, + 31, + 1, + '', + 'Mumble.proto' +) +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cMumble.proto\x12\x0bMumbleProto\"b\n\x07Version\x12\x12\n\nversion_v1\x18\x01 \x01(\r\x12\x12\n\nversion_v2\x18\x05 \x01(\x04\x12\x0f\n\x07release\x18\x02 \x01(\t\x12\n\n\x02os\x18\x03 \x01(\t\x12\x12\n\nos_version\x18\x04 \x01(\t\"\x1b\n\tUDPTunnel\x12\x0e\n\x06packet\x18\x01 \x02(\x0c\"\x86\x01\n\x0c\x41uthenticate\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\x12\x0e\n\x06tokens\x18\x03 \x03(\t\x12\x15\n\rcelt_versions\x18\x04 \x03(\x05\x12\x13\n\x04opus\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x16\n\x0b\x63lient_type\x18\x06 \x01(\x05:\x01\x30\"\xd5\x01\n\x04Ping\x12\x11\n\ttimestamp\x18\x01 \x01(\x04\x12\x0c\n\x04good\x18\x02 \x01(\r\x12\x0c\n\x04late\x18\x03 \x01(\r\x12\x0c\n\x04lost\x18\x04 \x01(\r\x12\x0e\n\x06resync\x18\x05 \x01(\r\x12\x13\n\x0budp_packets\x18\x06 \x01(\r\x12\x13\n\x0btcp_packets\x18\x07 \x01(\r\x12\x14\n\x0cudp_ping_avg\x18\x08 \x01(\x02\x12\x14\n\x0cudp_ping_var\x18\t \x01(\x02\x12\x14\n\x0ctcp_ping_avg\x18\n \x01(\x02\x12\x14\n\x0ctcp_ping_var\x18\x0b \x01(\x02\"\x8d\x02\n\x06Reject\x12,\n\x04type\x18\x01 \x01(\x0e\x32\x1e.MumbleProto.Reject.RejectType\x12\x0e\n\x06reason\x18\x02 \x01(\t\"\xc4\x01\n\nRejectType\x12\x08\n\x04None\x10\x00\x12\x10\n\x0cWrongVersion\x10\x01\x12\x13\n\x0fInvalidUsername\x10\x02\x12\x0f\n\x0bWrongUserPW\x10\x03\x12\x11\n\rWrongServerPW\x10\x04\x12\x11\n\rUsernameInUse\x10\x05\x12\x0e\n\nServerFull\x10\x06\x12\x11\n\rNoCertificate\x10\x07\x12\x15\n\x11\x41uthenticatorFail\x10\x08\x12\x14\n\x10NoNewConnections\x10\t\"_\n\nServerSync\x12\x0f\n\x07session\x18\x01 \x01(\r\x12\x15\n\rmax_bandwidth\x18\x02 \x01(\r\x12\x14\n\x0cwelcome_text\x18\x03 \x01(\t\x12\x13\n\x0bpermissions\x18\x04 \x01(\x04\"#\n\rChannelRemove\x12\x12\n\nchannel_id\x18\x01 \x02(\r\"\x99\x02\n\x0c\x43hannelState\x12\x12\n\nchannel_id\x18\x01 \x01(\r\x12\x0e\n\x06parent\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\r\n\x05links\x18\x04 \x03(\r\x12\x13\n\x0b\x64\x65scription\x18\x05 \x01(\t\x12\x11\n\tlinks_add\x18\x06 \x03(\r\x12\x14\n\x0clinks_remove\x18\x07 \x03(\r\x12\x18\n\ttemporary\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\x13\n\x08position\x18\t \x01(\x05:\x01\x30\x12\x18\n\x10\x64\x65scription_hash\x18\n \x01(\x0c\x12\x11\n\tmax_users\x18\x0b \x01(\r\x12\x1b\n\x13is_enter_restricted\x18\x0c \x01(\x08\x12\x11\n\tcan_enter\x18\r \x01(\x08\"r\n\nUserRemove\x12\x0f\n\x07session\x18\x01 \x02(\r\x12\r\n\x05\x61\x63tor\x18\x02 \x01(\r\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x0b\n\x03\x62\x61n\x18\x04 \x01(\x08\x12\x17\n\x0f\x62\x61n_certificate\x18\x05 \x01(\x08\x12\x0e\n\x06\x62\x61n_ip\x18\x06 \x01(\x08\"\xe6\x04\n\tUserState\x12\x0f\n\x07session\x18\x01 \x01(\r\x12\r\n\x05\x61\x63tor\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0f\n\x07user_id\x18\x04 \x01(\r\x12\x12\n\nchannel_id\x18\x05 \x01(\r\x12\x0c\n\x04mute\x18\x06 \x01(\x08\x12\x0c\n\x04\x64\x65\x61\x66\x18\x07 \x01(\x08\x12\x10\n\x08suppress\x18\x08 \x01(\x08\x12\x11\n\tself_mute\x18\t \x01(\x08\x12\x11\n\tself_deaf\x18\n \x01(\x08\x12\x0f\n\x07texture\x18\x0b \x01(\x0c\x12\x16\n\x0eplugin_context\x18\x0c \x01(\x0c\x12\x17\n\x0fplugin_identity\x18\r \x01(\t\x12\x0f\n\x07\x63omment\x18\x0e \x01(\t\x12\x0c\n\x04hash\x18\x0f \x01(\t\x12\x14\n\x0c\x63omment_hash\x18\x10 \x01(\x0c\x12\x14\n\x0ctexture_hash\x18\x11 \x01(\x0c\x12\x18\n\x10priority_speaker\x18\x12 \x01(\x08\x12\x11\n\trecording\x18\x13 \x01(\x08\x12\x1f\n\x17temporary_access_tokens\x18\x14 \x03(\t\x12\x1d\n\x15listening_channel_add\x18\x15 \x03(\r\x12 \n\x18listening_channel_remove\x18\x16 \x03(\r\x12L\n\x1blistening_volume_adjustment\x18\x17 \x03(\x0b\x32\'.MumbleProto.UserState.VolumeAdjustment\x1aH\n\x10VolumeAdjustment\x12\x19\n\x11listening_channel\x18\x01 \x01(\r\x12\x19\n\x11volume_adjustment\x18\x02 \x01(\x02\"\xc4\x01\n\x07\x42\x61nList\x12+\n\x04\x62\x61ns\x18\x01 \x03(\x0b\x32\x1d.MumbleProto.BanList.BanEntry\x12\x14\n\x05query\x18\x02 \x01(\x08:\x05\x66\x61lse\x1av\n\x08\x42\x61nEntry\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x02(\x0c\x12\x0c\n\x04mask\x18\x02 \x02(\r\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0c\n\x04hash\x18\x04 \x01(\t\x12\x0e\n\x06reason\x18\x05 \x01(\t\x12\r\n\x05start\x18\x06 \x01(\t\x12\x10\n\x08\x64uration\x18\x07 \x01(\r\"c\n\x0bTextMessage\x12\r\n\x05\x61\x63tor\x18\x01 \x01(\r\x12\x0f\n\x07session\x18\x02 \x03(\r\x12\x12\n\nchannel_id\x18\x03 \x03(\r\x12\x0f\n\x07tree_id\x18\x04 \x03(\r\x12\x0f\n\x07message\x18\x05 \x02(\t\"\xa7\x03\n\x10PermissionDenied\x12\x12\n\npermission\x18\x01 \x01(\r\x12\x12\n\nchannel_id\x18\x02 \x01(\r\x12\x0f\n\x07session\x18\x03 \x01(\r\x12\x0e\n\x06reason\x18\x04 \x01(\t\x12\x34\n\x04type\x18\x05 \x01(\x0e\x32&.MumbleProto.PermissionDenied.DenyType\x12\x0c\n\x04name\x18\x06 \x01(\t\"\x85\x02\n\x08\x44\x65nyType\x12\x08\n\x04Text\x10\x00\x12\x0e\n\nPermission\x10\x01\x12\r\n\tSuperUser\x10\x02\x12\x0f\n\x0b\x43hannelName\x10\x03\x12\x0f\n\x0bTextTooLong\x10\x04\x12\x07\n\x03H9K\x10\x05\x12\x14\n\x10TemporaryChannel\x10\x06\x12\x16\n\x12MissingCertificate\x10\x07\x12\x0c\n\x08UserName\x10\x08\x12\x0f\n\x0b\x43hannelFull\x10\t\x12\x10\n\x0cNestingLimit\x10\n\x12\x15\n\x11\x43hannelCountLimit\x10\x0b\x12\x18\n\x14\x43hannelListenerLimit\x10\x0c\x12\x15\n\x11UserListenerLimit\x10\r\"\xd4\x03\n\x03\x41\x43L\x12\x12\n\nchannel_id\x18\x01 \x02(\r\x12\x1a\n\x0cinherit_acls\x18\x02 \x01(\x08:\x04true\x12*\n\x06groups\x18\x03 \x03(\x0b\x32\x1a.MumbleProto.ACL.ChanGroup\x12&\n\x04\x61\x63ls\x18\x04 \x03(\x0b\x32\x18.MumbleProto.ACL.ChanACL\x12\x14\n\x05query\x18\x05 \x01(\x08:\x05\x66\x61lse\x1a\x9c\x01\n\tChanGroup\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x17\n\tinherited\x18\x02 \x01(\x08:\x04true\x12\x15\n\x07inherit\x18\x03 \x01(\x08:\x04true\x12\x19\n\x0binheritable\x18\x04 \x01(\x08:\x04true\x12\x0b\n\x03\x61\x64\x64\x18\x05 \x03(\r\x12\x0e\n\x06remove\x18\x06 \x03(\r\x12\x19\n\x11inherited_members\x18\x07 \x03(\r\x1a\x93\x01\n\x07\x43hanACL\x12\x18\n\napply_here\x18\x01 \x01(\x08:\x04true\x12\x18\n\napply_subs\x18\x02 \x01(\x08:\x04true\x12\x17\n\tinherited\x18\x03 \x01(\x08:\x04true\x12\x0f\n\x07user_id\x18\x04 \x01(\r\x12\r\n\x05group\x18\x05 \x01(\t\x12\r\n\x05grant\x18\x06 \x01(\r\x12\x0c\n\x04\x64\x65ny\x18\x07 \x01(\r\"(\n\nQueryUsers\x12\x0b\n\x03ids\x18\x01 \x03(\r\x12\r\n\x05names\x18\x02 \x03(\t\"E\n\nCryptSetup\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\x14\n\x0c\x63lient_nonce\x18\x02 \x01(\x0c\x12\x14\n\x0cserver_nonce\x18\x03 \x01(\x0c\"\xd3\x01\n\x13\x43ontextActionModify\x12\x0e\n\x06\x61\x63tion\x18\x01 \x02(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontext\x18\x03 \x01(\r\x12=\n\toperation\x18\x04 \x01(\x0e\x32*.MumbleProto.ContextActionModify.Operation\",\n\x07\x43ontext\x12\n\n\x06Server\x10\x01\x12\x0b\n\x07\x43hannel\x10\x02\x12\x08\n\x04User\x10\x04\" \n\tOperation\x12\x07\n\x03\x41\x64\x64\x10\x00\x12\n\n\x06Remove\x10\x01\"D\n\rContextAction\x12\x0f\n\x07session\x18\x01 \x01(\r\x12\x12\n\nchannel_id\x18\x02 \x01(\r\x12\x0e\n\x06\x61\x63tion\x18\x03 \x02(\t\"\x85\x01\n\x08UserList\x12)\n\x05users\x18\x01 \x03(\x0b\x32\x1a.MumbleProto.UserList.User\x1aN\n\x04User\x12\x0f\n\x07user_id\x18\x01 \x02(\r\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\tlast_seen\x18\x03 \x01(\t\x12\x14\n\x0clast_channel\x18\x04 \x01(\r\"\xb8\x01\n\x0bVoiceTarget\x12\n\n\x02id\x18\x01 \x01(\r\x12\x30\n\x07targets\x18\x02 \x03(\x0b\x32\x1f.MumbleProto.VoiceTarget.Target\x1ak\n\x06Target\x12\x0f\n\x07session\x18\x01 \x03(\r\x12\x12\n\nchannel_id\x18\x02 \x01(\r\x12\r\n\x05group\x18\x03 \x01(\t\x12\x14\n\x05links\x18\x04 \x01(\x08:\x05\x66\x61lse\x12\x17\n\x08\x63hildren\x18\x05 \x01(\x08:\x05\x66\x61lse\"P\n\x0fPermissionQuery\x12\x12\n\nchannel_id\x18\x01 \x01(\r\x12\x13\n\x0bpermissions\x18\x02 \x01(\r\x12\x14\n\x05\x66lush\x18\x03 \x01(\x08:\x05\x66\x61lse\"\\\n\x0c\x43odecVersion\x12\r\n\x05\x61lpha\x18\x01 \x02(\x05\x12\x0c\n\x04\x62\x65ta\x18\x02 \x02(\x05\x12\x1a\n\x0cprefer_alpha\x18\x03 \x02(\x08:\x04true\x12\x13\n\x04opus\x18\x04 \x01(\x08:\x05\x66\x61lse\"\x80\x06\n\tUserStats\x12\x0f\n\x07session\x18\x01 \x01(\r\x12\x19\n\nstats_only\x18\x02 \x01(\x08:\x05\x66\x61lse\x12\x14\n\x0c\x63\x65rtificates\x18\x03 \x03(\x0c\x12\x31\n\x0b\x66rom_client\x18\x04 \x01(\x0b\x32\x1c.MumbleProto.UserStats.Stats\x12\x31\n\x0b\x66rom_server\x18\x05 \x01(\x0b\x32\x1c.MumbleProto.UserStats.Stats\x12\x13\n\x0budp_packets\x18\x06 \x01(\r\x12\x13\n\x0btcp_packets\x18\x07 \x01(\r\x12\x14\n\x0cudp_ping_avg\x18\x08 \x01(\x02\x12\x14\n\x0cudp_ping_var\x18\t \x01(\x02\x12\x14\n\x0ctcp_ping_avg\x18\n \x01(\x02\x12\x14\n\x0ctcp_ping_var\x18\x0b \x01(\x02\x12%\n\x07version\x18\x0c \x01(\x0b\x32\x14.MumbleProto.Version\x12\x15\n\rcelt_versions\x18\r \x03(\x05\x12\x0f\n\x07\x61\x64\x64ress\x18\x0e \x01(\x0c\x12\x11\n\tbandwidth\x18\x0f \x01(\r\x12\x12\n\nonlinesecs\x18\x10 \x01(\r\x12\x10\n\x08idlesecs\x18\x11 \x01(\r\x12!\n\x12strong_certificate\x18\x12 \x01(\x08:\x05\x66\x61lse\x12\x13\n\x04opus\x18\x13 \x01(\x08:\x05\x66\x61lse\x12:\n\rrolling_stats\x18\x14 \x01(\x0b\x32#.MumbleProto.UserStats.RollingStats\x1a\x41\n\x05Stats\x12\x0c\n\x04good\x18\x01 \x01(\r\x12\x0c\n\x04late\x18\x02 \x01(\r\x12\x0c\n\x04lost\x18\x03 \x01(\r\x12\x0e\n\x06resync\x18\x04 \x01(\r\x1a\x89\x01\n\x0cRollingStats\x12\x13\n\x0btime_window\x18\x01 \x01(\r\x12\x31\n\x0b\x66rom_client\x18\x02 \x01(\x0b\x32\x1c.MumbleProto.UserStats.Stats\x12\x31\n\x0b\x66rom_server\x18\x03 \x01(\x0b\x32\x1c.MumbleProto.UserStats.Stats\"\\\n\x0bRequestBlob\x12\x17\n\x0fsession_texture\x18\x01 \x03(\r\x12\x17\n\x0fsession_comment\x18\x02 \x03(\r\x12\x1b\n\x13\x63hannel_description\x18\x03 \x03(\r\"\xb3\x01\n\x0cServerConfig\x12\x15\n\rmax_bandwidth\x18\x01 \x01(\r\x12\x14\n\x0cwelcome_text\x18\x02 \x01(\t\x12\x12\n\nallow_html\x18\x03 \x01(\x08\x12\x16\n\x0emessage_length\x18\x04 \x01(\r\x12\x1c\n\x14image_message_length\x18\x05 \x01(\r\x12\x11\n\tmax_users\x18\x06 \x01(\r\x12\x19\n\x11recording_allowed\x18\x07 \x01(\x08\"a\n\rSuggestConfig\x12\x12\n\nversion_v1\x18\x01 \x01(\r\x12\x12\n\nversion_v2\x18\x04 \x01(\x04\x12\x12\n\npositional\x18\x02 \x01(\x08\x12\x14\n\x0cpush_to_talk\x18\x03 \x01(\x08\"k\n\x16PluginDataTransmission\x12\x15\n\rsenderSession\x18\x01 \x01(\r\x12\x1c\n\x10receiverSessions\x18\x02 \x03(\rB\x02\x10\x01\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x0e\n\x06\x64\x61taID\x18\x04 \x01(\tB\x02H\x01') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'Mumble_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'H\001' + _globals['_PLUGINDATATRANSMISSION'].fields_by_name['receiverSessions']._loaded_options = None + _globals['_PLUGINDATATRANSMISSION'].fields_by_name['receiverSessions']._serialized_options = b'\020\001' + _globals['_VERSION']._serialized_start=29 + _globals['_VERSION']._serialized_end=127 + _globals['_UDPTUNNEL']._serialized_start=129 + _globals['_UDPTUNNEL']._serialized_end=156 + _globals['_AUTHENTICATE']._serialized_start=159 + _globals['_AUTHENTICATE']._serialized_end=293 + _globals['_PING']._serialized_start=296 + _globals['_PING']._serialized_end=509 + _globals['_REJECT']._serialized_start=512 + _globals['_REJECT']._serialized_end=781 + _globals['_REJECT_REJECTTYPE']._serialized_start=585 + _globals['_REJECT_REJECTTYPE']._serialized_end=781 + _globals['_SERVERSYNC']._serialized_start=783 + _globals['_SERVERSYNC']._serialized_end=878 + _globals['_CHANNELREMOVE']._serialized_start=880 + _globals['_CHANNELREMOVE']._serialized_end=915 + _globals['_CHANNELSTATE']._serialized_start=918 + _globals['_CHANNELSTATE']._serialized_end=1199 + _globals['_USERREMOVE']._serialized_start=1201 + _globals['_USERREMOVE']._serialized_end=1315 + _globals['_USERSTATE']._serialized_start=1318 + _globals['_USERSTATE']._serialized_end=1932 + _globals['_USERSTATE_VOLUMEADJUSTMENT']._serialized_start=1860 + _globals['_USERSTATE_VOLUMEADJUSTMENT']._serialized_end=1932 + _globals['_BANLIST']._serialized_start=1935 + _globals['_BANLIST']._serialized_end=2131 + _globals['_BANLIST_BANENTRY']._serialized_start=2013 + _globals['_BANLIST_BANENTRY']._serialized_end=2131 + _globals['_TEXTMESSAGE']._serialized_start=2133 + _globals['_TEXTMESSAGE']._serialized_end=2232 + _globals['_PERMISSIONDENIED']._serialized_start=2235 + _globals['_PERMISSIONDENIED']._serialized_end=2658 + _globals['_PERMISSIONDENIED_DENYTYPE']._serialized_start=2397 + _globals['_PERMISSIONDENIED_DENYTYPE']._serialized_end=2658 + _globals['_ACL']._serialized_start=2661 + _globals['_ACL']._serialized_end=3129 + _globals['_ACL_CHANGROUP']._serialized_start=2823 + _globals['_ACL_CHANGROUP']._serialized_end=2979 + _globals['_ACL_CHANACL']._serialized_start=2982 + _globals['_ACL_CHANACL']._serialized_end=3129 + _globals['_QUERYUSERS']._serialized_start=3131 + _globals['_QUERYUSERS']._serialized_end=3171 + _globals['_CRYPTSETUP']._serialized_start=3173 + _globals['_CRYPTSETUP']._serialized_end=3242 + _globals['_CONTEXTACTIONMODIFY']._serialized_start=3245 + _globals['_CONTEXTACTIONMODIFY']._serialized_end=3456 + _globals['_CONTEXTACTIONMODIFY_CONTEXT']._serialized_start=3378 + _globals['_CONTEXTACTIONMODIFY_CONTEXT']._serialized_end=3422 + _globals['_CONTEXTACTIONMODIFY_OPERATION']._serialized_start=3424 + _globals['_CONTEXTACTIONMODIFY_OPERATION']._serialized_end=3456 + _globals['_CONTEXTACTION']._serialized_start=3458 + _globals['_CONTEXTACTION']._serialized_end=3526 + _globals['_USERLIST']._serialized_start=3529 + _globals['_USERLIST']._serialized_end=3662 + _globals['_USERLIST_USER']._serialized_start=3584 + _globals['_USERLIST_USER']._serialized_end=3662 + _globals['_VOICETARGET']._serialized_start=3665 + _globals['_VOICETARGET']._serialized_end=3849 + _globals['_VOICETARGET_TARGET']._serialized_start=3742 + _globals['_VOICETARGET_TARGET']._serialized_end=3849 + _globals['_PERMISSIONQUERY']._serialized_start=3851 + _globals['_PERMISSIONQUERY']._serialized_end=3931 + _globals['_CODECVERSION']._serialized_start=3933 + _globals['_CODECVERSION']._serialized_end=4025 + _globals['_USERSTATS']._serialized_start=4028 + _globals['_USERSTATS']._serialized_end=4796 + _globals['_USERSTATS_STATS']._serialized_start=4591 + _globals['_USERSTATS_STATS']._serialized_end=4656 + _globals['_USERSTATS_ROLLINGSTATS']._serialized_start=4659 + _globals['_USERSTATS_ROLLINGSTATS']._serialized_end=4796 + _globals['_REQUESTBLOB']._serialized_start=4798 + _globals['_REQUESTBLOB']._serialized_end=4890 + _globals['_SERVERCONFIG']._serialized_start=4893 + _globals['_SERVERCONFIG']._serialized_end=5072 + _globals['_SUGGESTCONFIG']._serialized_start=5074 + _globals['_SUGGESTCONFIG']._serialized_end=5171 + _globals['_PLUGINDATATRANSMISSION']._serialized_start=5173 + _globals['_PLUGINDATATRANSMISSION']._serialized_end=5280 +# @@protoc_insertion_point(module_scope) diff --git a/__pycache__/Mumble_pb2.cpython-312.pyc b/__pycache__/Mumble_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aec03443f33d8e75b3631e6c9bc42702bfade1ed GIT binary patch literal 10448 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 RM7sKwCWT_>tTN)|{{a;PH+cX6 literal 0 HcmV?d00001 diff --git a/experimental.py b/experimental.py index f7ad5be..4bb6103 100644 --- a/experimental.py +++ b/experimental.py @@ -1,13 +1,16 @@ import alsaaudio import numpy as np import wave - +import opuslib import socket # Network -UDP_IP = "172.16.11.27" -UDP_PORT = 5005 +# UDP_IP = "172.16.11.27" +UDP_IP = "127.0.0.1" + +UDP_PORT = 5005 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +encoder = opuslib.Encoder(48000, 1, opuslib.APPLICATION_VOIP) inp = alsaaudio.PCM( alsaaudio.PCM_CAPTURE, # capture mode # alsaaudio.PCM_NONBLOCK, # non-blocking @@ -28,7 +31,10 @@ try: if length > 0: # convert raw bytes to numpy array audio = np.frombuffer(data, dtype=np.int16) - sock.sendto(data, (UDP_IP, UDP_PORT)) + opus_data = encoder.encode(data, 960) + sock.sendto(opus_data, (UDP_IP, UDP_PORT)) + + # sock.sendto(data, (UDP_IP, UDP_PORT)) print(f"Frames: {length} | Max amplitude: {np.max(np.abs(audio))}") except KeyboardInterrupt: print("Stopped") diff --git a/sniffer.py b/sniffer.py new file mode 100644 index 0000000..f77b720 --- /dev/null +++ b/sniffer.py @@ -0,0 +1,119 @@ +import ssl +import socket +import struct +import Mumble_pb2 +import threading +import time +SERVER_IP = "172.16.11.170" +SERVER_PORT = 64738 + +# create raw TCP socket +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# wrap with TLS +ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) +ctx.check_hostname = False +ctx.verify_mode = ssl.CERT_NONE + +tls = ctx.wrap_socket(sock, server_hostname=SERVER_IP) +tls.connect((SERVER_IP, SERVER_PORT)) + +print("TLS connected to Mumble server!") +print(f"Cipher: {tls.cipher()}") +print(f"TLS version: {tls.version()}") + +def send_message(tls, msg_type, message): + + data = message.SerializeToString() + header = struct.pack(">HI", msg_type, len(data)) + tls.send(header + data) + print(f"Sent message type: {msg_type} | size: {len(data)}B") + +def recv_message(tls): + header = tls.recv(6) + if len(header) < 6: + return None, None + msg_type, length = struct.unpack(">HI", header) + data = tls.recv(length) + return msg_type, data + +def send_ping(tls): + while True: + ping = Mumble_pb2.Ping() + ping.timestamp = int(time.time()) + send_message(tls, 3, ping) # type 3 = Ping + print("Ping sent!") + time.sleep(5) + + +# step 1 — send Version +version = Mumble_pb2.Version() +version.version_v1 = (1 << 16) | (4 << 8) | 0 # 1.4.0 +version.release = "1.4.0" +version.os = "Linux" +version.os_version = "Ubuntu" +send_message(tls, 0, version) # type 0 = Version +print("Sent Version!") + + +# step 2 — send Authenticate +auth = Mumble_pb2.Authenticate() +auth.username = "PythonClient" +auth.password = "" # ← put server password here if needed +auth.opus = True +send_message(tls, 2, auth) # type 2 = Authenticate +print("Sent Authenticate!") + +print("\nListening for server messages...") +MSG_TYPES = { + 0: "Version", + 1: "UDPTunnel", + 2: "Authenticate", + 3: "Ping", + 4: "Reject", + 5: "ServerSync", + 6: "ChannelRemove", + 7: "ChannelState", + 8: "UserRemove", + 9: "UserState", + 15: "CryptSetup", + 24: "TextMessage", +} +# start ping thread before main loop +ping_thread = threading.Thread(target=send_ping, args=(tls,)) +ping_thread.daemon = True # dies when main program exits +ping_thread.start() + + +while True: + msg_type, data = recv_message(tls) + if msg_type is None: + print("edjn",msg_type) + break + name = MSG_TYPES.get(msg_type, f"Unknown({msg_type})") + print(f"Received: {name} | size: {len(data)}B",msg_type) + + # parse specific messages + if msg_type == 0: # Version + v = Mumble_pb2.Version() + v.ParseFromString(data) + print(f" Server version: {v.release}") + + elif msg_type == 4: # Reject + r = Mumble_pb2.Reject() + r.ParseFromString(data) + print(f" REJECTED: {r.reason}") + break + elif msg_type == 5: # ServerSync — fully connected! + s = Mumble_pb2.ServerSync() + s.ParseFromString(data) + print(f" Session ID: {s.session}") + print(f" Welcome: {s.welcome_text}") + print(" FULLY CONNECTED TO MUMBLE! ✅") + + elif msg_type == 15: # CryptSetup — encryption keys! + c = Mumble_pb2.CryptSetup() + c.ParseFromString(data) + print(f" KEY: {c.key.hex()}") + print(f" CLIENT_NONCE: {c.client_nonce.hex()}") + print(f" SERVER_NONCE: {c.server_nonce.hex()}") \ No newline at end of file