mumble-ruby2 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +119 -0
- data/Rakefile +2 -0
- data/lib/mumble-ruby2.rb +39 -0
- data/lib/mumble-ruby2/audio_player.rb +107 -0
- data/lib/mumble-ruby2/audio_recorder.rb +79 -0
- data/lib/mumble-ruby2/cert_manager.rb +67 -0
- data/lib/mumble-ruby2/channel.rb +48 -0
- data/lib/mumble-ruby2/client.rb +218 -0
- data/lib/mumble-ruby2/connection.rb +85 -0
- data/lib/mumble-ruby2/img_reader.rb +37 -0
- data/lib/mumble-ruby2/messages.rb +361 -0
- data/lib/mumble-ruby2/model.rb +43 -0
- data/lib/mumble-ruby2/mumble.proto +291 -0
- data/lib/mumble-ruby2/packet_data_stream.rb +157 -0
- data/lib/mumble-ruby2/thread_tools.rb +24 -0
- data/lib/mumble-ruby2/user.rb +51 -0
- data/lib/mumble-ruby2/version.rb +3 -0
- data/mumble-ruby2.gemspec +24 -0
- metadata +137 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Mumble
|
4
|
+
class Model
|
5
|
+
extend ::Forwardable
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def attribute(name, &block)
|
9
|
+
attributes << name
|
10
|
+
define_method(name) do
|
11
|
+
if block_given?
|
12
|
+
self.instance_eval(&block)
|
13
|
+
else
|
14
|
+
@data[name.to_s]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def attributes
|
20
|
+
@attributes ||= []
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(client, data)
|
25
|
+
@client = client
|
26
|
+
@data = data
|
27
|
+
end
|
28
|
+
|
29
|
+
def update(data)
|
30
|
+
@data.merge!(data)
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
attrs = self.class.attributes.map do |attr|
|
35
|
+
[attr, send(attr)].join("=")
|
36
|
+
end.join(" ")
|
37
|
+
%Q{#<#{self.class.name} #{attrs}>}
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
attr_reader :data, :client
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
package MumbleProto;
|
2
|
+
|
3
|
+
option optimize_for = SPEED;
|
4
|
+
|
5
|
+
message Version {
|
6
|
+
optional uint32 version = 1;
|
7
|
+
optional string release = 2;
|
8
|
+
optional string os = 3;
|
9
|
+
optional string os_version = 4;
|
10
|
+
}
|
11
|
+
|
12
|
+
message UDPTunnel {
|
13
|
+
required bytes packet = 1;
|
14
|
+
}
|
15
|
+
|
16
|
+
message Authenticate {
|
17
|
+
optional string username = 1;
|
18
|
+
optional string password = 2;
|
19
|
+
repeated string tokens = 3;
|
20
|
+
repeated int32 celt_versions = 4;
|
21
|
+
optional bool opus = 5 [default = false];
|
22
|
+
}
|
23
|
+
|
24
|
+
message Ping {
|
25
|
+
optional uint64 timestamp = 1;
|
26
|
+
optional uint32 good = 2;
|
27
|
+
optional uint32 late = 3;
|
28
|
+
optional uint32 lost = 4;
|
29
|
+
optional uint32 resync = 5;
|
30
|
+
optional uint32 udp_packets = 6;
|
31
|
+
optional uint32 tcp_packets = 7;
|
32
|
+
optional float udp_ping_avg = 8;
|
33
|
+
optional float udp_ping_var = 9;
|
34
|
+
optional float tcp_ping_avg = 10;
|
35
|
+
optional float tcp_ping_var = 11;
|
36
|
+
}
|
37
|
+
|
38
|
+
message Reject {
|
39
|
+
enum RejectType {
|
40
|
+
None = 0;
|
41
|
+
WrongVersion = 1;
|
42
|
+
InvalidUsername = 2;
|
43
|
+
WrongUserPW = 3;
|
44
|
+
WrongServerPW = 4;
|
45
|
+
UsernameInUse = 5;
|
46
|
+
ServerFull = 6;
|
47
|
+
NoCertificate = 7;
|
48
|
+
}
|
49
|
+
optional RejectType type = 1;
|
50
|
+
optional string reason = 2;
|
51
|
+
}
|
52
|
+
|
53
|
+
message ServerConfig {
|
54
|
+
optional uint32 max_bandwidth = 1;
|
55
|
+
optional string welcome_text = 2;
|
56
|
+
optional bool allow_html = 3;
|
57
|
+
optional uint32 message_length = 4;
|
58
|
+
optional uint32 image_message_length = 5;
|
59
|
+
}
|
60
|
+
|
61
|
+
message ServerSync {
|
62
|
+
optional uint32 session = 1;
|
63
|
+
optional uint32 max_bandwidth = 2;
|
64
|
+
optional string welcome_text = 3;
|
65
|
+
optional uint64 permissions = 4;
|
66
|
+
}
|
67
|
+
|
68
|
+
message ChannelRemove {
|
69
|
+
required uint32 channel_id = 1;
|
70
|
+
}
|
71
|
+
|
72
|
+
message ChannelState {
|
73
|
+
optional uint32 channel_id = 1;
|
74
|
+
optional uint32 parent = 2;
|
75
|
+
optional string name = 3;
|
76
|
+
repeated uint32 links = 4;
|
77
|
+
optional string description = 5;
|
78
|
+
repeated uint32 links_add = 6;
|
79
|
+
repeated uint32 links_remove = 7;
|
80
|
+
optional bool temporary = 8 [default = false];
|
81
|
+
optional int32 position = 9 [default = 0];
|
82
|
+
optional bytes description_hash = 10;
|
83
|
+
}
|
84
|
+
|
85
|
+
message UserRemove {
|
86
|
+
required uint32 session = 1;
|
87
|
+
optional uint32 actor = 2;
|
88
|
+
optional string reason = 3;
|
89
|
+
optional bool ban = 4;
|
90
|
+
}
|
91
|
+
|
92
|
+
message UserState {
|
93
|
+
optional uint32 session = 1;
|
94
|
+
optional uint32 actor = 2;
|
95
|
+
optional string name = 3;
|
96
|
+
optional uint32 user_id = 4;
|
97
|
+
optional uint32 channel_id = 5;
|
98
|
+
optional bool mute = 6;
|
99
|
+
optional bool deaf = 7;
|
100
|
+
optional bool suppress = 8;
|
101
|
+
optional bool self_mute = 9;
|
102
|
+
optional bool self_deaf = 10;
|
103
|
+
optional bytes texture = 11;
|
104
|
+
optional bytes plugin_context = 12;
|
105
|
+
optional string plugin_identity = 13;
|
106
|
+
optional string comment = 14;
|
107
|
+
optional string hash = 15;
|
108
|
+
optional bytes comment_hash = 16;
|
109
|
+
optional bytes texture_hash = 17;
|
110
|
+
optional bool priority_speaker = 18;
|
111
|
+
optional bool recording = 19;
|
112
|
+
}
|
113
|
+
|
114
|
+
message BanList {
|
115
|
+
message BanEntry {
|
116
|
+
required bytes address = 1;
|
117
|
+
required uint32 mask = 2;
|
118
|
+
optional string name = 3;
|
119
|
+
optional string hash = 4;
|
120
|
+
optional string reason = 5;
|
121
|
+
optional string start = 6;
|
122
|
+
optional uint32 duration = 7;
|
123
|
+
}
|
124
|
+
repeated BanEntry bans = 1;
|
125
|
+
optional bool query = 2 [default = false];
|
126
|
+
}
|
127
|
+
|
128
|
+
message TextMessage {
|
129
|
+
optional uint32 actor = 1;
|
130
|
+
repeated uint32 session = 2;
|
131
|
+
repeated uint32 channel_id = 3;
|
132
|
+
repeated uint32 tree_id = 4;
|
133
|
+
required string message = 5;
|
134
|
+
}
|
135
|
+
|
136
|
+
message PermissionDenied {
|
137
|
+
enum DenyType {
|
138
|
+
Text = 0;
|
139
|
+
Permission = 1;
|
140
|
+
SuperUser = 2;
|
141
|
+
ChannelName = 3;
|
142
|
+
TextTooLong = 4;
|
143
|
+
H9K = 5;
|
144
|
+
TemporaryChannel = 6;
|
145
|
+
MissingCertificate = 7;
|
146
|
+
UserName = 8;
|
147
|
+
ChannelFull = 9;
|
148
|
+
NestingLimit = 10;
|
149
|
+
}
|
150
|
+
optional uint32 permission = 1;
|
151
|
+
optional uint32 channel_id = 2;
|
152
|
+
optional uint32 session = 3;
|
153
|
+
optional string reason = 4;
|
154
|
+
optional DenyType type = 5;
|
155
|
+
optional string name = 6;
|
156
|
+
}
|
157
|
+
|
158
|
+
message ACL {
|
159
|
+
message ChanGroup {
|
160
|
+
required string name = 1;
|
161
|
+
optional bool inherited = 2 [default = true];
|
162
|
+
optional bool inherit = 3 [default = true];
|
163
|
+
optional bool inheritable = 4 [default = true];
|
164
|
+
repeated uint32 add = 5;
|
165
|
+
repeated uint32 remove = 6;
|
166
|
+
repeated uint32 inherited_members = 7;
|
167
|
+
}
|
168
|
+
message ChanACL {
|
169
|
+
optional bool apply_here = 1 [default = true];
|
170
|
+
optional bool apply_subs = 2 [default = true];
|
171
|
+
optional bool inherited = 3 [default = true];
|
172
|
+
optional uint32 user_id = 4;
|
173
|
+
optional string group = 5;
|
174
|
+
optional uint32 grant = 6;
|
175
|
+
optional uint32 deny = 7;
|
176
|
+
}
|
177
|
+
required uint32 channel_id = 1;
|
178
|
+
optional bool inherit_acls = 2 [default = true];
|
179
|
+
repeated ChanGroup groups = 3;
|
180
|
+
repeated ChanACL acls = 4;
|
181
|
+
optional bool query = 5 [default = false];
|
182
|
+
}
|
183
|
+
|
184
|
+
message QueryUsers {
|
185
|
+
repeated uint32 ids = 1;
|
186
|
+
repeated string names = 2;
|
187
|
+
}
|
188
|
+
|
189
|
+
message CryptSetup {
|
190
|
+
optional bytes key = 1;
|
191
|
+
optional bytes client_nonce = 2;
|
192
|
+
optional bytes server_nonce = 3;
|
193
|
+
}
|
194
|
+
|
195
|
+
message ContextActionModify {
|
196
|
+
enum Context {
|
197
|
+
Server = 0x01;
|
198
|
+
Channel = 0x02;
|
199
|
+
User = 0x04;
|
200
|
+
}
|
201
|
+
enum Operation {
|
202
|
+
Add = 0;
|
203
|
+
Remove = 1;
|
204
|
+
}
|
205
|
+
required string action = 1;
|
206
|
+
optional string text = 2;
|
207
|
+
optional uint32 context = 3;
|
208
|
+
optional Operation operation = 4;
|
209
|
+
}
|
210
|
+
|
211
|
+
message ContextAction {
|
212
|
+
optional uint32 session = 1;
|
213
|
+
optional uint32 channel_id = 2;
|
214
|
+
required string action = 3;
|
215
|
+
}
|
216
|
+
|
217
|
+
message UserList {
|
218
|
+
message User {
|
219
|
+
required uint32 user_id = 1;
|
220
|
+
optional string name = 2;
|
221
|
+
}
|
222
|
+
repeated User users = 1;
|
223
|
+
}
|
224
|
+
|
225
|
+
message VoiceTarget {
|
226
|
+
message Target {
|
227
|
+
repeated uint32 session = 1;
|
228
|
+
optional uint32 channel_id = 2;
|
229
|
+
optional string group = 3;
|
230
|
+
optional bool links = 4 [default = false];
|
231
|
+
optional bool children = 5 [default = false];
|
232
|
+
}
|
233
|
+
optional uint32 id = 1;
|
234
|
+
repeated Target targets = 2;
|
235
|
+
}
|
236
|
+
|
237
|
+
message PermissionQuery {
|
238
|
+
optional uint32 channel_id = 1;
|
239
|
+
optional uint32 permissions = 2;
|
240
|
+
optional bool flush = 3 [default = false];
|
241
|
+
}
|
242
|
+
|
243
|
+
message CodecVersion {
|
244
|
+
required int32 alpha = 1;
|
245
|
+
required int32 beta = 2;
|
246
|
+
required bool prefer_alpha = 3 [default = true];
|
247
|
+
optional bool opus = 4 [default = false];
|
248
|
+
}
|
249
|
+
|
250
|
+
message UserStats {
|
251
|
+
message Stats {
|
252
|
+
optional uint32 good = 1;
|
253
|
+
optional uint32 late = 2;
|
254
|
+
optional uint32 lost = 3;
|
255
|
+
optional uint32 resync = 4;
|
256
|
+
}
|
257
|
+
|
258
|
+
optional uint32 session = 1;
|
259
|
+
optional bool stats_only = 2 [default = false];
|
260
|
+
repeated bytes certificates = 3;
|
261
|
+
optional Stats from_client = 4;
|
262
|
+
optional Stats from_server = 5;
|
263
|
+
|
264
|
+
optional uint32 udp_packets = 6;
|
265
|
+
optional uint32 tcp_packets = 7;
|
266
|
+
optional float udp_ping_avg = 8;
|
267
|
+
optional float udp_ping_var = 9;
|
268
|
+
optional float tcp_ping_avg = 10;
|
269
|
+
optional float tcp_ping_var = 11;
|
270
|
+
|
271
|
+
optional Version version = 12;
|
272
|
+
repeated int32 celt_versions = 13;
|
273
|
+
optional bytes address = 14;
|
274
|
+
optional uint32 bandwidth = 15;
|
275
|
+
optional uint32 onlinesecs = 16;
|
276
|
+
optional uint32 idlesecs = 17;
|
277
|
+
optional bool strong_certificate = 18 [default = false];
|
278
|
+
optional bool opus = 19 [default = false];
|
279
|
+
}
|
280
|
+
|
281
|
+
message SuggestConfig {
|
282
|
+
optional uint32 version = 1;
|
283
|
+
optional bool positional = 2;
|
284
|
+
optional bool push_to_talk = 3;
|
285
|
+
}
|
286
|
+
|
287
|
+
message RequestBlob {
|
288
|
+
repeated uint32 session_texture = 1;
|
289
|
+
repeated uint32 session_comment = 2;
|
290
|
+
repeated uint32 channel_description = 3;
|
291
|
+
}
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Mumble
|
2
|
+
class PacketDataStream
|
3
|
+
def initialize(data=nil)
|
4
|
+
@data = data || 0.chr * 1024
|
5
|
+
@data = @data.split ''
|
6
|
+
@pos = 0
|
7
|
+
@ok = true
|
8
|
+
@capacity = @data.size
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid
|
12
|
+
@ok
|
13
|
+
end
|
14
|
+
|
15
|
+
def size
|
16
|
+
@pos
|
17
|
+
end
|
18
|
+
|
19
|
+
def left
|
20
|
+
@capacity - @pos
|
21
|
+
end
|
22
|
+
|
23
|
+
def append(val)
|
24
|
+
if @pos < @capacity
|
25
|
+
@data[@pos] = val.chr
|
26
|
+
skip
|
27
|
+
else
|
28
|
+
@ok = false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def append_block(data)
|
33
|
+
len = data.size
|
34
|
+
if len < left
|
35
|
+
@data[@pos, len] = data.split('')
|
36
|
+
skip len
|
37
|
+
else
|
38
|
+
@ok = false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_block(len)
|
43
|
+
if len < left
|
44
|
+
ret = @data[@pos, len]
|
45
|
+
skip len
|
46
|
+
else
|
47
|
+
@ok = false
|
48
|
+
ret = []
|
49
|
+
end
|
50
|
+
ret
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_next
|
54
|
+
if @pos < @capacity
|
55
|
+
ret = @data[@pos].ord
|
56
|
+
skip
|
57
|
+
else
|
58
|
+
ret = 0
|
59
|
+
@ok = false
|
60
|
+
end
|
61
|
+
ret
|
62
|
+
end
|
63
|
+
|
64
|
+
def rewind
|
65
|
+
@pos = 0
|
66
|
+
end
|
67
|
+
|
68
|
+
def skip(len=1)
|
69
|
+
len < left ? @pos += len : @ok = false
|
70
|
+
end
|
71
|
+
|
72
|
+
def put_int(int)
|
73
|
+
if !(int & 0x8000000000000000).zero? && (~int < 0x100000000)
|
74
|
+
int = ~int
|
75
|
+
puts int
|
76
|
+
if int <= 0x3
|
77
|
+
# Shortcase for -1 to -4
|
78
|
+
append(0xFC | int)
|
79
|
+
else
|
80
|
+
append(0xF8)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
if int < 0x80
|
85
|
+
# Need top bit clear
|
86
|
+
append(int)
|
87
|
+
elsif int < 0x4000
|
88
|
+
# Need top two bits clear
|
89
|
+
append((int >> 8) | 0x80)
|
90
|
+
append(int & 0xFF)
|
91
|
+
elsif int < 0x200000
|
92
|
+
# Need top three bits clear
|
93
|
+
append((int >> 16) | 0xC0)
|
94
|
+
append((int >> 8) & 0xFF)
|
95
|
+
append(int & 0xFF)
|
96
|
+
elsif int < 0x10000000
|
97
|
+
# Need top four bits clear
|
98
|
+
append((int >> 24) | 0xE0)
|
99
|
+
append((int >> 16) & 0xFF)
|
100
|
+
append((int >> 8) & 0xFF)
|
101
|
+
append(int & 0xFF)
|
102
|
+
elsif int < 0x100000000
|
103
|
+
# It's a full 32-bit integer.
|
104
|
+
append(0xF0)
|
105
|
+
append((int >> 24) & 0xFF)
|
106
|
+
append((int >> 16) & 0xFF)
|
107
|
+
append((int >> 8) & 0xFF)
|
108
|
+
append(int & 0xFF)
|
109
|
+
else
|
110
|
+
# It's a 64-bit value.
|
111
|
+
append(0xF4)
|
112
|
+
append((int >> 56) & 0xFF)
|
113
|
+
append((int >> 48) & 0xFF)
|
114
|
+
append((int >> 40) & 0xFF)
|
115
|
+
append((int >> 32) & 0xFF)
|
116
|
+
append((int >> 24) & 0xFF)
|
117
|
+
append((int >> 16) & 0xFF)
|
118
|
+
append((int >> 8) & 0xFF)
|
119
|
+
append(int & 0xFF)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_int
|
124
|
+
v = get_next
|
125
|
+
int = 0
|
126
|
+
|
127
|
+
if (v & 0x80) == 0x00
|
128
|
+
int = v & 0x7F
|
129
|
+
elsif (v & 0xC0) == 0x80
|
130
|
+
int = (v & 0x3F) << 8 | get_next
|
131
|
+
elsif (v & 0xF0) == 0xF0
|
132
|
+
x = v & 0xFC
|
133
|
+
if x == 0xF0
|
134
|
+
int = get_next << 24 | get_next << 16 | get_next << 8 | get_next
|
135
|
+
elsif x == 0xF4
|
136
|
+
int = get_next << 56 | get_next << 48 | get_next << 40 | get_next << 32 |
|
137
|
+
get_next << 24 | get_next << 16 | get_next << 8 | get_next
|
138
|
+
elsif x == 0xF8
|
139
|
+
int = get_int
|
140
|
+
int = ~int
|
141
|
+
elsif x == 0xFC
|
142
|
+
int = v & 0x03
|
143
|
+
int = ~int
|
144
|
+
else
|
145
|
+
@ok = false
|
146
|
+
int = 0
|
147
|
+
end
|
148
|
+
elsif (v & 0xF0) == 0xE0
|
149
|
+
int = (v & 0x0F) << 24 | get_next << 16 | get_next << 8 | get_next
|
150
|
+
elsif (v & 0xE0) == 0xC0
|
151
|
+
int = (v & 0x1F) << 16 | get_next << 8 | get_next
|
152
|
+
end
|
153
|
+
|
154
|
+
return int
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|