try to handle nightly debug port resets
[auerswald-callnotifier.git] / src / callnotifier / Source / Remote.php
1 <?php
2 namespace callnotifier;
3
4 class Source_Remote
5 {
6     protected $socket;
7
8     public function __construct($config, $handler)
9     {
10         $this->config  = $config;
11         $this->handler = $handler;
12     }
13
14     public function run()
15     {
16         do {
17             try {
18                 $tryAgain = false;
19                 $this->connect($this->config->host, $this->config->port);
20                 $this->init();
21                 $this->loop();
22             } catch (\Exception_ConnectionReset $e) {
23                 $tryAgain = true;
24             }
25         } while ($tryAgain);
26         $this->disconnect();
27     }
28
29     public function connect($ip, $port)
30     {
31         if ($ip == '') {
32             throw new \Exception('No remote IP or hostname given.');
33         }
34
35         $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
36         if ($socket === false) {
37             throw new \Exception(
38                 'socket_create() failed: reason: '
39                 . socket_strerror(socket_last_error())
40             );
41         }
42         //echo "Attempting to connect to '$ip' on port '$port'...";
43         $result = socket_connect($socket, $ip, $port);
44         if ($result === false) {
45             throw new \Exception(
46                 "socket_connect() failed. Reason: "
47                 . socket_strerror(socket_last_error($socket))
48             );
49         }
50
51         $this->socket = $socket;
52     }
53
54     function init()
55     {
56         $msg = "\x00\x01DecoderV=1\n";
57         socket_write($this->socket, $msg, strlen($msg));
58         $res = $this->read_response();
59         socket_write($this->socket, "\x00\x02", 2);
60     }
61
62     function loop()
63     {
64         while (true) {
65             $dbgmsg = $this->read_response();
66             //echo $dbgmsg . "\n";
67             $this->handler->handle($dbgmsg);
68         }
69     }
70
71     function read_response()
72     {
73         $res = socket_read($this->socket, 2048, PHP_NORMAL_READ);
74         if ($res === false) {
75             //handle "Connection reset by peer" that appears nightly since
76             // version 4.0N
77             throw new Exception_ConnectionReset();
78         }
79         return substr($res, 2, -1);
80     }
81
82     function disconnect()
83     {
84         socket_write($this->socket, "\x00\x03", 2);
85         socket_close($this->socket);
86     }
87
88 }
89
90 ?>