Importing all scripts
This commit is contained in:
commit
9c987c19f9
0
push/PushErrors.log
Normal file
0
push/PushErrors.log
Normal file
248
push/PushMonitor.php
Normal file
248
push/PushMonitor.php
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
|
||||||
|
PHP APNS Service with Queue
|
||||||
|
(C) 2009 Alessandro Segala (alessandro.segala@letsdev.it)
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Some settings
|
||||||
|
$cache_server = 'localhost';
|
||||||
|
$cache_port = 22201;
|
||||||
|
$queue_id = 'PushQueue';
|
||||||
|
$check_interval = 10;
|
||||||
|
$php_executable = 'php';
|
||||||
|
$inactivity_timeout = 600; // Quits the connection with APNS after X seconds of inactivity
|
||||||
|
$debug = false; // Set to true to display verbose information
|
||||||
|
|
||||||
|
// We want this process to run forever... Well, at least until the user stops it!
|
||||||
|
set_time_limit(0);
|
||||||
|
|
||||||
|
// Settings for child processes
|
||||||
|
$descriptorspec = array(
|
||||||
|
0 => array('pipe', 'r'), // stdin
|
||||||
|
1 => array('pipe', 'w'), // stdout
|
||||||
|
2 => array('pipe', 'w') // stderr
|
||||||
|
);
|
||||||
|
|
||||||
|
$process = false;
|
||||||
|
|
||||||
|
// Changes the working directory so it matches this script's directory
|
||||||
|
chdir(dirname(__FILE__));
|
||||||
|
|
||||||
|
// Opens a connection to the MemcacheQ daemon, used for queueing requests
|
||||||
|
$cache = new Memcache();
|
||||||
|
if(!$cache->connect($cache_server, $cache_port))
|
||||||
|
{
|
||||||
|
echo "Error while connecting to cache server\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Application's loop
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
$value = $cache->get($queue_id);
|
||||||
|
if(!$value)
|
||||||
|
{
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
echo "No data: sleeping for $check_interval seconds\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kills the process after X seconds of inactivity
|
||||||
|
if($process)
|
||||||
|
{
|
||||||
|
if($process->time < (time() - $inactivity_timeout))
|
||||||
|
{
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
echo "Quitting connection with Apple for inactivity\n";
|
||||||
|
}
|
||||||
|
$process->kill();
|
||||||
|
$process = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep($check_interval);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
var_dump($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_error_handler(create_function('', 'error_log(date(\'Y-m-d H:i\')." - Error while unserializing\n\n", 3, \'PushErrors.log\');'));
|
||||||
|
$unserialized = unserialize($value);
|
||||||
|
restore_error_handler();
|
||||||
|
if(!$unserialized)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list($deviceToken, $value) = $unserialized;
|
||||||
|
|
||||||
|
// Try to send the message 3 times
|
||||||
|
for($i = 0; $i < 3; $i++)
|
||||||
|
{
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
echo "Sending message\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$process)
|
||||||
|
{
|
||||||
|
$process = new Process(1153 + $i);
|
||||||
|
if(!$process->init())
|
||||||
|
{
|
||||||
|
echo "Error while starting child process\n";
|
||||||
|
|
||||||
|
$process->kill();
|
||||||
|
$process = false;
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
echo "Sleeping 10 seconds before trying again\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(10);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $process->sendMessage($deviceToken, $value);
|
||||||
|
|
||||||
|
if($result)
|
||||||
|
{
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
echo "Message sent\n\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
elseif($debug)
|
||||||
|
{
|
||||||
|
echo "Attempt ",$i+1," failed\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all 3 attempts failed...
|
||||||
|
if($i == 3)
|
||||||
|
{
|
||||||
|
$process->kill();
|
||||||
|
$process = false;
|
||||||
|
error_log(date('Y-m-d H:i')." - Cannot send message:\n".$message."\nTo device: ".$deviceToken."\n\n", 3, 'PushErrors.log');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Process
|
||||||
|
{
|
||||||
|
private $pointer;
|
||||||
|
private $pipes;
|
||||||
|
private $port;
|
||||||
|
public $time;
|
||||||
|
|
||||||
|
public function __construct($port = 1153)
|
||||||
|
{
|
||||||
|
$this->port = $port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function init()
|
||||||
|
{
|
||||||
|
global $descriptorspec, $php_executable;
|
||||||
|
|
||||||
|
$this->pointer = proc_open($php_executable.' -f PushService.php -- -p'.$this->port, $descriptorspec, $this->pipes);
|
||||||
|
if(!$this->pointer)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->time = time();
|
||||||
|
|
||||||
|
// Wait until the process is fully ready
|
||||||
|
$read = fgets($this->pipes[1]);
|
||||||
|
if(trim($read) != 'LISTENING '.$this->port)
|
||||||
|
{
|
||||||
|
global $debug;
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
echo "Error while starting child process.\n";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendMessage($deviceToken, $message)
|
||||||
|
{
|
||||||
|
if(!($conn = fsockopen('localhost', $this->port, $errno, $errstr, 5)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$read = fgets($conn);
|
||||||
|
if(trim($read) != 'OK')
|
||||||
|
{
|
||||||
|
fclose($conn);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite($conn, $deviceToken."\n");
|
||||||
|
fwrite($conn, $message."\n");
|
||||||
|
|
||||||
|
$read = fgets($conn);
|
||||||
|
if(trim($read) != 'SENT')
|
||||||
|
{
|
||||||
|
fclose($conn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($conn);
|
||||||
|
|
||||||
|
$this->time = time();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kill()
|
||||||
|
{
|
||||||
|
$status = proc_get_status($this->pointer);
|
||||||
|
|
||||||
|
if($status['running'])
|
||||||
|
{
|
||||||
|
fclose($this->pipes[0]);
|
||||||
|
fclose($this->pipes[1]);
|
||||||
|
fclose($this->pipes[2]);
|
||||||
|
|
||||||
|
$ppid = $status['pid'];
|
||||||
|
$pids = preg_split('/\s+/', `ps -o pid --no-heading --pid $ppid`);
|
||||||
|
foreach($pids as $pid)
|
||||||
|
{
|
||||||
|
if(is_numeric($pid))
|
||||||
|
{
|
||||||
|
if($debug)
|
||||||
|
{
|
||||||
|
echo "Killing $pid\n";
|
||||||
|
}
|
||||||
|
posix_kill($pid, 9); //9 is the SIGKILL signal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (proc_close($this->pointer) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
103
push/PushService.php
Normal file
103
push/PushService.php
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
PHP APNS Service
|
||||||
|
Created by Luke Rhodes
|
||||||
|
|
||||||
|
Released into the public domain
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
$port = 0;
|
||||||
|
foreach($argv as $a)
|
||||||
|
{
|
||||||
|
if($a[0] == '-' && $a[1] == 'p' && !empty($a[2]))
|
||||||
|
{
|
||||||
|
$port = intval(substr($a, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pushNotifications = new pushNotifications($port);
|
||||||
|
|
||||||
|
class pushNotifications
|
||||||
|
{
|
||||||
|
private $apnsHost = 'gateway.push.apple.com';
|
||||||
|
private $apnsPort = '2195';
|
||||||
|
private $sslPem = 'apns.pem';
|
||||||
|
private $passPhrase = '';
|
||||||
|
|
||||||
|
private $serviceHost = '127.0.0.1';
|
||||||
|
private $servicePort = '1153';
|
||||||
|
|
||||||
|
private $apnsConnection;
|
||||||
|
private $serviceConnection;
|
||||||
|
|
||||||
|
function __construct($port = 0)
|
||||||
|
{
|
||||||
|
if($port)
|
||||||
|
{
|
||||||
|
$this->servicePort = $port;
|
||||||
|
}
|
||||||
|
$this->connectToAPNS();
|
||||||
|
$this->listenForClients();
|
||||||
|
$this->closeConnections();
|
||||||
|
}
|
||||||
|
|
||||||
|
function connectToAPNS()
|
||||||
|
{
|
||||||
|
$streamContext = stream_context_create();
|
||||||
|
stream_context_set_option($streamContext, 'ssl', 'local_cert', $this->sslPem);
|
||||||
|
stream_context_set_option($streamContext, 'ssl', 'passphrase', $this->passPhrase);
|
||||||
|
|
||||||
|
$this->apnsConnection = stream_socket_client('ssl://'.$this->apnsHost.':'.$this->apnsPort, $error, $errorString, 60, STREAM_CLIENT_CONNECT, $streamContext);
|
||||||
|
if($this->apnsConnection == false)
|
||||||
|
{
|
||||||
|
print "Failed to connect {$error} {$errorString}\n";
|
||||||
|
$this->closeConnections();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function listenForClients()
|
||||||
|
{
|
||||||
|
$this->serviceConnection = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||||
|
socket_bind($this->serviceConnection, $this->serviceHost, $this->servicePort);
|
||||||
|
socket_listen($this->serviceConnection, 10);
|
||||||
|
|
||||||
|
echo 'LISTENING ',$this->servicePort,"\n";
|
||||||
|
|
||||||
|
while($clientSocket = socket_accept($this->serviceConnection))
|
||||||
|
{
|
||||||
|
socket_write($clientSocket, "OK\n");
|
||||||
|
|
||||||
|
$deviceToken = trim(socket_read($clientSocket, 1024, PHP_NORMAL_READ));
|
||||||
|
$message = trim(socket_read($clientSocket, 1024, PHP_NORMAL_READ));
|
||||||
|
|
||||||
|
if(!empty($deviceToken) && !empty($message))
|
||||||
|
{
|
||||||
|
$this->sendNotification($deviceToken, $message);
|
||||||
|
socket_write($clientSocket, "SENT\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
socket_write($clientSocket, "ERROR\n");
|
||||||
|
}
|
||||||
|
socket_close($clientSocket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendNotification($deviceToken, $message)
|
||||||
|
{
|
||||||
|
$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($message)) . $message;
|
||||||
|
|
||||||
|
fwrite($this->apnsConnection, $apnsMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeConnections()
|
||||||
|
{
|
||||||
|
socket_close($this->serviceConnection);
|
||||||
|
fclose($this->apnsConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
Loading…
x
Reference in New Issue
Block a user