forked from clue/reactphp-ssdp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathClient.php
More file actions
87 lines (71 loc) · 2.62 KB
/
Client.php
File metadata and controls
87 lines (71 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<?php
namespace Clue\React\Ssdp;
use Clue\React\Multicast\Factory as MulticastFactory;
use React\EventLoop\Loop;
use React\EventLoop\LoopInterface;
use React\Promise\Deferred;
use RuntimeException;
class Client
{
const ADDRESS = '239.255.255.250:1900';
/** @var LoopInterface */
private $loop;
/** @var MulticastFactory */
private $multicast;
/**
* This class takes an optional `LoopInterface|null $loop` parameter that can be used to
* pass the event loop instance to use for this object. You can use a `null` value
* here in order to use the [default loop](https://github.com/reactphp/event-loop#loop).
* This value SHOULD NOT be given unless you're sure you want to explicitly use a
* given event loop instance.
*
* @param ?LoopInterface $loop
* @param ?MulticastFactory $multicast
*/
public function __construct(LoopInterface $loop = null, MulticastFactory $multicast = null)
{
$this->loop = $loop ?: Loop::get();
$this->multicast = $multicast ?: new MulticastFactory($this->loop);
}
public function search($searchTarget = 'ssdp:all', $mx = 2)
{
$data = "M-SEARCH * HTTP/1.1\r\n";
$data .= "HOST: " . self::ADDRESS . "\r\n";
$data .= "MAN: \"ssdp:discover\"\r\n";
$data .= "MX: $mx\r\n";
$data .= "ST: $searchTarget\r\n";
$data .= "\r\n";
$socket = $this->multicast->createSender();
// TODO: The TTL for the IP packet SHOULD default to 2 and SHOULD be configurable.
$messages = array();
$loop = $this->loop;
$deferred = new Deferred(function () use ($socket, &$timer, $loop) {
// canceling resulting promise cancels timer and closes socket
$loop->cancelTimer($timer);
$socket->close();
throw new RuntimeException('Cancelled');
});
$timer = $this->loop->addTimer($mx, function() use ($socket, &$deferred, &$messages) {
$deferred->resolve($messages);
$socket->close();
});
$that = $this;
$socket->on('message', function ($data, $remote) use (&$messages, $that) {
$message = $that->parseMessage($data, $remote);
$messages[] = $message;
$deferred->progress($message);
});
$socket->send($data, self::ADDRESS);
return $deferred->promise();
}
/** @internal */
public function parseMessage($message, $remote)
{
// TODO: parse message into message model
$message = array(
'data' => $message,
'_sender' => $remote
);
return $message;
}
}