103 lines
2.9 KiB
PHP
103 lines
2.9 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace NoccyLabs\UPnP\HTTPU;
|
||
|
|
||
|
class Endpoint
|
||
|
{
|
||
|
|
||
|
protected $socket;
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param string $bind The IP to bind to (0.0.0.0 for all)
|
||
|
* @throws EndpointException
|
||
|
*/
|
||
|
public function __construct($bind='0.0.0.0', $port=0, $reuse_port=false)
|
||
|
{
|
||
|
//Create the socket.
|
||
|
$socket = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
|
||
|
|
||
|
// Handle errors on failure
|
||
|
if (!$socket) {
|
||
|
$errno = socket_last_error();
|
||
|
$errmsg = socket_error($errno);
|
||
|
throw new EndpointException("Could not create socket: {$errmsg} ({$errno})");
|
||
|
}
|
||
|
|
||
|
//Set socket options.
|
||
|
socket_set_nonblock($socket);
|
||
|
socket_set_option($socket, SOL_SOCKET, SO_BROADCAST, 1);
|
||
|
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
|
||
|
if ($reuse_port) {
|
||
|
socket_set_option($socket, SOL_SOCKET, SO_REUSEPORT, 1);
|
||
|
}
|
||
|
|
||
|
if(!socket_bind($socket, $bind, $port)) {
|
||
|
$errno = socket_last_error();
|
||
|
$errmsg = socket_error($errno);
|
||
|
throw new EndpointException("Could not bind socket to {$bind}:{$port}: {$errmsg} ({$errno})");
|
||
|
}
|
||
|
|
||
|
$this->socket = $socket;
|
||
|
|
||
|
}
|
||
|
|
||
|
public function __destruct()
|
||
|
{
|
||
|
if ($this->socket) {
|
||
|
@socket_close($this->socket);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*
|
||
|
* @param Request $request The request to send
|
||
|
* @return Response[] The received responses if any
|
||
|
*/
|
||
|
public function send(Request $request, $wait_time=5)
|
||
|
{
|
||
|
// Get the details from the request
|
||
|
$buffer = $request->getBuffer();
|
||
|
$addr = $request->getAddress();
|
||
|
$port = $request->getPort();
|
||
|
|
||
|
if (false === socket_sendto($this->socket, $buffer, strlen($buffer), 0, $addr, $port)) {
|
||
|
$errno = socket_last_error();
|
||
|
$errmsg = socket_error($errno);
|
||
|
throw new EndpointException("Send failed: {$errmsg} ({$errno})");
|
||
|
}
|
||
|
|
||
|
// Wait $wait_time seconds for responses to arrive
|
||
|
$read_expires = microtime(true) + $wait_time;
|
||
|
$responses = [];
|
||
|
|
||
|
while (microtime(true) < $read_expires) {
|
||
|
if (socket_recvfrom($this->socket, $data, 5120, MSG_DONTWAIT, $raddr, $rport)) {
|
||
|
//while(is_string($data = socket_read($this->socket, 5120))) {
|
||
|
$response = Response::createFromString($data, $raddr);
|
||
|
if ($response) {
|
||
|
$responses[] = $response;
|
||
|
}
|
||
|
}
|
||
|
usleep(10000);
|
||
|
}
|
||
|
|
||
|
return $responses;
|
||
|
|
||
|
/*
|
||
|
while(socket_select($read, $write, $except, 3)) {
|
||
|
|
||
|
//Read received packets with a maximum size of 5120 bytes.
|
||
|
while(is_string($data = socket_read($this->socket, 5120))) {
|
||
|
echo "READ: {$data}\n";
|
||
|
return $data;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|