Chandra
view release on metacpan or search on metacpan
include/chandra/chandra_socket_hub.h view on Meta::CPAN
static SV *
_hub_create_tcp_listener(pTHX_ HV *hv)
{
SV **tls_cert_svp = hv_fetchs(hv, "tls_cert", 0);
SV **tls_key_svp = hv_fetchs(hv, "tls_key", 0);
SV **bind_svp = hv_fetchs(hv, "bind_addr", 0);
SV **port_svp = hv_fetchs(hv, "port", 0);
SV *host = bind_svp ? *bind_svp : sv_2mortal(newSVpvs("127.0.0.1"));
SV *port = port_svp ? *port_svp : &PL_sv_undef;
SV *listener = NULL;
if (tls_cert_svp && SvOK(*tls_cert_svp) &&
tls_key_svp && SvOK(*tls_key_svp)) {
listener = _sock_tls_listen(aTHX_ host, port,
*tls_cert_svp, *tls_key_svp);
if (!listener)
croak("Hub: cannot listen on TLS TCP %s:%s: %s",
bind_svp ? SvPV_nolen(*bind_svp) : "?",
port_svp ? SvPV_nolen(*port_svp) : "?",
SvPV_nolen(get_sv("!", 0)));
_sock_set_nonblocking(aTHX_ listener);
} else {
listener = _sock_tcp_listen(aTHX_ host, port);
if (!listener)
croak("Hub: cannot listen on TCP %s:%s: %s",
bind_svp ? SvPV_nolen(*bind_svp) : "?",
port_svp ? SvPV_nolen(*port_svp) : "?",
SvPV_nolen(get_sv("!", 0)));
}
return listener;
}
/* ---- Create a Unix domain listener ---- */
static SV *
_hub_create_unix_listener(pTHX_ HV *hv)
{
SV **name_svp = hv_fetchs(hv, "name", 0);
SV **token_svp = hv_fetchs(hv, "_token", 0);
const char *name_str = (name_svp && SvOK(*name_svp))
? SvPV_nolen(*name_svp) : "default";
SV *path_sv, *listener;
const char *path_str;
STRLEN path_len;
path_sv = _sock_build_path(aTHX_ name_str);
path_str = SvPV(path_sv, path_len);
(void)hv_stores(hv, "_socket_path", newSVsv(path_sv));
(void)PerlLIO_unlink(path_str);
listener = _sock_unix_listen(aTHX_ path_sv);
if (!listener) {
SvREFCNT_dec(path_sv);
croak("Hub: cannot listen on %s: %s",
path_str, SvPV_nolen(get_sv("!", 0)));
}
#ifndef _WIN32
(void)PerlLIO_chmod(path_str, 0600);
#endif
_sock_set_nonblocking(aTHX_ listener);
/* Write token file */
{
SV *token_path_sv = newSVpvf("%s.token", path_str);
(void)hv_stores(hv, "_token_path", newSVsv(token_path_sv));
if (token_svp && SvOK(*token_svp)) {
STRLEN tlen;
const char *tstr = SvPV(*token_svp, tlen);
_sock_write_token_file(aTHX_ SvPV_nolen(token_path_sv), tstr, tlen);
}
SvREFCNT_dec(token_path_sv);
}
SvREFCNT_dec(path_sv);
return listener;
}
/* ---- Start the listener socket ---- */
static void
_hub_start_listener(pTHX_ SV *self)
{
HV *hv = (HV *)SvRV(self);
SV **transport_svp = hv_fetchs(hv, "transport", 0);
SV **select_svp = hv_fetchs(hv, "_select", 0);
const char *transport;
SV *listener;
transport = (transport_svp && SvOK(*transport_svp))
? SvPV_nolen(*transport_svp) : "unix";
#ifdef _WIN32
/* Auto-upgrade to TCP on Windows - Unix domain sockets not available */
if (!strEQ(transport, "tcp")) {
transport = "tcp";
(void)hv_stores(hv, "transport", newSVpvs("tcp"));
}
#endif
if (strEQ(transport, "tcp"))
listener = _hub_create_tcp_listener(aTHX_ hv);
else
listener = _hub_create_unix_listener(aTHX_ hv);
(void)hv_stores(hv, "_listener", listener);
if (select_svp && SvOK(*select_svp))
_sock_select_add(aTHX_ *select_svp, listener);
#ifdef _WIN32
/* Write discovery file so clients can find this TCP hub by name.
* The file contains "port\ntoken\n" and is written to the same
* directory that would hold the Unix socket path. */
{
SV **name_svp = hv_fetchs(hv, "name", 0);
if (name_svp && SvOK(*name_svp)) {
SV *disc_path = _sock_build_path(aTHX_ SvPV_nolen(*name_svp));
/* Get the real bound port via sockname() */
( run in 1.767 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )