|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace Clue\React\Ssdp; |
| 4 | + |
| 5 | +use React\EventLoop\LoopInterface; |
| 6 | +use Clue\React\Multicast\Factory as MulticastFactory; |
| 7 | +use React\Promise\Deferred; |
| 8 | + |
| 9 | +class Client |
| 10 | +{ |
| 11 | + const ADDRESS = '239.255.255.250:1900'; |
| 12 | + |
| 13 | + private $loop; |
| 14 | + private $multicast; |
| 15 | + |
| 16 | + public function __construct(LoopInterface $loop, MulticastFactory $multicast = null) |
| 17 | + { |
| 18 | + if ($multicast === null) { |
| 19 | + $multicast = new MulticastFactory($loop); |
| 20 | + } |
| 21 | + $this->loop = $loop; |
| 22 | + $this->multicast = $multicast; |
| 23 | + } |
| 24 | + |
| 25 | + public function search($searchTarget = 'ssdp:all', $mx = 2) |
| 26 | + { |
| 27 | + $data = "M-SEARCH * HTTP/1.1\r\n"; |
| 28 | + $data .= "HOST: " . self::ADDRESS . "\r\n"; |
| 29 | + $data .= "MAN: \"ssdp:discover\"\r\n"; |
| 30 | + $data .= "MX: $mx\r\n"; |
| 31 | + $data .= "ST: $searchTarget\r\n"; |
| 32 | + $data .= "\r\n"; |
| 33 | + |
| 34 | + $socket = $this->multicast->createSender(); |
| 35 | + // TODO: The TTL for the IP packet SHOULD default to 2 and SHOULD be configurable. |
| 36 | + |
| 37 | + $timer = $this->loop->addTimer($mx, function() use ($socket, &$deferred) { |
| 38 | + $deferred->resolve(); |
| 39 | + $socket->close(); |
| 40 | + }); |
| 41 | + |
| 42 | + $deferred = new Deferred(function () use ($socket, &$timer) { |
| 43 | + // canceling resulting promise cancels timer and closes socket |
| 44 | + $timer->cancel(); |
| 45 | + $socket->close(); |
| 46 | + throw new RuntimeException('Cancelled'); |
| 47 | + }); |
| 48 | + |
| 49 | + $that = $this; |
| 50 | + $socket->on('message', function ($data, $remote) use ($deferred, $that) { |
| 51 | + $message = $that->parseMessage($data, $remote); |
| 52 | + |
| 53 | + $deferred->progress($message); |
| 54 | + }); |
| 55 | + |
| 56 | + $socket->send($data, self::ADDRESS); |
| 57 | + |
| 58 | + return $deferred->promise(); |
| 59 | + } |
| 60 | + |
| 61 | + /** @internal */ |
| 62 | + public function parseMessage($message, $remote) |
| 63 | + { |
| 64 | + // TODO: parse message into message model |
| 65 | + $message = array( |
| 66 | + 'data' => $message, |
| 67 | + '_sender' => $remote |
| 68 | + ); |
| 69 | + return $message; |
| 70 | + } |
| 71 | +} |
0 commit comments