td
td copied to clipboard
Wasm: failed to open connection
I am trying to implement TDLib client for NodeJS with WebAssembly. Everything works fine before I send setAuthenticationPhoneNumber
request. Then I receive an error: Failed to open connection
.
Can you advise something?
Settings:
tdlibParameters {
use_test_dc = true
database_directory = "./dev/db"
files_directory = ""
use_file_database = false
use_chat_info_database = false
use_message_database = false
use_secret_chats = false
api_id = xxx
api_hash = "xxx"
system_language_code = "en"
device_model = "UNKNOWN DEVICE"
system_version = "UNKNOWN VERSION"
application_version = "0.1.0"
enable_storage_optimizer = false
ignore_file_names = false
}
Log:
[ 3][t 0][1562392992.641999960][Td.cpp:3285][!Td][&td_requests] Receive request 5: setAuthenticationPhoneNumber {
phone_number = "xxx"
allow_flash_call = false
is_current_phone_number = false
}
[ 4][t 0][1562392992.641999960][utils.cpp:21][!AuthManager] Create storer for auth_sendCode {
flags = 0
phone_number = "xxx"
api_id = xxx
api_hash = "xxx"
}
[ 3][t 0][1562392992.641999960][NetQuery.h:347][!AuthManager] [Query:[id:196608][tl:0x86aef0ec][state:Query]]
[ 3][t 0][1562392992.641999960][NetQuery.h:239][!AuthManager][&net_query] [Query:[id:196608][tl:0x86aef0ec][state:Query]] [debug:dispatch]
[ 3][t 0][1562392992.641999960][NetQuery.h:239][!AuthManager][&net_query] [Query:[id:196608][tl:0x86aef0ec][state:Query]] [debug:sent to main session multi proxy DcId{2}]
[ 3][t 0][1562392992.641999960][NetQuery.h:239][!SessionMultiProxy:2:main][&net_query] [Query:[id:196608][tl:0x86aef0ec][state:Query]] [debug:SessionMultiProxy:2:main: send to proxy #0]
[ 3][t 0][1562392992.643000126][NetQuery.h:239][!SessionProxy:2:main][&net_query] [Query:[id:196608][tl:0x86aef0ec][state:Query]] [debug:SessionProxy:2:main: sent to session]
[ 3][t 0][1562392992.643000126][NetQuery.h:239][!Session:2:main][&net_query] [Query:[id:196608][tl:0x86aef0ec][state:Query]] [debug:Session: received from SessionProxy]
[ 3][t 0][1562392992.643000126][Session.cpp:230][!Session:2:main][&net_query] Got query [Query:[id:196608][tl:0x86aef0ec][state:Query]]
[ 3][t 0][1562392992.643000126][NetQuery.h:239][!Session:2:main][&net_query] [Query:[id:196608][tl:0x86aef0ec][state:Query]] [debug:Session: pending]
[ 3][t 0][1562392993.563000202][StateManager.cpp:139][!State manager] Auto set net_type = Other
[ 3][t 0][1562392993.563000202][ConnectionCreator.cpp:754][!ConnectionCreator][&connections] Receive network flag true with generation 1
[ 3][t 0][1562392993.564000130][ConnectionCreator.cpp:759][!ConnectionCreator][&connections] Set proxy query token to 0: 1 1
[ 3][t 0][1562392993.564000130][ConnectionCreator.cpp:925][!ConnectionCreator][&connections] In client_loop: [client:0x5e69d1ad]
[ 3][t 0][1562392993.564000130][ConfigManager.cpp:559][!Recoverer][&config_recoverer] Failed to connect for 0.998419
[ 3][t 0][1562392993.564000130][ConfigManager.cpp:619][!Recoverer][&config_recoverer] Wakeup in 4001.6ms
[ 2][t 0][1562392993.932000160][Session.cpp:1121][!Session:2:main::HandshakeActor] Failed to open connection: [Error : 0 : Connection closed : [172.29.2.0:443] to DcId{2} from [0.0.0.0:0]]
Full log: wasm.log
Could you check in Developer tools on Network tab, why the connection is closed?
The idea is using wasm
module in NodeJS (https://github.com/airgram/airgram/issues/36), so I run script from console, not in browser. Should WebAssembly module work in server environment?
No, it shouldn't, because it expects that all netwotk connection are automatically wrapped with the WebScoket protocol.
From Node.js you can use ordinary JSON TDLib interface, for example, see tdl.
As far as I can see, the creation of ws
client is provided for Node.js. Doesn't it?
td_wasm.js#3159:
var WebSocketConstructor
if (ENVIRONMENT_IS_NODE) {WebSocketConstructor = require('ws')} else if (ENVIRONMENT_IS_WEB) {WebSocketConstructor = window['WebSocket']} else {WebSocketConstructor = WebSocket}
ws = new WebSocketConstructor(url, opts)
ws.binaryType = 'arraybuffer'
From Node.js you can use ordinary JSON TDLib interface, for example, see tdl.
Client with JSON TDLib interface has already been implemented: Airgram. But there are 2 caveats:
- this interface doesn't work out of the box, because everyone has to build
tdlib
by themselves. - Multiple clients running at the same time will not work properly due
ffi-napi
restriction: "It is recommended to avoid any multi-threading usage of this library if possible."
Probably, something is still wrong with establishing secure WebSocket connection as it's automatically done in the WebBrowser. You can try to investigate, what is going on, through Wireshark.
I could not see any WebSocket packets in Wareshark log.
Do ip addresses 172.29.1.0
, 172.29.2.0
and 172.29.3.0
look correct?
[ 3][t 0][1562673517.459000111][IPAddress.cpp:404][!ConnectionCreator] Try to init IP address of pluto.web.telegram.org/apiws_test with port 443
[ 3][t 0][1562673517.463000059][IPAddress.cpp:469][!ConnectionCreator] Have address 172.29.1.0 with port 443
[ 3][t 0][1562673517.464999914][IPAddress.cpp:404][!ConnectionCreator] Try to init IP address of venus.web.telegram.org/apiws_test with port 443
[ 3][t 0][1562673517.467000246][IPAddress.cpp:469][!ConnectionCreator] Have address 172.29.2.0 with port 443
[ 3][t 0][1562673517.467000246][IPAddress.cpp:404][!ConnectionCreator] Try to init IP address of aurora.web.telegram.org/apiws_test with port 443
[ 3][t 0][1562673517.467000246][IPAddress.cpp:469][!ConnectionCreator] Have address 172.29.3.0 with port 443
[ 3][t 0][1562673517.468000174][ConfigManager.cpp:561][!Recoverer][&config_recoverer] Successfully connected
[ 3][t 0][1562673517.468000174][ConfigManager.cpp:622][!Recoverer][&config_recoverer] Wakeup NEVER
Client can't connect to those ip addresses:
[ 3][t 0][1562673134.707000256][ConnectionCreator.cpp:1150][!ConnectionCreator] [hash:0x5e69d1ad] wakeup
[ 3][t 0][1562673134.707000256][ConnectionCreator.cpp:925][!ConnectionCreator][&connections] In client_loop: [client:0x5e69d1ad]
[ 3][t 0][1562673134.708000183][ConnectionCreator.cpp:903][!ConnectionCreator] Create: [172.29.2.0:443] to DcId{2}
[ 3][t 0][1562673134.710000277][ConnectionCreator.cpp:1074][!ConnectionCreator][&connections] In client_loop: create new direct connection [172.29.2.0:443] to DcId{2} from [0.0.0.0:0]
[ 3][t 0][1562673134.710000277][ConnectionCreator.cpp:1127][!ConnectionCreator][&connections] [client:0x5e69d1ad] set timeout in 15.992135
[ 3][t 0][1562673134.710000277][ConnectionCreator.cpp:1112][!ConnectionCreator][&connections] Start check: [172.29.2.0:443] to DcId{2} from [0.0.0.0:0]
[ 3][t 0][1562673134.711000204][RawConnection.cpp:55][!PingActor<[172.29.2.0:443] to DcId{2} from [0.0.0.0:0]>] Send handshake packet:
00000000 00000000 00000001 00000000 00000070 be7e8ef1 71ed3115 44517e30 ef0ae14e 4d41d9e3 2dc3d35b 39738ec2 fbc2ede7 4ead162e 40d9bdd8 49c34802
385f2ebc 627f8ab8 268265e9 76955326 f6aa2407 a49bb69d 481cdbd8 e6e31bad a709658f f9b1cd11 cd8a5569 188ef801 521be403 dabfd4fe 08186eff 543f8a78
eb830bb0
[ 3][t 0][1562673136.496999979][ConnectionCreator.cpp:1093][!PingActor<[172.29.2.0:443] to DcId{2} from [0.0.0.0:0]>][&connections] Failed connection (checked) [Error : 0 : Connection closed] [172.29.2.0:443] to DcId{2} from [0.0.0.0:0]
Ping result:
PING 172.29.2.0 (172.29.2.0): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
Request timeout for icmp_seq 3
Request timeout for icmp_seq 4
Request timeout for icmp_seq 5
^C
--- 172.29.2.0 ping statistics ---
7 packets transmitted, 0 packets received, 100.0% packet loss
@esindger 172.29.1.0 and other are not valid addresses. They are generated as placeholders for connection ID by Emscripten and translated by Emscripten to real URLs and IPs.
Do you have any idea what is wrong and how to fix it? Maybe I should create a simple repo, so you can check the connection issue?
The difference is somewhere in way a TCP stream is wrapped into Secure WebSocket connection in browsers and Node.JS. It's hard to tell, where is exactly the problem, without researching source code of Emscripten and Node.JS ws library or dumping network requests, so this needs some investigation.
It would be nice, if the next TDLib release has fully support of wasm
for NodeJS, then we could use it instead of ffi-napi
and solve some issues like #643.
@esindger I will have no time to look at that before the next release. Between, by default WASM is built without threads support either.
I managed to get it to work on Node.js.
- browser:

- node:

The issue is that ws
doesn't send the Sec-WebSocket-Protocol
header.
I looked into the code the code that emscripten has generated in the td_wasm.js
file:
opts = ENVIRONMENT_IS_NODE ? {
"protocol": subProtocols.toString(),
} : subProtocols
// ...
WebSocketConstructor = require("ws")
// ...
ws = new WebSocketConstructor(url, opts);
ws.binaryType = "arraybuffer"
ws
doesn't support the 'protocol' option anymore: docs. It should be passed in the second argument.
So, Emscripten is not intended to work with the latest ws
. It works correctly with ws@2
(which was released in 2017).
I also got it to work with these patches on the latest ws
7.4.0:
-subProtocols = subProtocols.replace(/^ +| +$/g, "").split(/ *, */);
-opts = ENVIRONMENT_IS_NODE ? {
- "protocol": subProtocols.toString(),
-} : subProtocols
+subProtocols = subProtocols.replace(/^ +| +$/g, "").split(/ *, */);
+opts = subProtocols
-peer.socket.on("message", function(data, flags) {
- if (!flags.binary) {
- return
- }
- handleMessage(new Uint8Array(data).buffer)
-});
+peer.socket.on("message", function(data) { // (the flags argument doesn't exist anymore)
+ handleMessage(new Uint8Array(data).buffer)
+});
It seems to work, but note that something might be broken.
Also, WebAssembly should make it much easier to run TDLib in Node.js. Since Node.js exports OpenSSL symbols, TDLib (at least dynamically linked) uses the symbols from the node.js binary and not from the system. This requires either building TDLib with the exact same openssl version that the pre-built Node.js is linked against, or re-building Node.js with linking against the system openssl. I've also had random segfaults after some time running, even when only the letter in the openssl versions differs, so no more different openssl versions for me.
@Bannerets Awesome! Could you report this to Emscripten developers, so they can support the latest ws
?
I opened an issue in the emscripten repository: https://github.com/emscripten-core/emscripten/issues/12813