Moshe, Kfir schrieb: > > Hey > > > > I would like to change the main send and receive function that > OpenSSL uses to functions written by me > > So every packet send\receive by OpenSSL will be actually send\receive > from my code > > BUT: I want to keep the whole TLS\SSL logic as is > Yes, easy, just for OpenSSL beginner as I am. Just take source copy of BIO_s_accept, build your own copy (must create IOCTLs with higher, unused numbers) and change directly in your own custom switch() block.
To better understanding, you can use my gauge/progress indicator BIO, which is hereby released to public without any license or restriction. But note: BIO_f_gauge is not production quality code, just for my learning of BIO concept, last week. Greetings, Modem Man
#include <string.h> /*strlen*/ #include <time.h> /*strlen*/ #include <openssl\bio.h> #include <openssl\err.h> #include "BIO_f_gauge.h" #ifdef __cplusplus extern "C" { #endif static int gauge_write(BIO *h, const char *buf,int num); static int gauge_read( BIO *h, char *buf, int size); static int gauge_puts( BIO *h, const char *str); static int gauge_gets( BIO *h, char *str, int size); static long gauge_ctrl( BIO *h, int cmd, long arg1, void *arg2); static int gauge_new( BIO *h); static int gauge_free( BIO *data); static long gauge_callback_ctrl( BIO *h, int cmd, bio_info_cb *fp ); typedef struct gauge_struct { unsigned long Rx,Tx; time_t TxStartTime, RxStartTime; void * GaugeHandle; GAUGE_CALLBACK_ROUTINE GaugeCB; } BIO_F_GAUGE_CTX; /* Sample Gauge foo */ #if 0 void Gauge( BIO *b, void* GaugeHandle, int IsRx ) { FILE *fHnd; unsigned long Value, Speed; time_t Delta, Last; Value = BIO_ctrl( b, (IsRx) ? BIO_CTRL_GAUGE_GET_RX : BIO_CTRL_GAUGE_GET_TX, 0, NULL ); Last = BIO_ctrl( b, (IsRx) ? BIO_CTRL_GAUGE_GET_RXTIME : BIO_CTRL_GAUGE_GET_TXTIME, 0, NULL ); Delta = time(NULL) - Last; /* WinCE: time() emulation or port is avail as open source/free */ if(0==Delta) Delta++; /* simple div by zero blocker */ Speed = Value / (unsigned long) Delta; fHnd = (FILE*) GaugeHandle; if( fHnd ) { fprintf( fHnd, "== Transfer Speed %s: %lu cps (%lu in %lu)==\n", (IsRx)?"Rx":"Tx", Speed, Value, Delta ); } return; } #endif static BIO_METHOD methods_gauge = { BIO_TYPE_GAUGE, "gauge", gauge_write, gauge_read, gauge_puts, gauge_gets, gauge_ctrl, gauge_new, gauge_free, gauge_callback_ctrl, }; BIO_METHOD *BIO_f_gauge( void ) { return( &methods_gauge ); } static int gauge_new(BIO *bi) { BIO_F_GAUGE_CTX *ctx; ctx=(BIO_F_GAUGE_CTX *)OPENSSL_malloc(sizeof(BIO_F_GAUGE_CTX)); if (ctx == NULL) return(0); ctx->Rx = 0UL; ctx->Tx = 0UL; ctx->GaugeHandle = (void*) 0; ctx->GaugeCB = (GAUGE_CALLBACK_ROUTINE) 0; bi->init=1; bi->ptr=(char *)ctx; bi->flags=0; return(1); } static int gauge_free(BIO *a) { BIO_F_GAUGE_CTX *b; if (a == NULL) return(0); b=(BIO_F_GAUGE_CTX *)a->ptr; OPENSSL_free(a->ptr); a->ptr=NULL; a->init=0; a->flags=0; return(1); } static int gauge_read(BIO *b, char *out, int outl) { BIO_F_GAUGE_CTX *ctx; int i,num=0; if (out == NULL) return(0); ctx=(BIO_F_GAUGE_CTX *)b->ptr; if ((ctx == NULL) || (b->next_bio == NULL)) return(0); BIO_clear_retry_flags(b); i=BIO_read( b->next_bio, out, outl ); if(i>0) { if( 0==ctx->Rx ) ctx->RxStartTime = time(NULL); /* WinCE: time() emulation or port is avail as open source/free */ ctx->Rx += i; if( ctx->GaugeCB ) ctx->GaugeCB( b, ctx->GaugeHandle, 1 ); // unclear : b->num_read += i; } else { BIO_copy_next_retry(b); } return i; } static int gauge_write(BIO *b, const char *in, int inl) { BIO_F_GAUGE_CTX *ctx; int i,num=0; if ((in == NULL) || (inl <= 0)) return(0); ctx=(BIO_F_GAUGE_CTX *)b->ptr; if ((ctx == NULL) || (b->next_bio == NULL)) return(0); BIO_clear_retry_flags(b); i=BIO_write( b->next_bio, in, inl ); if(i>0) { if( 0==ctx->Tx ) ctx->TxStartTime = time(NULL); /* WinCE: time() emulation or port is avail as open source/free */ ctx->Tx += i; if( ctx->GaugeCB ) ctx->GaugeCB( b, ctx->GaugeHandle, 0 ); // unclear : b->num_write += i; } else { BIO_copy_next_retry(b); } return i; } static long gauge_ctrl(BIO *b, int cmd, long num, void *ptr) { BIO_F_GAUGE_CTX *ctx; long ret=1; ctx=(BIO_F_GAUGE_CTX *)b->ptr; if (ctx == NULL) return(0); switch (cmd) { case BIO_CTRL_GAUGE_SET_FOO: // (0xA0) ctx->GaugeCB = (GAUGE_CALLBACK_ROUTINE) ptr; return 1; case BIO_CTRL_GAUGE_SET_HND: // (0xA1) ctx->GaugeHandle = ptr; return 1; case BIO_CTRL_GAUGE_GET_RX : // (0xA2) { unsigned long *pV = (unsigned long *) ptr; ret=(long) ctx->Rx; if( pV ) *pV = ctx->Rx; }; break; case BIO_CTRL_GAUGE_GET_TX : // (0xA3) { unsigned long *pV = (unsigned long *) ptr; ret=(long) ctx->Tx; if( pV ) *pV = ctx->Tx; }; break; case BIO_CTRL_GAUGE_GET_RXTIME: // (0xA4) { time_t *pV = (time_t *) ptr; ret=(long) ctx->RxStartTime; if( pV ) *pV = ctx->RxStartTime; }; break; case BIO_CTRL_GAUGE_GET_TXTIME: // (0xA5) { time_t *pV = (time_t *) ptr; ret=(long) ctx->TxStartTime; if( pV ) *pV = ctx->TxStartTime; }; break; case BIO_C_DO_STATE_MACHINE: if (b->next_bio == NULL) return(0); BIO_clear_retry_flags(b); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); BIO_copy_next_retry(b); break; default: if (b->next_bio == NULL) return(0); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; } return(ret); } static long gauge_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) { long ret=1; if (b->next_bio == NULL) return(0); switch (cmd) { default: ret=BIO_callback_ctrl(b->next_bio,cmd,fp); break; } return(ret); } static int gauge_gets(BIO *b, char *buf, int size) { BIO_F_GAUGE_CTX *ctx; int i; ctx=(BIO_F_GAUGE_CTX *)b->ptr; if ((ctx == NULL) || (buf == NULL) || (size<0)) return(0); i=BIO_read(b->next_bio,buf,size); if(i>0) { if( 0==ctx->Rx ) ctx->RxStartTime = time(NULL); /* WinCE: time() emulation or port is avail as open source/free */ ctx->Rx += i; if( ctx->GaugeCB ) ctx->GaugeCB( b, ctx->GaugeHandle, 1 ); // unclear : b->num_read += i; } else { BIO_copy_next_retry(b); } return i; } static int gauge_puts(BIO *b, const char *str) { return(gauge_write(b,str,(int)strlen(str))); } #ifdef __cplusplus } #endif
#ifndef BIO_f_gauge_h_ #define BIO_f_gauge_h_ #include <openssl\bio.h> #ifdef __cplusplus extern "C" { #endif #define BIO_TYPE_GAUGE (0xA0 | BIO_TYPE_FILTER) #define BIO_CTRL_GAUGE_SET_FOO (0xA0) #define BIO_CTRL_GAUGE_SET_HND (0xA1) #define BIO_CTRL_GAUGE_GET_RX (0xA2) #define BIO_CTRL_GAUGE_GET_TX (0xA3) #define BIO_CTRL_GAUGE_GET_RXTIME (0xA4) #define BIO_CTRL_GAUGE_GET_TXTIME (0xA5) typedef void (*GAUGE_CALLBACK_ROUTINE)( BIO *b, void* GaugeHandle, int IsRx ); BIO_METHOD *BIO_f_gauge(void); #ifdef __cplusplus } #endif #endif /*BIO_f_gauge_h_*/