#include "p5SSLeay.h" static int p5_bio_ex_bio_ptr=0; static int p5_bio_ex_bio_callback=0; static int p5_bio_ex_bio_callback_data=0; static long p5_bio_callback(bio,state,parg,cmd,larg,ret) BIO *bio; int state; char *parg; int cmd; long larg; int ret; { int i; SV *me,*cb; me=(SV *)BIO_get_ex_data(bio,p5_bio_ex_bio_ptr); cb=(SV *)BIO_get_ex_data(bio,p5_bio_ex_bio_callback); if (cb != NULL) { dSP; ENTER ; SAVETMPS; PUSHMARK(sp); XPUSHs(sv_2mortal(newSViv(me))); XPUSHs(sv_2mortal(newSViv(state))); XPUSHs(sv_2mortal(newSViv(cmd))); if ((state == BIO_CB_READ) || (state == BIO_CB_WRITE)) { XPUSHs(sv_2mortal(newSVpv(parg,larg))); } else XPUSHs(&sv_undef); /* ptr one */ XPUSHs(sv_2mortal(newSViv(larg))); XPUSHs(sv_2mortal(newSViv(ret))); PUTBACK; i=perl_call_sv(cb,G_SCALAR); SPAGAIN; if (i == 1) ret=POPi; else ret=1; PUTBACK; FREETMPS; LEAVE; } else { croak("Internal error in SSL p5_ssl_info_callback"); } return(ret); } int boot_bio() { p5_bio_ex_bio_ptr= BIO_get_ex_new_index(0,"SSLeay::BIO",ex_new,NULL, ex_cleanup); p5_bio_ex_bio_callback= BIO_get_ex_new_index(0,"bio_callback",NULL,NULL, ex_cleanup); p5_bio_ex_bio_callback_data= BIO_get_ex_new_index(0,"bio_callback_data",NULL,NULL, ex_cleanup); return(1); } MODULE = SSLeay::BIO PACKAGE = SSLeay::BIO PREFIX = p5_BIO_ VERSIONCHECK: DISABLE void p5_BIO_new_buffer_ssl_connect(...) PREINIT: SSL_CTX *ctx; BIO *bio; SV *arg; PPCODE: if (items == 1) arg=ST(0); else if (items == 2) arg=ST(1); else arg=NULL; if ((arg == NULL) || !(sv_derived_from(arg,"SSLeay::SSL::CTX"))) croak("Usage: SSLeay::BIO::new_buffer_ssl_connect(SSL_CTX)"); else { IV tmp=SvIV((SV *)SvRV(arg)); ctx=(SSL_CTX *)tmp; } EXTEND(sp,1); bio=BIO_new_buffer_ssl_connect(ctx); arg=(SV *)BIO_get_ex_data(bio,p5_bio_ex_bio_ptr); PUSHs(arg); void p5_BIO_new_ssl_connect(...) PREINIT: SSL_CTX *ctx; BIO *bio; SV *arg; PPCODE: if (items == 1) arg=ST(0); else if (items == 2) arg=ST(1); else arg=NULL; if ((arg == NULL) || !(sv_derived_from(arg,"SSLeay::SSL::CTX"))) croak("Usage: SSLeay::BIO::new_ssl_connect(SSL_CTX)"); else { IV tmp=SvIV((SV *)SvRV(arg)); ctx=(SSL_CTX *)tmp; } EXTEND(sp,1); bio=BIO_new_ssl_connect(ctx); arg=(SV *)BIO_get_ex_data(bio,p5_bio_ex_bio_ptr); PUSHs(arg); void p5_BIO_new(...) PREINIT: BIO *bio; char *type; SV *arg; PPCODE: pr_name("p5_BIO_new"); if ((items == 1) && SvPOK(ST(0))) type=SvPV(ST(0),na); else if ((items == 2) && SvPOK(ST(1))) type=SvPV(ST(1),na); else croak("Usage: SSLeay::BIO::new(type)"); EXTEND(sp,1); if (strcmp(type,"connect") == 0) bio=BIO_new(BIO_s_connect()); else if (strcmp(type,"accept") == 0) bio=BIO_new(BIO_s_accept()); else if (strcmp(type,"ssl") == 0) bio=BIO_new(BIO_f_ssl()); else if (strcmp(type,"buffer") == 0) bio=BIO_new(BIO_f_buffer()); else croak("unknown BIO type"); arg=(SV *)BIO_get_ex_data(bio,p5_bio_ex_bio_ptr); PUSHs(arg); int p5_BIO_hostname(bio,name) BIO *bio; char *name; CODE: RETVAL=BIO_set_conn_hostname(bio,name); OUTPUT: RETVAL int p5_BIO_set_accept_port(bio,str) BIO *bio; char *str; CODE: RETVAL=BIO_set_accept_port(bio,str); OUTPUT: RETVAL int p5_BIO_do_handshake(bio) BIO *bio; CODE: RETVAL=BIO_do_handshake(bio); OUTPUT: RETVAL BIO * p5_BIO_push(b,bio) BIO *b; BIO *bio; CODE: /* This reference will be reduced when the reference is * let go, and then when the BIO_free_all() is called * inside the SSLeay library by the BIO with this * pushed into */ bio->references++; RETVAL=BIO_push(b,bio); OUTPUT: RETVAL void p5_BIO_pop(b) BIO *b PREINIT: BIO *bio; char *type; SV *arg; PPCODE: bio=BIO_pop(b); if (bio != NULL) { /* This BIO will either be one created in the * perl library, in which case it will have a perl * SV, otherwise it will have been created internally, * inside SSLeay. For the 'pushed in', it needs * the reference count decememted. */ arg=(SV *)BIO_get_ex_data(bio,p5_bio_ex_bio_ptr); if (arg == NULL) { arg=new_ref("SSLeay::BIO",(char *)bio,0); BIO_set_ex_data(bio,p5_bio_ex_bio_ptr,(char *)arg); PUSHs(arg); } else { /* it was pushed in */ SvREFCNT_inc(arg); PUSHs(arg); #if 0 /* This does not need to be done. */ if (bio->references < 1) abort(); /* decrement the reference count */ BIO_free(bio); #endif } } int p5_BIO_sysread(bio,in,num, ...) BIO *bio; SV *in; int num; PREINIT: int i,n,olen; int offset; char *p; CODE: offset=0; if (!SvPOK(in)) sv_setpvn(in,"",0); SvPV(in,olen); if (items > 3) { offset=SvIV(ST(3)); if (offset < 0) { if (-offset > olen) croak("Offset outside string"); offset+=olen; } } if ((num+offset) > olen) { SvGROW(in,num+offset+1); p=SvPV(in,i); memset(&(p[olen]),0,(num+offset)-olen+1); } p=SvPV(in,n); i=BIO_read(bio,p+offset,num); RETVAL=i; if (i <= 0) i=0; SvCUR_set(in,offset+i); OUTPUT: RETVAL int p5_BIO_syswrite(bio,in, ...) BIO *bio; SV *in; PREINIT: char *ptr; int len,in_len; int offset=0; int n; CODE: ptr=SvPV(in,in_len); if (items > 2) { len=SvOK(ST(2))?SvIV(ST(2)):in_len; if (items > 3) { offset=SvIV(ST(3)); if (offset < 0) { if (-offset > in_len) croak("Offset outside string"); offset+=in_len; } else if ((offset >= in_len) && (in_len > 0)) croak("Offset outside string"); } if (len >= (in_len-offset)) len=in_len-offset; } else len=in_len; RETVAL=BIO_write(bio,ptr+offset,len); OUTPUT: RETVAL void p5_BIO_getline(bio) BIO *bio; PREINIT: int i; char *p; PPCODE: pr_name("p5_BIO_gets"); EXTEND(sp,1); PUSHs(sv_newmortal()); sv_setpvn(ST(0),"",0); SvGROW(ST(0),1024); p=SvPV(ST(0),na); i=BIO_gets(bio,p,1024); if (i < 0) i=0; SvCUR_set(ST(0),i); int p5_BIO_flush(bio) BIO *bio; CODE: RETVAL=BIO_flush(bio); OUTPUT: RETVAL char * p5_BIO_type(bio) BIO *bio; CODE: RETVAL=bio->method->name; OUTPUT: RETVAL void p5_BIO_next_bio(b) BIO *b PREINIT: BIO *bio; char *type; SV *arg; PPCODE: bio=b->next_bio; if (bio != NULL) { arg=(SV *)BIO_get_ex_data(bio,p5_bio_ex_bio_ptr); if (arg == NULL) { arg=new_ref("SSLeay::BIO",(char *)bio,0); BIO_set_ex_data(bio,p5_bio_ex_bio_ptr,(char *)arg); bio->references++; PUSHs(arg); } else { SvREFCNT_inc(arg); PUSHs(arg); } } int p5_BIO_puts(bio,in) BIO *bio; SV *in; PREINIT: char *ptr; CODE: ptr=SvPV(in,na); RETVAL=BIO_puts(bio,ptr); OUTPUT: RETVAL void p5_BIO_set_callback(bio,cb,...) BIO *bio; SV *cb; PREINIT: SV *arg=NULL; SV *arg2=NULL; CODE: if (items > 3) croak("Usage: SSLeay::BIO::set_callback(bio,callback[,arg]"); if (items == 3) { arg2=sv_mortalcopy(ST(2)); SvREFCNT_inc(arg2); BIO_set_ex_data(bio,p5_bio_ex_bio_callback_data, (char *)arg2); } arg=sv_mortalcopy(ST(1)); SvREFCNT_inc(arg); BIO_set_ex_data(bio,p5_bio_ex_bio_callback,(char *)arg); printf("%08lx < bio_ptr\n",BIO_get_ex_data(bio,p5_bio_ex_bio_ptr)); BIO_set_callback(bio,p5_bio_callback); void p5_BIO_DESTROY(bio) BIO *bio PREINIT: SV *sv; PPCODE: pr_name_d("p5_BIO_DESTROY",bio->references); printf("p5_BIO_DESTROY <%s> %d\n",bio->method->name,bio->references); BIO_set_ex_data(bio,p5_bio_ex_bio_ptr,NULL); BIO_free_all(bio); int p5_BIO_set_ssl(bio,ssl) BIO *bio; SSL *ssl; CODE: pr_name("p5_BIO_set_ssl"); ssl->references++; RETVAL=BIO_set_ssl(bio,ssl,BIO_CLOSE); OUTPUT: RETVAL int p5_BIO_number_read(bio) BIO *bio; CODE: RETVAL=BIO_number_read(bio); OUTPUT: RETVAL int p5_BIO_number_written(bio) BIO *bio; CODE: RETVAL=BIO_number_written(bio); OUTPUT: RETVAL int p5_BIO_references(bio) BIO *bio; CODE: RETVAL=bio->references; OUTPUT: RETVAL