2019-12-12 00:56:30 +01:00
< ? php
2020-01-17 18:19:25 +01:00
/*
* This file is part of RaspiSMS .
*
* ( c ) Pierre - Lin Bonnemaison < plebwebsas @ gmail . com >
*
* This source file is subject to the GPL - 3.0 license that is bundled
* with this source code in the file LICENSE .
*/
2019-12-12 00:56:30 +01:00
namespace daemons ;
2020-01-17 18:19:25 +01:00
use Monolog\Handler\StreamHandler ;
use Monolog\Logger ;
2020-09-02 20:50:31 +02:00
use Symfony\Component\Process\Exception\ProcessFailedException ;
use Symfony\Component\Process\Process ;
2019-12-12 00:56:30 +01:00
/**
2020-01-17 18:19:25 +01:00
* Phone daemon class .
2019-12-12 00:56:30 +01:00
*/
class Phone extends AbstractDaemon
{
2020-03-04 05:10:45 +01:00
private $max_inactivity = 5 * 60 ;
2019-12-12 00:56:30 +01:00
private $msg_queue ;
2020-01-07 01:31:34 +01:00
private $msg_queue_id ;
private $webhook_queue ;
2019-12-17 07:47:11 +01:00
private $last_message_at ;
2020-01-07 01:31:34 +01:00
private $phone ;
private $adapter ;
private $bdd ;
2019-12-12 00:56:30 +01:00
2020-01-07 01:31:34 +01:00
/**
2020-01-17 18:19:25 +01:00
* Constructor .
*
2020-01-07 01:31:34 +01:00
* @ param array $phone : A phone table entry
*/
public function __construct ( array $phone )
2019-12-12 00:56:30 +01:00
{
2020-01-07 01:31:34 +01:00
$this -> phone = $phone ;
2020-03-04 01:40:47 +01:00
$this -> msg_queue_id = ( int ) ( QUEUE_ID_PHONE_PREFIX . $this -> phone [ 'id' ]);
2020-01-17 18:19:25 +01:00
2020-03-04 01:40:47 +01:00
$name = 'RaspiSMS Daemon Phone ' . $this -> phone [ 'id' ];
2019-12-12 00:56:30 +01:00
$logger = new Logger ( $name );
2020-03-04 04:18:26 +01:00
$logger -> pushHandler ( new StreamHandler ( PWD_LOGS . '/daemons.log' , Logger :: DEBUG ));
2019-12-17 07:47:11 +01:00
$pid_dir = PWD_PID ;
2020-01-08 18:20:17 +01:00
$no_parent = false ; //Phone should be rattach to manager, so manager can stop him easily
2019-12-17 07:47:11 +01:00
$additional_signals = [];
2020-01-08 18:20:17 +01:00
$uniq = true ; //Each phone should be uniq
2019-12-12 00:56:30 +01:00
2020-01-08 18:20:17 +01:00
//Construct the daemon
parent :: __construct ( $name , $logger , $pid_dir , $no_parent , $additional_signals , $uniq );
2020-01-17 18:19:25 +01:00
2019-12-12 00:56:30 +01:00
parent :: start ();
}
public function run ()
{
2020-03-04 03:28:34 +01:00
usleep ( 0.5 * 1000000 ); //Micro sleep for perfs
2020-01-17 18:19:25 +01:00
2020-01-07 01:31:34 +01:00
$this -> bdd = \descartes\Model :: _connect ( DATABASE_HOST , DATABASE_NAME , DATABASE_USER , DATABASE_PASSWORD , 'UTF8' );
2020-01-17 18:19:25 +01:00
2020-01-07 01:31:34 +01:00
//Send smss in queue
$this -> send_smss ();
2019-12-17 07:47:11 +01:00
2020-01-07 01:31:34 +01:00
//Read received smss
$this -> read_smss ();
2020-03-04 03:28:34 +01:00
//Stop after 5 minutes of inactivity to avoid useless daemon
if (( microtime ( true ) - $this -> last_message_at ) > $this -> max_inactivity )
{
posix_kill ( getmypid (), SIGTERM ); //Send exit signal to the current process
2020-07-03 03:48:42 +02:00
2020-03-04 03:28:34 +01:00
return false ;
}
2020-01-04 19:30:06 +01:00
}
2020-01-17 18:19:25 +01:00
public function on_start ()
{
//Set last message at to construct time
$this -> last_message_at = microtime ( true );
$this -> msg_queue = msg_get_queue ( $this -> msg_queue_id );
//Instanciate adapter
$adapter_class = $this -> phone [ 'adapter' ];
2020-03-31 01:28:32 +02:00
$this -> adapter = new $adapter_class ( $this -> phone [ 'adapter_datas' ]);
2020-01-17 18:19:25 +01:00
2020-01-17 18:47:08 +01:00
$this -> logger -> info ( 'Starting Phone daemon with pid ' . getmypid ());
2020-01-17 18:19:25 +01:00
}
public function on_stop ()
{
//Delete queue on daemon close
2020-01-17 18:47:08 +01:00
$this -> logger -> info ( 'Closing queue : ' . $this -> msg_queue_id );
2020-01-17 18:19:25 +01:00
msg_remove_queue ( $this -> msg_queue );
2020-01-17 18:47:08 +01:00
$this -> logger -> info ( 'Stopping Phone daemon with pid ' . getmypid ());
2020-01-17 18:19:25 +01:00
}
public function handle_other_signals ( $signal )
{
2020-01-17 18:47:08 +01:00
$this -> logger -> info ( 'Signal not handled by ' . $this -> name . ' Daemon : ' . $signal );
2020-01-17 18:19:25 +01:00
}
2020-01-04 19:30:06 +01:00
/**
2020-01-17 18:19:25 +01:00
* Send sms .
2020-01-04 19:30:06 +01:00
*/
2020-01-17 18:19:25 +01:00
private function send_smss ()
2020-01-04 19:30:06 +01:00
{
2020-09-02 20:50:31 +02:00
$tasks = [];
2020-06-23 21:06:13 +02:00
2020-01-07 01:31:34 +01:00
$find_message = true ;
while ( $find_message )
2019-12-12 00:56:30 +01:00
{
2020-01-17 18:19:25 +01:00
//Call message
2020-01-07 17:55:16 +01:00
$msgtype = null ;
$maxsize = 409600 ;
$message = null ;
$error_code = null ;
2020-01-17 18:19:25 +01:00
$success = msg_receive ( $this -> msg_queue , QUEUE_TYPE_SEND_MSG , $msgtype , $maxsize , $message , true , MSG_IPC_NOWAIT , $error_code ); //MSG_IPC_NOWAIT == dont wait if no message found
2020-01-07 17:55:16 +01:00
2020-01-17 18:19:25 +01:00
if ( ! $success && MSG_ENOMSG !== $error_code )
2020-01-07 17:55:16 +01:00
{
2020-01-17 18:47:08 +01:00
$this -> logger -> critical ( 'Error reading MSG SEND Queue, error code : ' . $error_code );
2020-01-17 18:19:25 +01:00
2020-01-07 17:55:16 +01:00
return false ;
}
2020-01-07 01:31:34 +01:00
if ( ! $message )
{
$find_message = false ;
2020-01-17 18:19:25 +01:00
2020-01-07 01:31:34 +01:00
continue ;
}
2020-01-17 18:19:25 +01:00
2020-01-07 01:31:34 +01:00
//Update last message time
$this -> last_message_at = microtime ( true );
2020-06-23 21:06:13 +02:00
//Do message sending
2020-01-17 18:47:08 +01:00
$this -> logger -> info ( 'Try send message : ' . json_encode ( $message ));
2020-09-02 20:50:31 +02:00
$this -> logger -> info ( 'with : ' . join ( ' ' , [ PWD . '/console.php' , 'controllers/internals/Console.php' , 'send_sms' , '--id_phone=' . escapeshellarg ( $this -> phone [ 'id' ]), '--message=' . escapeshellarg ( json_encode ( $message ))]));
2020-06-23 21:06:13 +02:00
2020-09-02 20:50:31 +02:00
$process = new Process ([ PWD . '/console.php' , 'controllers/internals/Console.php' , 'send_sms' , '--id_phone=' . $this -> phone [ 'id' ], '--message=' . json_encode ( $message )]);
$tasks [] = [ 'message' => $message , 'process' => $process ];
}
2020-06-23 21:06:13 +02:00
2020-09-02 20:50:31 +02:00
foreach ( $tasks as $task )
{
2020-09-02 21:45:26 +02:00
$task [ 'process' ] -> start ();
2020-09-02 20:50:31 +02:00
}
2020-06-23 21:06:13 +02:00
2020-09-02 20:50:31 +02:00
$done = false ;
while ( ! $done )
{
usleep ( 0.001 * 1000000 ); //Micro sleep for perfs
$done = true ;
foreach ( $tasks as $task )
{
if ( $task [ 'process' ] -> isRunning ()) {
$done = false ;
continue ;
}
if ( ! $task [ 'process' ] -> isSuccessful ()) {
$this -> logger -> error ( 'Failed send message : ' . json_encode ( $task [ 'message' ]) . ' with : ' . $task [ 'process' ] -> getErrorOutput () . $task [ 'process' ] -> getOutput ());
continue ;
}
$this -> logger -> info ( 'Successfully send message : ' . json_encode ( $task [ 'message' ]));
}
2019-12-12 00:56:30 +01:00
}
2020-01-07 01:31:34 +01:00
}
/**
2020-03-04 01:40:47 +01:00
* Read smss for a phone .
2020-01-07 01:31:34 +01:00
*/
2020-01-17 18:19:25 +01:00
private function read_smss ()
2020-01-07 01:31:34 +01:00
{
$internal_received = new \controllers\internals\Received ( $this -> bdd );
2020-01-17 18:19:25 +01:00
2020-03-31 02:22:40 +02:00
if ( ! $this -> adapter -> meta_support_read ())
{
return true ;
}
2020-06-23 21:06:13 +02:00
2020-04-02 01:55:55 +02:00
$response = $this -> adapter -> read ();
if ( $response [ 'error' ])
{
$this -> logger -> info ( 'Error reading received smss : ' . $response [ 'error_message' ]);
2020-06-23 21:06:13 +02:00
2020-04-02 01:55:55 +02:00
return false ;
}
if ( ! $response [ 'smss' ])
2020-01-07 01:31:34 +01:00
{
return true ;
}
//Process smss
2020-04-02 01:55:55 +02:00
foreach ( $response [ 'smss' ] as $sms )
2020-01-07 01:31:34 +01:00
{
2020-01-17 18:47:08 +01:00
$this -> logger -> info ( 'Receive message : ' . json_encode ( $sms ));
2020-04-02 18:40:39 +02:00
$response = $internal_received -> receive ( $this -> phone [ 'id_user' ], $this -> phone [ 'id' ], $sms [ 'text' ], $sms [ 'origin' ]);
2020-06-23 21:06:13 +02:00
2020-04-02 18:40:39 +02:00
if ( $response [ 'error' ])
2020-01-07 17:55:16 +01:00
{
2020-04-02 18:40:39 +02:00
$this -> logger -> error ( 'Failed receive message : ' . json_encode ( $sms ) . ' with error : ' . $response [ 'error_message' ]);
2020-06-23 21:06:13 +02:00
2020-04-02 18:40:39 +02:00
continue ;
2020-01-07 17:55:16 +01:00
}
2020-01-17 18:19:25 +01:00
2020-04-02 18:40:39 +02:00
$this -> logger -> info ( 'Message received successfully.' );
2020-01-08 14:14:40 +01:00
}
2019-12-12 00:56:30 +01:00
}
}