mtproto 0.0.1 → 0.0.3
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 +4 -4
- data/lib/mtproto/transport/abridged_packet_codec.rb +35 -0
- data/lib/mtproto/transport/tcp_connection.rb +91 -0
- data/lib/mtproto/version.rb +2 -2
- data/lib/mtproto.rb +8 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa11aaca7c34af33346fa59458bf300211785023ff833336738b0988deeafc32
|
|
4
|
+
data.tar.gz: 417cef055fd9d042956880f8e0214a10669759d7881e3af67e15e3bd2018de6c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 630dadd58d377ed2342abddf659385e8864fbfca3e6c4e1e9fa5a861b29a7a4fcb7628f9e3c7341c716588c5b37c18944d14e954cf0304ced52fa8482dcf859b
|
|
7
|
+
data.tar.gz: 796286ff4a5b9b9a42d7b0c14616040f3b8e0b310c2afece12943f49c14622d1f82f5b4479ef23b47fa6cabd3216b95aa16d0eb1ba4459cddab039042b94dd2a
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MTProto
|
|
4
|
+
module Transport
|
|
5
|
+
class AbridgedPacketCodec
|
|
6
|
+
TAG = "\xef".b
|
|
7
|
+
OBFUSCATE_TAG = "\xef\xef\xef\xef".b
|
|
8
|
+
|
|
9
|
+
def encode_packet(data)
|
|
10
|
+
length = data.bytesize >> 2
|
|
11
|
+
|
|
12
|
+
length_prefix = if length < 127
|
|
13
|
+
[length].pack('C')
|
|
14
|
+
else
|
|
15
|
+
"\x7f".b + [length].pack('L<')[0, 3]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
length_prefix + data
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def decode_packet(data)
|
|
22
|
+
length = data.unpack1('C')
|
|
23
|
+
offset = 1
|
|
24
|
+
|
|
25
|
+
if length >= 127
|
|
26
|
+
length = (data[1, 3] + "\x00").unpack1('L<')
|
|
27
|
+
offset = 4
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
actual_length = length << 2
|
|
31
|
+
data[offset, actual_length]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'socket'
|
|
4
|
+
require 'timeout'
|
|
5
|
+
|
|
6
|
+
module MTProto
|
|
7
|
+
module Transport
|
|
8
|
+
class ConnectionError < StandardError; end
|
|
9
|
+
|
|
10
|
+
class TCPConnection
|
|
11
|
+
attr_reader :host, :port, :codec
|
|
12
|
+
|
|
13
|
+
def initialize(host, port, codec)
|
|
14
|
+
@host = host
|
|
15
|
+
@port = port
|
|
16
|
+
@codec = codec
|
|
17
|
+
@socket = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def connect
|
|
21
|
+
return if connected?
|
|
22
|
+
|
|
23
|
+
@socket = TCPSocket.new(@host, @port)
|
|
24
|
+
|
|
25
|
+
send_init_tag if @codec.class.const_defined?(:TAG)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def connected?
|
|
29
|
+
!@socket.nil? && !@socket.closed?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def send(data)
|
|
33
|
+
raise ConnectionError, 'Not connected' unless connected?
|
|
34
|
+
|
|
35
|
+
encoded = @codec.encode_packet(data)
|
|
36
|
+
@socket.write(encoded)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def recv(timeout: 60)
|
|
40
|
+
raise ConnectionError, 'Not connected' unless connected?
|
|
41
|
+
|
|
42
|
+
Timeout.timeout(timeout) do
|
|
43
|
+
read_packet
|
|
44
|
+
end
|
|
45
|
+
rescue Timeout::Error
|
|
46
|
+
raise ConnectionError, 'Receive timeout'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def close
|
|
50
|
+
return unless @socket
|
|
51
|
+
|
|
52
|
+
@socket.close
|
|
53
|
+
rescue StandardError
|
|
54
|
+
nil
|
|
55
|
+
ensure
|
|
56
|
+
@socket = nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def send_init_tag
|
|
62
|
+
tag = @codec.class.const_get(:TAG)
|
|
63
|
+
@socket.write(tag) if tag
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def read_packet
|
|
67
|
+
first_byte = read_exactly(1)
|
|
68
|
+
length = first_byte.unpack1('C')
|
|
69
|
+
|
|
70
|
+
if length >= 127
|
|
71
|
+
length_bytes = read_exactly(3)
|
|
72
|
+
length = (length_bytes + "\x00").unpack1('L<')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
actual_length = length << 2
|
|
76
|
+
read_exactly(actual_length)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def read_exactly(bytes_needed)
|
|
80
|
+
result = ''.b
|
|
81
|
+
while result.bytesize < bytes_needed
|
|
82
|
+
chunk = @socket.read(bytes_needed - result.bytesize)
|
|
83
|
+
raise ConnectionError, 'EOF while reading' if chunk.nil? || chunk.empty?
|
|
84
|
+
|
|
85
|
+
result += chunk
|
|
86
|
+
end
|
|
87
|
+
result
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/mtproto/version.rb
CHANGED
data/lib/mtproto.rb
ADDED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mtproto
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Artem Levenkov
|
|
@@ -19,6 +19,9 @@ extra_rdoc_files: []
|
|
|
19
19
|
files:
|
|
20
20
|
- ".ruby-version"
|
|
21
21
|
- Rakefile
|
|
22
|
+
- lib/mtproto.rb
|
|
23
|
+
- lib/mtproto/transport/abridged_packet_codec.rb
|
|
24
|
+
- lib/mtproto/transport/tcp_connection.rb
|
|
22
25
|
- lib/mtproto/version.rb
|
|
23
26
|
homepage: https://github.com/alev-pro/mtproto-ruby
|
|
24
27
|
licenses:
|