38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
# File 'lib/mtproto/client/rpc.rb', line 38
def call_sync(body, content_related: true)
raise 'Auth key not generated' unless @client.auth_key
raise 'Session not initialized' unless @client.session
msg_id = MessageId.generate(time_offset: @client.time_offset)
seq_no = @client.session.next_seq_no(content_related: content_related)
encrypted_msg = EncryptedMessage.encrypt(
auth_key: @client.auth_key,
server_salt: @client.server_salt,
session_id: @client.session.session_id,
msg_id: msg_id,
seq_no: seq_no,
body: body
)
@client.connection.send(encrypted_msg.serialize)
response_data = @client.connection.recv(timeout: @client.timeout)
decrypted = EncryptedMessage.decrypt(
auth_key: @client.auth_key,
encrypted_message_data: response_data,
sender: :server
)
response_body = decrypted[:body]
constructor = response_body[0, 4].unpack1('L<')
if constructor == CONSTRUCTOR_BAD_SERVER_SALT
offset = 4
offset += 8
offset += 4
offset += 4
new_server_salt = response_body[offset, 8].unpack1('Q<')
update_server_salt(new_server_salt)
return call_sync(body, content_related: content_related)
end
if constructor == Type::NewSessionCreated::CONSTRUCTOR
session_info = Type::NewSessionCreated.deserialize(response_body)
update_server_salt(session_info.server_salt)
response_data = @client.connection.recv(timeout: @client.timeout)
decrypted = EncryptedMessage.decrypt(
auth_key: @client.auth_key,
encrypted_message_data: response_data,
sender: :server
)
response_body = decrypted[:body]
constructor = response_body[0, 4].unpack1('L<')
end
if constructor == Type::MsgContainer::CONSTRUCTOR
container = Type::MsgContainer.deserialize(response_body)
rpc_result = container.messages.find do |msg|
msg[:body][0, 4].unpack1('L<') == CONSTRUCTOR_RPC_RESULT
end
return (rpc_result[:body][12..]) if rpc_result
new_session = container.messages.find do |msg|
msg[:body][0, 4].unpack1('L<') == Type::NewSessionCreated::CONSTRUCTOR
end
if new_session
session_info = Type::NewSessionCreated.deserialize(new_session[:body])
update_server_salt(session_info.server_salt)
other_messages = container.messages.reject do |msg|
constructor = msg[:body][0, 4].unpack1('L<')
(
constructor == Type::NewSessionCreated::CONSTRUCTOR ||
constructor == CONSTRUCTOR_MSGS_ACK
)
end
return other_messages.first[:body] unless other_messages.empty?
response_data = @client.connection.recv(timeout: @client.timeout)
decrypted = EncryptedMessage.decrypt(
auth_key: @client.auth_key,
encrypted_message_data: response_data,
sender: :server
)
response_body = decrypted[:body]
constructor = response_body[0, 4].unpack1('L<')
return (response_body[12..]) if constructor == CONSTRUCTOR_RPC_RESULT
if constructor == Type::MsgContainer::CONSTRUCTOR
container = Type::MsgContainer.deserialize(response_body)
rpc_result = container.messages.find do |msg|
msg[:body][0, 4].unpack1('L<') == CONSTRUCTOR_RPC_RESULT
end
return (rpc_result[:body][12..]) if rpc_result
end
return response_body
end
return container.messages.first[:body]
end
return (response_body[12..]) if constructor == CONSTRUCTOR_RPC_RESULT
response_body
end
|