-
Notifications
You must be signed in to change notification settings - Fork 35
the "socket closed" and other issues - with free demo content #59
Comments
i came up with a few new ideas and tested those.
function isConnected() {
if( !$this->runtime['socket'] || !@fputs($this->runtime['socket'], "\n") ){
if( is_resource( $this->runtime['socket'] ) ){
$this->runtime['socket'] = $this->runtime['bot_clid'] = '';
@fclose( $this->runtime['socket'] );
}
return false;
}
return true;
} refactored
do {
$data .= @fgets($this->runtime['socket'], 4096);
if(strpos($data, 'error id=3329 msg=connection') !== false) {
$this->runtime['socket'] = $this->runtime['bot_clid'] = '';
$this->addDebugLog('You got banned from server. Socket closed.', $tracert[1]['function'], $tracert[0]['line']);
return $this->generateOutput(false, array('You got banned from server. Connection closed.'), false);
}
} while(strpos($data, 'msg=') === false or strpos($data, 'error id=') === false); i would suggest you test it in your env's and perhaps it will fit your expectations too to get in a future PR, if you dont find the time, let me know, i will prepare a current PR based on this research. some other stuff missing imho: /**
* clearDebugLog
*
* Clears the debug log
*
* @author Stefan Zehnpfennig
* @return empty array debugLog
*/
public function clearDebugLog() {
return $this->runtime['debug']=[];
} modified the debug output to contain a timestamp, when something happens, we should know when it happend. /**
* addDebugLog
*
* Adds an entry to debugLog
*
* @author Stefan Zehnpfennig
* @param string $text text which should added to debugLog
* @param string $methodName name of the executed method [optional]
* @param string $line line where error triggered [optional]
* @return void
*/
private function addDebugLog($text, $methodName = '', $line = '') {
if(empty($methodName) and empty($line)) {
$backtrace = debug_backtrace();
$methodName = $backtrace[1]['function'];
$line = $backtrace[0]['line'];
}
$this->runtime['debug'][] = date( 'Y-m-d H:i:s' ) . ' Error in '.$methodName.'() on line '.$line.': '.$text;
}
} ahhh and last not least: private function getData($mode, $command) {
$validModes = array('boolean', 'array', 'multi', 'plain');
if(!in_array($mode, $validModes)) {
$this->addDebugLog($mode.' is an invalid mode');
return $this->generateOutput(false, array('Error: '.$mode.' is an invalid mode'), false);
}
if(empty($command)) {
$this->addDebugLog('you have to enter a command');
return $this->generateOutput(false, array('Error: you have to enter a command'), false);
}
$fetchData = $this->executeCommand($command, debug_backtrace());
$fetchData['data'] = str_replace(array('error id=0 msg=ok', chr('01')), '', $fetchData['data']);
if($fetchData['success']) {
if($mode == 'boolean') {
return $this->generateOutput(true, array(), true);
}
if($mode == 'array' || $mode == 'multi'){
if(empty($fetchData['data'])) { return $this->generateOutput(true, array(), array()); }
$datasets = explode('|', $fetchData['data']);
$output = array();
foreach($datasets as $datablock) {
$datablock = explode(' ', $datablock);
$tmpArray = array();
foreach($datablock as $dataset) {
$dataset = explode('=', $dataset, 2);
$tmpArray[ $this->unEscapeText($dataset[ 0 ]) ] = isset( $dataset[ 1 ] ) ? $this->unEscapeText( $dataset[ 1 ] ) : '';
}
if($mode == 'array'){
return $this->generateOutput(true, array(), $tmpArray);
}
$output[] = $tmpArray;
}
return $this->generateOutput(true, array(), $output);
}
if($mode == 'plain') {
return $fetchData;
}
}else{
return $this->generateOutput(false, $fetchData['errors'], false);
}
} |
as i expected, the
/**
* readChatMessage
*
* Read chat message by its type (Result: http://bit.ly/2dtBXnT)
*
* IMPORTANT: Check always for message success, sometimes you can get an empty message
* and it will return empty data
*
* <b>Output:</b>
* <pre>
* Array
* {
* [invokerid] => 37
* [invokeruid] => /jl8QCHJWrHDKXgVtF+9FX7zg1E=
* [invokername] => toxiicdev.net
* [msg] => It's just a prank bro
* [targetmode] => 3
* }
* </pre>
* @author toxiicdev
* @param string $type textserver|textchannel|textprivate
* @param boolean $keepalive default false
* @param int $cid channel id (required only for textchannel)
* @return array data
*/
public function readChatMessage($type = 'textchannel', $keepalive = false, $cid = -1)
{
$tracert = debug_backtrace();
$availTypes = array('textserver', 'textchannel', 'textprivate');
$rtnData = array('success' => 0, 'data' => array('invokerid' => '', 'invokeruid' => '', 'invokername' => '', 'msg' => '', 'targetmode' => ''));
if(!$this->isConnected()) {
$this->runtime['socket'] = $this->runtime['bot_clid'] = '';
$this->addDebugLog('script isn\'t connected to server', $tracert[1]['function'], $tracert[0]['line']);
return $this->generateOutput(false, array('script isn\'t connected to server'), false);
}
if(!in_array($type, $availTypes)) {
$this->addDebugLog('Invalid passed read type', $tracert[1]['function'], $tracert[0]['line']);
return $rtnData;
}
if(!$this->runtime['selected']) { return $this->checkSelected(); }
$whoami = $this->whoami();
if(!$whoami['success']) { return $whoami; }
if($type == 'textchannel' && $whoami['data']['client_channel_id'] != $cid)
{
$this->clientMove($this->getQueryClid(), $cid);
}
$this->executeCommand("servernotifyregister event=$type" . ($cid != -1 ? " id=$cid" : "") , null);
$data = fgets($this->runtime['socket'], 4096);
if(!empty($data))
{
$rtnData['success'] = 1;
$msgData = explode(" ", $data);
foreach($msgData as $param)
{
$paramData = explode("=", $param);
if(array_key_exists($paramData[0], $rtnData['data']))
{
$rtnData['data'][$paramData[0]] = $this->unescapeText(implode("=", array_slice($paramData, 1, count($paramData) -1)));
}
}
}
if(!$keepalive) $this->serverNotifyUnregister();
return $rtnData;
} |
imho |
Hey @MINORITYmaN thanks for your work! could you create a new pull request with all these changes? |
hi @par0noid, |
this seemed very interesting and quite important - any news since? |
Looks like @par0noid ist currently inactive. We need to wait until he will be back. @MINORITYmaN is it possible to create also a pull request on my fork? I´ve changed a bit of the class for ssh support. |
I'm sorry for my inactivity. Got a lot to do at work. I invited you @lgund to collaborate on this repo. You seem to be very active and competent. @lgund Ich weiß nicht ob du wirklich Interesse dran hast hier ein wenig zu "administrieren" und Pull-Requests zu bestätigen (nach Prüfung natürlich), oder vielleicht auch Code zu ändern. Ich weiß nur leider aktuell nicht wo ich die Zeit her nehmen soll 😢 Hab auch leider ein bisschen den Eindruck gewonnen, dass Teamspeak 3 irgendwie nicht mehr so viel "Sinn" macht, Jeder scheint Discord zu nutzen und Teamspeak 5 ist ja auch im Gespräch. Dazu kommt noch, dass dieser Programmierstil ohne OOP von 2009 überhaupt nicht mehr meiner Natur entspricht, man entwickelt sich ja auch weiter. Fühle mich ein bisschen als ob ich das Projekt nur noch durch sporadische Updates "am Leben halte". Falls du also Interesse hast, erstelle ich gerne bei Versionswechseln eine neue Doku und aktualisiere die Homepage - für mehr hab ich leider aktuell nicht die Zeit 😭 |
Da TeamSpeak 5 wird sich gegenuber TeamSpeak 3 beim Server nicht großartig ändern. Ich kann dieses repro gerne supporten solange du keine Zeit hast. Mach dir keine Sorgen wegen oop. Finde den Stil bei php völlig überflüssig. Aber habe eh allgemein kein gutes Bild von php. |
Any update on this topic? I really need this fix :D |
hi there,
some long time ago #33 had some suggestions and there was even a discussion #3
lets get it on
in case class is used for a bot in daemon mode (runs infinite in the backbround doing his assigned tasks)
did you know, that this line
if(empty($data))
d9f7d46#diff-6d8bfb1cf539d16b81e45de812c980cbR4285
will never get evaluated if the socket dies (server restart, server stop, crash)?
the loop will stuck in a endless fgets, cpu core will go 100%, i metioned this issue allrady here #33
but it got ignored, and surprisingly nothing changed since then.
you cant read any data if there is no resource socket, its a blackhole endless loop.
if you dont belive, try it out, use this and turn the server off after 10 sec, and watch your bots/scripts CPU load and watch your console.
on server "crash" we should see in the console
but as you see, we see nothing, only our CPU goes crazy.
my solution below:
check if the socket is still alive and not at its end of "life" before we use fgets, so you can safely fetch data, and i repeat again if the socket dies we should get this output:
honestly, we get nothing but a blackhole loop, no output, no errors and a 100% cpu load.
so i hope you can eval this issue to see that i dont talk rubbish.
kind regards, stefano
edit: this post's code can be ignored because i came up with new updates, see the posts below.
The text was updated successfully, but these errors were encountered: