Crypt-OpenSSL-CA

 view release on metacpan or  search on metacpan

lib/Crypt/OpenSSL/CA/Inline/C.pm  view on Meta::CPAN


static inline SV* perl_wrap(const char* class, void* pointer) {
     SV*      obj = sv_setref_pv(newSV(0), class, pointer);
     if (! obj) { croak("not enough memory"); }
     SvREADONLY_on(SvRV(obj));
     return obj;
}

#define perl_unwrap(class, typename, obj) \
  ((typename) __perl_unwrap(__FILE__, __LINE__, (class), (obj)))

static inline void* __perl_unwrap(const char* file, int line,
                                  const char* class, SV* obj) {
    if (!(sv_isobject(obj) && sv_isa(obj, class))) {
      croak("%s:%d:perl_unwrap: got an invalid "
                "Perl argument (expected an object blessed "
                "in class ``%s'')", file, line, (class));
    }
    return (void *)(intptr_t)SvIV(SvRV(obj));
}

static inline SV* openssl_buf_to_SV(char* string, int length) {
/* Note that a newmortal is not wanted here, even though
 * caller will typically return the SV* to Perl. This is because XS
 * performs some magic of its own for functions that return an SV (as
 * documented in L<perlxs/Returning SVs, AVs and HVs through RETVAL>)
 * and Inline::C leverages that. */
   SV* retval = newSVpv(string, length);
   OPENSSL_free(string);
   return retval;
}

static inline SV* openssl_string_to_SV(char* string) {
   return openssl_buf_to_SV(string, 0);
}

static inline SV* BIO_mem_to_SV(BIO *mem) {
   SV* retval;
   BUF_MEM* buf;

   BIO_get_mem_ptr(mem, &buf);
   if (! buf) {
        BIO_free(mem);
        croak("BIO_get_mem_ptr failed");
   }
   retval = newSVpv(buf->data, 0);
   if (! retval) {
        BIO_free(mem);
        croak("newSVpv failed");
   }
   BIO_free(mem);
   return retval;
}

#define ERRBUFSZ 512
#define THISPACKAGE "Crypt::OpenSSL::CA"
static void sslcroak(char *fmt, ...) {
    va_list ap;                 /* The argument list hiding behind the
                                   hyphens in the protype above */
    dSP;                        /* Required to be able to perform Perl
                                   callbacks */
    char* argv[3];              /* The list of arguments to pass to the
                                   callback */
    char croakbuf[ERRBUFSZ];    /* The buffer to typeset the main error
                                   message into */
    char errbuf[ERRBUFSZ];      /* The buffer to typeset the auxillary error
                                   messages from OpenSSL into */
    SV* dollar_at;              /* Used to probe $@ to see if everything
                                   went well with the callback */
    unsigned long sslerr;       /* Will iterate through the OpenSSL
                                   error stack */

    va_start(ap, fmt);
    vsnprintf(croakbuf, ERRBUFSZ, fmt, ap);
    croakbuf[ERRBUFSZ - 1] = '\0';
    va_end(ap);

    argv[0] = "-message";
    argv[1] = croakbuf;
    argv[2] = NULL;
    call_argv(THISPACKAGE "::_sslcroak_callback", G_DISCARD, argv);

    argv[0] = "-openssl";
    argv[1] = errbuf;
    while( (sslerr = ERR_get_error()) ) {
        ERR_error_string_n(sslerr, errbuf, ERRBUFSZ);
        errbuf[ERRBUFSZ - 1] = '\0';
        call_argv(THISPACKAGE "::_sslcroak_callback", G_DISCARD, argv);
    }
    argv[0] = "DONE";
    argv[1] = NULL;
    call_argv(THISPACKAGE "::_sslcroak_callback", G_DISCARD, argv);

    dollar_at = get_sv("@", FALSE);
    if (dollar_at && sv_isobject(dollar_at)) {
         // Success!
         croak(Nullch);
    } else {
         // Something went bang, revert to the croakbuf.
         croak("%s", croakbuf);
    }
}

C_BOILERPLATE

=head2 BOOT-time effect

Each C<.so> XS module will be fitted with a C<BOOT> section (see
L<Inline::C/BOOT> which automatically gets executed upon loading it
with L<DynaLoader> or L<XSLoader>. The C<BOOT> section is the same for
all subpackages in L<Crypt::OpenSSL::CA>; it ensures that various
stuff is loaded inside OpenSSL, such as C<ERR_load_crypto_strings()>,
C<OpenSSL_add_all_algorithms()> and all that jazz.  After the boot
code completes, C<$Crypt::OpenSSL::CA::openssl_stuff_loaded> will be
1, so that the following XS modules can skip that when they in turn
get loaded.

=cut

sub _c_boot_section { <<"ENSURE_OPENSSL_STUFF_LOADED" }
    SV* already_loaded = get_sv



( run in 1.704 second using v1.01-cache-2.11-cpan-437f7b0c052 )