Chandra
view release on metacpan or search on metacpan
- Chandra::Socket::Connection - length-prefixed JSON wire protocol
- App: hub(), client() methods with integrated poll loop
- Channel-based message routing, broadcast, send_to
- on_connect/on_disconnect lifecycle hooks
- Security: token-based handshake authentication
- Security: socket path in $XDG_RUNTIME_DIR with 0600 permissions
- Security: token file (0600) written alongside socket for client auth
- Security: max frame size (16 MB) and buffer overflow protection (64 MB)
- Security: malformed JSON frame warnings
- Security: duplicate client name collision handling
- TCP transport: opt-in TLS via IO::Socket::SSL (tls_cert, tls_key, tls)
- Examples: socket_ipc_example.pl, chat_hub.pl, chat_window.pl
0.03 2026-03-29
- Switch from JSON to Cpanel::JSON::XS
- Add Cpanel::JSON::XS to PREREQ_PM
- Bail out of Makefile.PL on Linux when GTK/WebKit2 dev libraries are missing
0.02 2026-03-28
- Chandra::App - high-level OO application wrapper
- Chandra::Element - Moonshine-compatible DOM builder with render()
include/chandra/chandra_socket_common.h view on Meta::CPAN
XPUSHs(sv_2mortal(newSViv(0)));
PUTBACK;
count = call_method("new", G_SCALAR);
SPAGAIN;
if (count > 0) { SV *s = POPs; if (SvOK(s)) sock = newSVsv(s); }
PUTBACK;
FREETMPS; LEAVE;
return sock;
}
/* ---- Create IO::Socket::SSL (client or server) ---- */
static SV *
_sock_tls_connect(pTHX_ SV *host_sv, SV *port_sv, SV *tls_ca_sv)
{
dSP;
int count;
SV *sock = NULL;
SV *verify_mode;
load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("IO::Socket::SSL"), NULL);
/* Get verify mode constant */
{
ENTER; SAVETMPS;
PUSHMARK(SP);
PUTBACK;
count = call_pv(
(tls_ca_sv && SvOK(tls_ca_sv))
? "IO::Socket::SSL::SSL_VERIFY_PEER"
: "IO::Socket::SSL::SSL_VERIFY_NONE",
G_SCALAR);
SPAGAIN;
verify_mode = (count > 0) ? newSVsv(POPs) : newSViv(0);
PUTBACK;
FREETMPS; LEAVE;
}
{
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpvs("IO::Socket::SSL")));
XPUSHs(sv_2mortal(newSVpvs("PeerHost")));
XPUSHs(host_sv);
XPUSHs(sv_2mortal(newSVpvs("PeerPort")));
XPUSHs(port_sv);
XPUSHs(sv_2mortal(newSVpvs("SSL_verify_mode")));
XPUSHs(sv_2mortal(verify_mode));
if (tls_ca_sv && SvOK(tls_ca_sv)) {
XPUSHs(sv_2mortal(newSVpvs("SSL_ca_file")));
XPUSHs(tls_ca_sv);
}
include/chandra/chandra_socket_common.h view on Meta::CPAN
}
static SV *
_sock_tls_listen(pTHX_ SV *host_sv, SV *port_sv,
SV *cert_sv, SV *key_sv)
{
dSP;
int count;
SV *sock = NULL;
load_module(PERL_LOADMOD_NOIMPORT, newSVpvs("IO::Socket::SSL"), NULL);
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpvs("IO::Socket::SSL")));
XPUSHs(sv_2mortal(newSVpvs("LocalHost")));
XPUSHs(host_sv);
XPUSHs(sv_2mortal(newSVpvs("LocalPort")));
XPUSHs(port_sv);
XPUSHs(sv_2mortal(newSVpvs("Proto")));
XPUSHs(sv_2mortal(newSVpvs("tcp")));
XPUSHs(sv_2mortal(newSVpvs("Listen")));
XPUSHs(sv_2mortal(newSViv(16)));
XPUSHs(sv_2mortal(newSVpvs("ReuseAddr")));
XPUSHs(sv_2mortal(newSViv(1)));
lib/Chandra/Socket/Client.pm view on Meta::CPAN
# TCP â token must be passed explicitly
my $client = Chandra::Socket::Client->new(
name => 'remote-1',
transport => 'tcp',
host => '10.0.0.5',
port => 9000,
token => $token,
);
# TCP with TLS (requires IO::Socket::SSL)
my $client = Chandra::Socket::Client->new(
name => 'remote-1',
transport => 'tcp',
host => '10.0.0.5',
port => 9000,
token => $token,
tls => 1,
tls_ca => '/path/to/ca.pem', # optional cert verification
);
lib/Chandra/Socket/Client.pm view on Meta::CPAN
(Required for TCP) Hub port number.
=item token
Authentication token. For Unix sockets this is read from the token file
automatically. For TCP it must be provided (see C<< $hub->token >>).
=item tls
Set to a true value to connect via TLS. Requires L<IO::Socket::SSL>.
=item tls_ca
Path to a CA certificate file for server verification. When omitted, peer
verification is disabled.
=back
=head1 METHODS
lib/Chandra/Socket/Hub.pm view on Meta::CPAN
# Unix socket (default)
my $hub = Chandra::Socket::Hub->new(name => 'myapp');
# TCP
my $hub = Chandra::Socket::Hub->new(
transport => 'tcp',
port => 9000,
bind => '0.0.0.0',
);
# TCP with TLS (requires IO::Socket::SSL)
my $hub = Chandra::Socket::Hub->new(
transport => 'tcp',
port => 9000,
tls_cert => '/path/to/cert.pem',
tls_key => '/path/to/key.pem',
);
$hub->on('status', sub {
my ($data, $client) = @_;
print "Got status from ${\$client->name}\n";
lib/Chandra/Socket/Hub.pm view on Meta::CPAN
(Required for TCP) Port number to listen on.
=item bind
Bind address for TCP. Defaults to C<'127.0.0.1'>.
=item tls_cert
Path to a PEM certificate file. Enables TLS when paired with C<tls_key>.
Requires L<IO::Socket::SSL>.
=item tls_key
Path to a PEM private key file for TLS.
=back
=head1 METHODS
=head2 on
lib/Chandra/Socket/Hub.pm view on Meta::CPAN
C<$XDG_RUNTIME_DIR> (or the system temp directory) to limit access.
Hub generates a random authentication token on startup and writes it to a
token file (C<.token> beside the socket) with 0600 permissions. Clients
must present the correct token during the handshake or the connection is
rejected. For TCP transport, pass the token explicitly via the C<token>
parameter to L<Chandra::Socket::Client>.
For TCP transport over a network, enable TLS by passing C<tls_cert> and
C<tls_key> to the Hub, and C<< tls => 1 >> to the Client. This requires
L<IO::Socket::SSL>. Without TLS, TCP traffic (including the auth token)
is sent in plaintext.
=head1 SEE ALSO
L<Chandra::Socket::Client>, L<Chandra::Socket::Connection>, L<Chandra::App>
=cut
( run in 0.763 second using v1.01-cache-2.11-cpan-39bf76dae61 )