When you connect using the TS3PHPFramework via the classic "raw" way to your TeamSpeak server in the non-blocking mode, so that you can use it as bot, everything works as expected. When you simply change the port and ssh=0 to ssh=1, the PHP script starts failing within less than 5 minutes. At least in my test scenario.
Add a new test.php script in the root folder with the following content:
<?php
// load framework files
require_once("vendor/autoload.php");
use PlanetTeamSpeak\TeamSpeak3Framework\Adapter\ServerQuery;
use PlanetTeamSpeak\TeamSpeak3Framework\Exception\TeamSpeak3Exception;
use PlanetTeamSpeak\TeamSpeak3Framework\Helper\Signal;
use PlanetTeamSpeak\TeamSpeak3Framework\Node\Server;
use PlanetTeamSpeak\TeamSpeak3Framework\TeamSpeak3;
class exceptionDebugging
{
private Server $ts3_VirtualServer;
function onWaitTimeout(int $idle_seconds, ServerQuery $serverquery)
{
// For debugging purposes
// Print every 30 seconds the current idle time of the bot connection.
if ($idle_seconds % 30 == 0) {
echo "No reply from the server for $idle_seconds seconds.\n";
}
// If the timestamp on the last query is more than 300 seconds (5 minutes) in the past, send 'keepalive'
// 'keepalive' command is just server query command 'clientupdate' which does nothing without properties. So nothing changes.
if ($serverquery->getQueryLastTimestamp() < time() - 260) {
echo 'Sending keep-alive.\n';
$serverquery->request('clientupdate');
}
// Get data every minute
if ($idle_seconds % 60 == 0) {
// Resetting lists
echo "Resetting lists...\n";
$this->ts3_VirtualServer->clientListReset();
$this->ts3_VirtualServer->serverGroupListReset();
// Get servergroup client info
echo "Getting client list...\n";
$this->ts3_VirtualServer->clientList(['client_type' => 0]);
echo "Getting servergroup list...\n";
$servergrouplist = $this->ts3_VirtualServer->serverGroupList(['type' => 1]);
echo "Getting servergroup client lists...\n";
$servergroup_clientlist = [];
foreach ($servergrouplist as $servergroup) {
$servergroup_clientlist[$servergroup->sgid] = count($this->ts3_VirtualServer->serverGroupClientList($servergroup->sgid));
}
// Get virtualserver info
echo "Getting info...\n";
$this->ts3_VirtualServer->getInfo(true, true);
echo "Getting connection info...\n";
$this->ts3_VirtualServer->connectionInfo();
}
}
function main()
{
echo "Connecting...\n";
try {
// Connect to the specified server, authenticate and spawn an object for the virtual server
$this->ts3_VirtualServer = TeamSpeak3::factory("serverquery://serveradmin:password@localhost:10011/?server_port=9987&ssh=0&blocking=0#no_query_clients");
} catch(TeamSpeak3Exception $e) {
// Print the error message returned by the server
die("Error " . $e->getCode() . ": " . $e->getMessage());
}
// Register for server events
echo "Register for server events...\n";
$this->ts3_VirtualServer->notifyRegister('server');
// Register a callback for serverqueryWaitTimeout events
echo "Subscribing to `serverqueryWaitTimeout`...\n";
Signal::getInstance()->subscribe('serverqueryWaitTimeout', $this->onWaitTimeout(...));
echo "Waiting for events...\n";
while (true) {
$this->ts3_VirtualServer->getAdapter()->wait();
}
}
}
$testing = new exceptionDebugging;
$testing->main();
When I run it with the TCP port 10011 (classic "raw") and the option ssh=0, everything works as expected - no issues:
$ time php test.php
Connecting...
Register for server events...
Subscribing to `serverqueryWaitTimeout`...
Waiting for events...
No reply from the server for 30 seconds.
No reply from the server for 30 seconds.
No reply from the server for 60 seconds.
...
Resetting lists...
Getting client list...
Getting servergroup list...
Getting servergroup client lists...
Getting info...
Getting connection info...
No reply from the server for 30 seconds.
No reply from the server for 60 seconds.
Resetting lists...
Getting client list...
Getting servergroup list...
Getting servergroup client lists...
Getting info...
Getting connection info...
No reply from the server for 30 seconds.
real 1180m10.935s
user 0m0.311s
sys 0m0.671s
As you can see: The script was running without any issues for over 19.5 hours (1180 minutes).
However, when you change the TCP port from 10011 to 10022 (encrypted SSH) and the option from ssh=0 to ssh=1 it fails for my TeamSpeak server mostly within 5 minutes:
$ time php test.php
Connecting...
Register for server events...
Subscribing to `serverqueryWaitTimeout`...
Waiting for events...
No reply from the server for 30 seconds.
No reply from the server for 60 seconds.
Resetting lists...
Getting client list...
Getting servergroup list...
Getting servergroup client lists...
PHP Fatal error: Uncaught PlanetTeamSpeak\TeamSpeak3Framework\Exception\ServerQueryException: invalid parameter. ident 'cldbid' does not exist in node '{"_identifier":"+GPk+IrgHZUQ7Vu6aY0mGgtseNw="}' in /home/Sebbo94BY/ts3phpframework/src/Adapter/ServerQuery/Reply.php:206
Stack trace:
#0 /home/Sebbo94BY/ts3phpframework/src/Node/Server.php(1286): PlanetTeamSpeak\TeamSpeak3Framework\Adapter\ServerQuery\Reply->toAssocArray('cldbid')
#1 /home/Sebbo94BY/ts3phpframework/test.php(47): PlanetTeamSpeak\TeamSpeak3Framework\Node\Server->serverGroupClientList(147)
#2 [internal function]: exceptionDebugging->onWaitTimeout(60, Object(PlanetTeamSpeak\TeamSpeak3Framework\Adapter\ServerQuery))
#3 /home/Sebbo94BY/ts3phpframework/src/Helper/Signal/Handler.php(77): call_user_func_array(Object(Closure), Array)
#4 /home/Sebbo94BY/ts3phpframework/src/Helper/Signal.php(75): PlanetTeamSpeak\TeamSpeak3Framework\Helper\Signal\Handler->call(Array)
#5 /home/Sebbo94BY/ts3phpframework/src/Transport/Transport.php(271): PlanetTeamSpeak\TeamSpeak3Framework\Helper\Signal->emit('serverqueryWait...', Array, Object(PlanetTeamSpeak\TeamSpeak3Framework\Adapter\ServerQuery))
#6 /home/Sebbo94BY/ts3phpframework/src/Transport/TCP.php(152): PlanetTeamSpeak\TeamSpeak3Framework\Transport\Transport->waitForReadyRead()#7 /home/Sebbo94BY/ts3phpframework/src/Adapter/ServerQuery.php(177): PlanetTeamSpeak\TeamSpeak3Framework\Transport\TCP->readLine()
#8 /home/Sebbo94BY/ts3phpframework/test.php(81): PlanetTeamSpeak\TeamSpeak3Framework\Adapter\ServerQuery->wait()
#9 /home/Sebbo94BY/ts3phpframework/test.php(87): exceptionDebugging->main()
#10 {main}
thrown in /home/Sebbo94BY/ts3phpframework/src/Adapter/ServerQuery/Reply.php on line 206
real 1m8.178s
user 0m0.156s
sys 0m0.052s
This issue is always reproducible for me.
Current behaviour
The bot works as expected via the classic "raw" connection.
The bot fails with the exception invalid parameter when it tries to get any list via a SSH connection.
Expected Behaviour
The bot should be properly able to get any list via a SSH connection as it does with the classic "raw" connection.
Additionals notes
This exception occurs for all *List() functions of the TS3PHPFramework
Sometimes it works and returns the lists as expected, but most of the time it fails. Maybe an issue with the TCP buffer or so?
I've already tested in a temporary written PHPUnit test, if longer (e. g. 556 clients as member of a servergroup) and especially the here returned response can be properly parsed by the TS3PHPFramework and yes, it works as expected - otherwise the classic "raw" connection would also fail. So we have two checks here. :)
It looks like as the SSH TCP connection does not get the full response (line): invalid parameter. ident 'cldbid' does not exist in node '{"_identifier":"+GPk+IrgHZUQ7Vu6aY0mGgtseNw="} (the node looks always a bit different, but always incomplete like this one)
Simply setting @stream_set_blocking($this->stream, true); does unfortunately not solve the issue. Instead it stucks in a very CPU intensive endless loop, where var_dump($data) returns bool(false). So it does somehow not break / exit the while() loop.
Summary
When you connect using the TS3PHPFramework via the classic "raw" way to your TeamSpeak server in the non-blocking mode, so that you can use it as bot, everything works as expected. When you simply change the port and
ssh=0
tossh=1
, the PHP script starts failing within less than 5 minutes. At least in my test scenario.Environment
dev
:83a2ffaace6073ca2589881a764625f2993996bc
)ssh2
1.4How to reproduce
dev
branchcomposer install
test.php
script in the root folder with the following content:When I run it with the TCP port
10011
(classic "raw") and the optionssh=0
, everything works as expected - no issues:As you can see: The script was running without any issues for over 19.5 hours (1180 minutes).
However, when you change the TCP port from
10011
to10022
(encryptedSSH
) and the option fromssh=0
tossh=1
it fails for my TeamSpeak server mostly within 5 minutes:This issue is always reproducible for me.
Current behaviour
The bot works as expected via the classic "raw" connection.
The bot fails with the exception
invalid parameter
when it tries to get any list via a SSH connection.Expected Behaviour
The bot should be properly able to get any list via a SSH connection as it does with the classic "raw" connection.
Additionals notes
*List()
functions of the TS3PHPFrameworkinvalid parameter. ident 'cldbid' does not exist in node '{"_identifier":"+GPk+IrgHZUQ7Vu6aY0mGgtseNw="}
(the node looks always a bit different, but always incomplete like this one)ssh=1
, we use the PHP functionsssh2_connect()
andssh2_shell()
: https://github.com/planetteamspeak/ts3phpframework/blob/83a2ffaace6073ca2589881a764625f2993996bc/src/Transport/TCP.php#L82fwrite()
: https://github.com/planetteamspeak/ts3phpframework/blob/83a2ffaace6073ca2589881a764625f2993996bc/src/Transport/TCP.php#L182fgets()
: https://github.com/planetteamspeak/ts3phpframework/blob/83a2ffaace6073ca2589881a764625f2993996bc/src/Transport/TCP.php#L154blocking=0
: https://github.com/planetteamspeak/ts3phpframework/blob/83a2ffaace6073ca2589881a764625f2993996bc/src/Adapter/ServerQuery.php#L169-L171ssh2_shell()
a comment mentions, thatstream_set_blocking()
should be set totrue
, but we always set it tofalse
: https://github.com/planetteamspeak/ts3phpframework/blob/83a2ffaace6073ca2589881a764625f2993996bc/src/Transport/TCP.php#L90@stream_set_blocking($this->stream, true);
does unfortunately not solve the issue. Instead it stucks in a very CPU intensive endless loop, wherevar_dump($data)
returnsbool(false)
. So it does somehow not break / exit thewhile()
loop.