tsclientlib icon indicating copy to clipboard operation
tsclientlib copied to clipboard

Cannot join TeaSpeak server

Open zumoshi opened this issue 4 years ago • 12 comments

Using git url in Cargo.toml: tsclientlib = { git = "https://github.com/ReSpeak/tsclientlib", default-features = false } With simple example the bot connects (can be seen in the server) but immidieltly crashes and times out.

Log:

May 10 21:07:32.341 INFO TsClientlib, tsproto-version: 0.1.0+135 (5facf71ad 2020-04-25) dirty 1 modification, profile: Debug, version: 0.1.0+135 (5facf71ad 2020-04-25) dirty 1 modification
addr: 213.232.x.x:8600
 module: resolver
  May 10 21:07:32.381 DEBG Starting resolve, address: 213.232.x.x:8600
 May 10 21:07:32.383 DEBG Connecting, address: 213.232.x.x:8600
 local_addr: 0.0.0.0:62709
  remote_addr: 213.232.x.x:8600
   May 10 21:07:32.500 INFO Solve RSA puzzle, y: 8723936990881646971634718538142609102355251916986973944432589766401949068486423461886395290859036201612429790782526491046960631694579471096541769720493184, n: 11123400745562958910244492490827953852572440103989553562167402963531575601608560797501435186671157100790399862727380181776554078832306932328534646034810183, x: 2734392063954191350664097231331798576250127772103965844421157207037545396495144005205222611970307297540547386323150397440565322634966676290871737460374830, level: 1000
   name: Solve RSA puzzle
    May 10 21:07:32.508 INFO time report, : 0.066709387
   May 10 21:07:32.676 WARN Out of order command packet, expected: 11, got: 12
 May 10 21:07:32.770 INFO Connecting failed, trying next address, error: Parameter PermissionId not found in PermList
Error: Failed to connect to server, address Other("213.232.x.x:8600") did not work

Full backtrace: gist

Tested with: TeaSpeak 1.4.12 TeaSpeak 1.3.25 TeamSpeak 3.12.1 (works fine)

Should I give you access to the server or provide more info? thanks.

zumoshi avatar May 10 '20 16:05 zumoshi

Thanks for the report. TeaSpeak sends the notifypermissionlist before the initserver, which caused the weird error message. Apart from that, some arguments are not sent on TeaSpeak (e.g. the PermissionId, server nickname and others). Those should be fixed, connecting seems to work now.

There will still be warnings, e.g. because TeaSpeak does not send a cliententerview for the connecting client itself, so the own client will never be added to the client list.

For future reference, I needed to change the following things in TeaSpeak to be able to connect: Set experimental_31: 1 and put a TS license into protocol_key.txt.

Flakebi avatar May 10 '20 22:05 Flakebi

Thanks for the quick fix. It connects fine now (i.e. it doesn't crash and time out).

For future reference ... experimental_31: 1

I do have that, I was connecting to the test server with official ts3 client version 3.5.2 TS3Audiobot (which if I understand correctly shares the tsdeclarations with this project) also had no trouble connecting to the test server.

TeaSpeak does not send a cliententerview for the connecting client itself

Yes, I still seem to have issues with teaspeak. While it doesn't drop anymore, the same code that works with teamspeak still fails in teaspeak. Should I open a separate issue or keep discussing it here?

The code I have is a modified version of the simple example that prints events to console, e.g.:

Some(Ok(ConEvents([PropertyChanged { id: ClientAwayMessage(ClientId(31)), old: OptionString(None), invoker: None }])))
Some(Ok(ConEvents([PropertyChanged { id: ClientAwayMessage(ClientId(31)), old: OptionString(Some("")), invoker: None }])))

But on teaspeak it doesn't print any events and outputs this error:

May 11 13:07:48.618 WARN Unknown argument, argument: Ok("virtualserver_default_music_group"), command: InitServer
 May 11 13:07:48.621 WARN Unknown argument, argument: Ok("virtualserver_default_channel_admin_group"), command: InitServer
 May 11 13:07:48.624 WARN Unknown argument, argument: Ok("virtualserver_weblist_enabled"), command: InitServer
 May 11 13:07:48.627 WARN Unknown argument, argument: Ok("virtualserver_country_code"), command: InitServer
 May 11 13:07:48.629 WARN Failed to parse message, error: ParseUid { arg: "InvokerUid", value: "undefined", source: InvalidLength }
Some(Ok(ConEvents([ChannelListFinished])))
 May 11 13:07:48.658 DEBG Unhandled message, message: notifyclientneededpermissions
 May 11 13:07:48.663 WARN Unknown argument, argument: Ok("client_channel_group_inherited_channel_id"), command: ClientUpdated
 May 11 13:07:48.665 WARN Unknown argument, argument: Ok("client_channel_group_id"), command: ClientUpdated
 May 11 13:07:49.141 WARN Failed to handle message, error: Client 4 not found

full trace: gist

zumoshi avatar May 11 '20 08:05 zumoshi

Should I open a separate issue or keep discussing it here?

Keeping this issue is fine.

TS3Audiobot (which if I understand correctly shares the tsdeclarations with this project) also had no trouble connecting to the test server.

Right, it seems to be more relaxed about when the initserver is sent (and uses a slightly older version of the declarations). Though I heard some problems there might also stem from the missing cliententerview.

I think the cleanest way would be if TeaSpeak would send the cliententerview to the joining client too as this is what the official server does @WolverinDEV :)

Flakebi avatar May 11 '20 09:05 Flakebi

TeaSpeak sends the notifypermissionlist before the initserver, which caused the weird error message.

Yes that's right, but except here it does not causes any issues at all ;)

TeaSpeak does not send a cliententerview for the connecting client itself

TeaSpeak sends a notifycliententerview for the own client. It sends it right with sending the channel tree (notifychannellist). Firstly it sends all parent channels and the channel the client is actually joined, then it sends the own notifycliententerview and thirdly it sends the rest of the channel tree.

WolverinDEV avatar May 11 '20 09:05 WolverinDEV

@Flakebi As addition would you mind to implement the parsing of the "root" key attribute in initivexpand2 command? This would allow to join TeaSpeak ignoring of the config settings. (The root property contains the base64 encoded public ed25515 base key)

WolverinDEV avatar May 11 '20 10:05 WolverinDEV

Thanks for your comments Wolverin.

Yes that's right, but except here it does not causes any issues at all ;)

Right, I guess I need to write my code in a more generic way.

TeaSpeak sends a notifycliententerview for the own client.

Hm ok, I’ll look again this evening.

Re root argument: Interesting way to … solve this problem, I guess I’ll add that ;)

Flakebi avatar May 11 '20 11:05 Flakebi

If you need any assistance, feel free to join my TS ;)

Yes the root approach is an interesting one.
BTW does your library support the "old" handshake? Since that's what TeaSpeak usually uses.
As well you should may think about the ability to send commands before the client init. TeaSpeak has a custom authentication step, since its not only support TS - Identities. The idea there is also to create an API to allow other authentication endpoints as well, like connect via Steam etc...

Sadly the commands are not yet documented, but it basically works like this:

  1. > clientinitiv alpha=... omega=... ip=... -teaspeak
    (-teaspeak will automatically switch to the old handshake)
  2. < initivexpand alpha=... beta=... omega=... teaspeak=1
    (teaspeak=1 only set if -teaspeak is provided)
  3. > handshakebegin intention=0 authentication_method=<method> [.... method depending data]
  4. < handshakeidentityproof [... method depending data]
  5. > handshakeidentityproof [... method depending data]
  6. > clientinit ...

WolverinDEV avatar May 11 '20 11:05 WolverinDEV

Ah, I see now that invokerid=0 invokername=undefined invokeruid=undefined is sent while the TeamSpeak server just omits them. The uid failed to parse as a valid uid of course.

BTW does your library support the "old" handshake? Since that's what TeaSpeak usually uses.

No, I threw that out a few weeks ago as all TeamSpeak programs are incompatible with it since a while and it is less secure (no perfect-forward-secrecy).

Hm, TeamSpeak also has additional authentications (myteamspeak), though I think this is done after the connection is completely established.

Anyway, things should be working better now.

Flakebi avatar May 11 '20 19:05 Flakebi

Thanks for the quick work. The new version doesn't throw any errors. I'm testing to see if I can find any other differences between ts/tea. So far Poke doesn't seem to want to parse on Teaspeak.

May 12 09:43:00.770 DEBG UdpPacket, header: Header(mac: Hex[9e ab 2a 23 5e 31 14 02], id: 0x23, Command, -c--)
   May 12 09:43:00.774 DEBG Packet, content: Packet(Header(mac: Hex[9e ab 2a 23 5e 31 14 02], id: 0x23, Command, -c--), "notifyclientpoke invokerid=2 invokername=bor invokeruid=M8QUkY1Fx43ItB66HFFr0CimBDo= msg=asd")
  dir: OUT
   May 12 09:43:00.779 DEBG Packet, content: Packet(Header(id: 0x0, c_id: 0x0, Ack, ----), 0x0023)
   May 12 09:43:00.783 DEBG UdpPacket, header: Header(mac: Hex[4f e7 dd 1d 0a 1b 7f 2d], id: 0x23, c_id: 0x4, Ack, ----), generation: 0
 May 12 09:43:00.788 WARN Failed to parse message, error: WrongPacketType(Command)

The only difference I found was that on teamspeak the packet log is prefixed by CommandLow while on Teaspeak it's just Command.

Another difference seems to be that on teaspeak it doesn't subscribe to startup channel's events by default. (e.g. I won't get any notifyclientupdated logs if I toggle my own away status). It seems to get fixed if I move the bot to another channel and back though. But on Teamspeak it gets all events correctly from the start.

zumoshi avatar May 12 '20 05:05 zumoshi

To subscribe to all channel use channelsubscribeall after connecting. Or use the bookkeeping Server struct and call set_subscribed(true) to subscribe to all (it will use channelsubscribeall)

Splamy avatar May 12 '20 14:05 Splamy

No, I threw that out a few weeks ago

Uff that's quite bad especially since the new handshake isn't enabled by default since its "experimental_31"

WolverinDEV avatar May 12 '20 16:05 WolverinDEV

To subscribe to all channel use channelsubscribeall after connecting. Or use the bookkeeping Server struct and call set_subscribed(true) to subscribe to all (it will use channelsubscribeall)

‘After connecting’ means you should subscribe after the ChannelListFinished event, otherwise you might miss some channels (at least on official servers)

Flakebi avatar May 12 '20 18:05 Flakebi