App-OpenHAP

 view release on metacpan or  search on metacpan

lib/Protocol/HAP/Server.pm  view on Meta::CPAN

# Event coalescing delay in seconds (HAP-HTTP.md §14)
use constant EVENT_COALESCE_DELAY => 0.250;

# _response(%args):
#	Build a response with the HAP defaults: the connection stays
#	open, because a controller sends every request of a session
#	over one connection.
sub _response (%args)
{
	my %headers = %{ $args{headers} // {} };
	$headers{Connection} //= 'keep-alive';

	return Protocol::HAP::HTTP::build_response( %args,
		headers => \%headers );
}

# _tlv_response($body):
#	A 200 response with the pairing TLV content type. Every
#	pairing and pairings-management reply uses it.
sub _tlv_response ($body)
{

man/openhap/hapctl.8  view on Meta::CPAN

.Pp
An absent configuration file is not an error.
A fresh install has none, and the daemon then runs on its defaults.
.It Cm status
Report on the daemon: its name, its HAP port, its uptime, its
pairing state and controller count, its configuration number, the
number of loaded devices, the number of open connections, and the
state of mDNS and MQTT.
.Pp
With no control socket, the command reports only whether a process
is alive, from
.Pa /var/run/openhapd.pid ,
and it names that file in its output.
.It Cm devices
List the devices.
With a control socket, the command lists the accessories that the
daemon really loaded, with the HomeKit accessory ID of each.
Without one, it lists the device blocks of the configuration file,
which is what the daemon would load at its next start.
.It Cm help
Show the usage message.

t/openhap/integration/daemon.t  view on Meta::CPAN


# Test 4: Daemon responds to connections
ok($env->wait_for_hap_port, 'daemon accepts connections');

# Test 5: Daemon restart works
ok($env->restart_daemon, 'daemon restarts successfully');

# Test 6: The restarted daemon owns the file
my $new_pid = $pidfile->read_pid;
ok(defined $new_pid && $new_pid ne $pid, 'the PID file names the new daemon');
is($pidfile->is_running, $new_pid, 'and that daemon is alive');

# Test 7: Daemon stop works
system('rcctl stop openhapd >/dev/null 2>&1');
sleep 1;
my $stopped = system('rcctl check openhapd >/dev/null 2>&1') != 0;
ok($stopped, 'daemon stops successfully');

# Test 8: The PID file stays after the stop, and it is stale. An
# unlink in root-owned /var/run needs a directory permission that the
# daemon gives up at the privilege drop. Thus the file is a leftover by

t/openhap/integration/hap-protocol.t  view on Meta::CPAN

	$resp2 .= $line;
	last if $line =~ /^\r?\n$/;
}

$socket->close;

# Test 11: Both requests succeed
ok($resp1 =~ /HTTP/ && $resp2 =~ /HTTP/,
   'connection persistence works');

# Test 12: Connection: keep-alive header in responses
$response = $env->http_request('GET', '/accessories');
my $has_keepalive = $response =~ /Connection:\s*keep-alive/i;
ok($has_keepalive, 'response includes Connection: keep-alive header');

# Test 13: HTTP responses use HTTP/1.1
$response = $env->http_request('GET', '/accessories');
ok($response =~ /HTTP\/1\.1/, 'server uses HTTP/1.1 specifically');

# Test 14: /pair-setup returns TLV response
$response = $env->http_request('POST', '/pair-setup', "\x00\x01\x00",
	{'Content-Type' => 'application/pairing+tlv8'});
# TLV responses are binary. Check for Content-Length.
my ($content_length) = $response =~ /Content-Length:\s*(\d+)/i;

t/openhap/integration/sandbox.t  view on Meta::CPAN

#!/usr/bin/env perl
# ex:ts=8 sw=4:
# Integration test: the daemon really pledges and unveils.
#
# A pledge violation kills the process. Thus a correctly pledged
# daemon and a completely unpledged one both satisfy "the daemon is
# alive and its trace shows no violation". That check is a null
# test. The syscall itself is observable. This file traces the
# daemon from exec with ktrace(1). It asserts that the daemon calls
# pledge(2) with exactly the production promise set. It asserts that
# the daemon calls unveil(2) for the inventory and then locks the
# view. It asserts that startup still succeeds in the configurations
# that worked before the sandbox existed. If you remove the pledge
# or unveil call from bin/openhapd, the corresponding syscall is
# absent from the trace.
#
# The Fugu repository's sandbox test proves the enforcement

t/openhap/integration/shutdown.t  view on Meta::CPAN

# Give the daemon time to act on the signal. A daemon that exits on
# HUP is gone within a second; the loop notices the flag on its next
# pass, which is at most one second away.
sleep 3;

ok( $pidfile->is_running, 'the daemon survived SIGHUP' );
is( $pidfile->read_pid, $before,
	'and it is the same process, not a restart' );
ok( port_open(), 'it still serves HAP after the reload' );

# A reload leaves the daemon able to answer, not merely alive
my $response = $env->http_request( 'GET', '/accessories' );
ok( defined $response, 'the reloaded daemon answers a request' );
$env->close_sockets;

# A second reload is the same. An operator reloads on every
# configuration edit, so once is not the interesting case.
system('rcctl reload openhapd >/dev/null 2>&1');
sleep 3;
ok( $pidfile->is_running, 'a second SIGHUP is also survivable' );
is( $pidfile->read_pid, $before, 'still the same process' );

t/protocol/http.t  view on Meta::CPAN


	is( scalar( grep { $_ } @complete ), 1, 'the message completes once' );
	is( $complete[-1], length($whole), 'at exactly its own length' );

	# Content-Length is found wherever it sits in the block. A
	# pattern anchored with $ under /m stops at the \r of the line
	# terminator, so it would match only the last header and every
	# real response would frame short.
	my $middle =
	      "HTTP/1.1 200 OK\r\n"
	    . "Connection: keep-alive\r\n"
	    . "Content-Length: 5\r\n"
	    . "Content-Type: text/plain\r\n"
	    . "\r\n" . 'hello';
	is( Protocol::HAP::HTTP::message_complete($middle),
		length($middle), 'a header that is not the last one is read' );

	# A message whose headers arrived but whose body has not
	my $headers_only = substr $whole, 0, index( $whole, "\r\n\r\n" ) + 4;
	is( Protocol::HAP::HTTP::message_complete($headers_only),
		0, 'headers with a declared body are not a whole message' );



( run in 0.895 second using v1.01-cache-2.11-cpan-14f38c9f855 )