EV-Etcd

 view release on metacpan or  search on metacpan

Etcd.xs  view on Meta::CPAN

    client->keepalive_timeout_ms = seconds_to_ms(keepalive_timeout);
    if (!client->keepalive_timeout_ms)
        client->keepalive_timeout_ms = 10000;

    if (tls) {
        grpc_ssl_pem_key_cert_pair pair;
        if (cert_pem) {
            pair.private_key = SvPV_nolen(key_pem);
            pair.cert_chain = SvPV_nolen(cert_pem);
        }
        client->creds = grpc_ssl_credentials_create(
            ca_pem ? SvPV_nolen(ca_pem) : NULL, cert_pem ? &pair : NULL, NULL, NULL);
        if (!client->creds) {
            for (int j = 0; j < client->endpoint_count; j++) {
                Safefree(client->endpoints[j]);
            }
            Safefree(client->endpoints);
            Safefree(client);
            grpc_release();
            croak("EV::Etcd: failed to create TLS credentials");
        }
        if (key_pem)
            memset(SvPVX(key_pem), 0, SvCUR(key_pem));
        if (tls_server_name)
            client->tls_server_name = savepv(tls_server_name);
    }

    client->channel_ref = etcd_create_channel(client, client->endpoints[0]);

    if (!client->channel_ref) {
        for (int j = 0; j < client->endpoint_count; j++) {
            Safefree(client->endpoints[j]);
        }
        Safefree(client->endpoints);
        if (client->creds) grpc_channel_credentials_release(client->creds);
        Safefree(client->tls_server_name);
        Safefree(client);
        grpc_release();
        croak("Failed to create gRPC channel");
    }
    client->channel = client->channel_ref->channel;

    client->cq = grpc_completion_queue_create_for_next(NULL);

    pthread_mutex_init(&client->queue_mutex, NULL);

Etcd.xs  view on Meta::CPAN

        grpc_completion_queue_shutdown(client->cq);
        while (grpc_completion_queue_next(client->cq,
               gpr_inf_past(GPR_CLOCK_REALTIME), NULL).type != GRPC_QUEUE_SHUTDOWN)
            ;
        grpc_completion_queue_destroy(client->cq);
        etcd_channel_release(client->channel_ref, 1);
        for (int j = 0; j < client->endpoint_count; j++) {
            Safefree(client->endpoints[j]);
        }
        Safefree(client->endpoints);
        if (client->creds) grpc_channel_credentials_release(client->creds);
        Safefree(client->tls_server_name);
        Safefree(client);
        grpc_release();
        croak("Failed to create gRPC completion queue thread");
    }

    if (init_auth_token && init_auth_token_len > 0) {
        Newx(client->auth_token, init_auth_token_len + 1, char);
        Copy(init_auth_token, client->auth_token, init_auth_token_len, char);
        client->auth_token[init_auth_token_len] = '\0';

Etcd.xs  view on Meta::CPAN

        while (client->keepalives) cleanup_keepalive(aTHX_ client->keepalives);
        while (client->observes) cleanup_observe(aTHX_ client->observes);
    }

    ev_timer_stop(EV_DEFAULT, &client->health_timer);

    etcd_channel_release(client->channel_ref, 1);
    client->channel_ref = NULL;
    client->channel = NULL;
    if (client->creds) {
        grpc_channel_credentials_release(client->creds);
        client->creds = NULL;
    }
    if (!client->in_callback)
        grpc_release();

    free_perl_resources:
    etcd_channel_release(client->channel_ref, 0);
    client->channel_ref = NULL;
    if (client->health_callback) {
        SvREFCNT_dec(client->health_callback);

Makefile.PL  view on Meta::CPAN

my $ev_inc_path = "-I$ev_inc";

my $grpc_cflags = `pkg-config --cflags grpc 2>/dev/null` || '';
my $grpc_libs = `pkg-config --libs grpc 2>/dev/null` || '-lgrpc';
chomp($grpc_cflags, $grpc_libs);

my $protobuf_c_cflags = `pkg-config --cflags libprotobuf-c 2>/dev/null` || '';
my $protobuf_c_libs = `pkg-config --libs libprotobuf-c 2>/dev/null` || '-lprotobuf-c';
chomp($protobuf_c_cflags, $protobuf_c_libs);

# - gRPC >= 1.45: grpc_insecure_credentials_create() + grpc_channel_create()
# - gRPC <  1.45: grpc_insecure_channel_create()
# The new API header moved from grpc_security.h to credentials.h in ~1.65
use File::Temp qw(tempdir);
my $grpc_api_defines = '';
my $tmpdir = tempdir(CLEANUP => 1);

sub try_compile {
    my ($cflags, $code) = @_;
    open my $fh, '>', "$tmpdir/test.c" or return 0;
    print $fh $code;
    close $fh;
    my $cc = $Config{cc} || 'cc';

Makefile.PL  view on Meta::CPAN

#error protobuf-c too old
#endif
void test(void) { grpc_shutdown_blocking(); }
int main(void) { return 0; }
END
    warn "EV::Etcd requires gRPC >= 1.20 and protobuf-c >= 1.3.0\n";
    exit 0;
}

if (try_compile($all_cflags, <<'END')) {
#include <grpc/credentials.h>
int main(void) { return 0; }
END
    $grpc_api_defines .= ' -DHAVE_GRPC_CREDENTIALS_H';
    print "Detected <grpc/credentials.h>\n";
}

my $creds_test_header = ($grpc_api_defines =~ /HAVE_GRPC_CREDENTIALS_H/)
    ? '#include <grpc/credentials.h>' : '#include <grpc/grpc_security.h>';
if (try_compile("$all_cflags $grpc_api_defines", <<"END")) {
#include <grpc/grpc.h>
$creds_test_header
void test(void) {
    grpc_channel_credentials *c = grpc_insecure_credentials_create();
    grpc_channel *ch = grpc_channel_create("localhost", c, NULL);
    (void)ch;
}
int main(void) { return 0; }
END
    $grpc_api_defines .= ' -DHAVE_GRPC_NEW_CHANNEL_API';
    print "Detected grpc_channel_create (new channel API)\n";
} else {
    print "Using legacy grpc_insecure_channel_create\n";
}

etcd_common.c  view on Meta::CPAN

        set_int_arg(&arg[args.num_args++], "grpc.keepalive_time_ms", client->keepalive_ms);
        set_int_arg(&arg[args.num_args++], "grpc.keepalive_timeout_ms", client->keepalive_timeout_ms);
        set_int_arg(&arg[args.num_args++], "grpc.keepalive_permit_without_calls", 0);
        set_int_arg(&arg[args.num_args++], "grpc.http2.max_pings_without_data", 0);
        set_int_arg(&arg[args.num_args++], "grpc.http2.min_time_between_pings_ms", client->keepalive_ms);
        set_int_arg(&arg[args.num_args++], "grpc.http2.ping_timeout_ms", client->keepalive_timeout_ms);
    }
    /* grpc_channel_create arrived in gRPC 1.45 */
    grpc_channel *channel;
#ifdef HAVE_GRPC_NEW_CHANNEL_API
    grpc_channel_credentials *creds = client->creds
        ? client->creds : grpc_insecure_credentials_create();
    WITH_SIGNALS_BLOCKED(channel = grpc_channel_create(target, creds, &args));
    if (!client->creds) grpc_channel_credentials_release(creds);
#else
    WITH_SIGNALS_BLOCKED(channel = client->creds
        ? grpc_secure_channel_create(client->creds, target, &args, NULL)
        : grpc_insecure_channel_create(target, &args, NULL));
#endif
    if (!channel) return NULL;

    channel_ref_t *ref;
    Newx(ref, 1, channel_ref_t);
    ref->channel = channel;

etcd_common.h  view on Meta::CPAN

    do { \
        sigset_t _ws_all, _ws_old; \
        sigfillset(&_ws_all); \
        pthread_sigmask(SIG_SETMASK, &_ws_all, &_ws_old); \
        stmt; \
        pthread_sigmask(SIG_SETMASK, &_ws_old, NULL); \
    } while (0)

#include <grpc/grpc.h>
#ifdef HAVE_GRPC_CREDENTIALS_H
#include <grpc/credentials.h>
#else
#include <grpc/grpc_security.h>
#endif
#include <grpc/byte_buffer.h>
#include <grpc/byte_buffer_reader.h>

#include "kv.pb-c.h"
#include "rpc.pb-c.h"
#include "lock.pb-c.h"
#include "election.pb-c.h"

etcd_common.h  view on Meta::CPAN

    int in_callback;  /* Guard against freeing client during event processing */
    char *auth_token;
    size_t auth_token_len;
    int timeout_seconds;

    char **endpoints;
    int endpoint_count;
    int current_endpoint;
    unsigned channel_gen;  /* bumped on every endpoint switch */

    grpc_channel_credentials *creds;  /* NULL = insecure */
    char *tls_server_name;
    int keepalive_ms;          /* 0 = no keepalive pings */
    int keepalive_timeout_ms;

    int max_retries;
    /* Bumped by each answer without a leader: voids reconnects counted before it */
    unsigned no_leader_epoch;

    ev_timer health_timer;
    int is_healthy;

t/auth.t  view on Meta::CPAN

{
    my $wrong_err;
    $client->authenticate($test_user, 'wrong-password', sub {
        my ($resp, $err) = @_;
        $wrong_err = $err;
        EV::break;
    });
    my $t_wrong = EV::timer(5, 0, sub { fail('timeout'); EV::break });
    EV::run;

    # Auth not enabled or invalid credentials: an error either way
    ok($wrong_err, 'authenticate with wrong password returns error');
    diag("Wrong password error: " . ($wrong_err->{message} // $wrong_err));
}

{
    my $change_result;
    my $change_err;
    $client->user_change_password($test_user, 'new-password-456', sub {
        my ($resp, $err) = @_;
        $change_result = $resp;



( run in 0.699 second using v1.01-cache-2.11-cpan-3f962061493 )