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_*/