Chandra

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    - 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 )