#include "tunala.h"
#ifndef NO_BUFFER
void buffer_init(buffer_t *buf)
{
buf->used = 0;
buf->total_in = buf->total_out = 0;
}
void buffer_close(buffer_t *buf)
{
buf->used = 0;
}
unsigned int buffer_used(buffer_t *buf) {
return buf->used; }
unsigned int buffer_unused(buffer_t *buf) {
return (MAX_DATA_SIZE - buf->used); }
int buffer_full(buffer_t *buf) {
return (buf->used == MAX_DATA_SIZE ? 1 : 0); }
int buffer_notfull(buffer_t *buf) {
return (buf->used < MAX_DATA_SIZE ? 1 : 0); }
int buffer_empty(buffer_t *buf) {
return (buf->used == 0 ? 1 : 0); }
int buffer_notempty(buffer_t *buf) {
return (buf->used > 0 ? 1 : 0); }
unsigned long buffer_total_in(buffer_t *buf) {
return buf->total_in; }
unsigned long buffer_total_out(buffer_t *buf) {
return buf->total_out; }
#if 0
static unsigned int buffer_adddata(buffer_t *buf, const unsigned char *ptr,
unsigned int size)
{
unsigned int added = MAX_DATA_SIZE - buf->used;
if(added > size)
added = size;
if(added == 0)
return 0;
memcpy(buf->data + buf->used, ptr, added);
buf->used += added;
buf->total_in += added;
return added;
}
static unsigned int buffer_tobuffer(buffer_t *to, buffer_t *from, int cap)
{
unsigned int moved, tomove = from->used;
if((int)tomove > cap)
tomove = cap;
if(tomove == 0)
return 0;
moved = buffer_adddata(to, from->data, tomove);
if(moved == 0)
return 0;
buffer_takedata(from, NULL, moved);
return moved;
}
#endif
static unsigned int buffer_takedata(buffer_t *buf, unsigned char *ptr,
unsigned int size)
{
unsigned int taken = buf->used;
if(taken > size)
taken = size;
if(taken == 0)
return 0;
if(ptr)
memcpy(ptr, buf->data, taken);
buf->used -= taken;
if(buf->used > 0)
memmove(buf->data, buf->data + taken, buf->used);
return taken;
}
#ifndef NO_IP
int buffer_from_fd(buffer_t *buf, int fd)
{
int toread = buffer_unused(buf);
if(toread == 0)
abort();
toread = read(fd, buf->data + buf->used, toread);
if(toread > 0) {
buf->used += toread;
buf->total_in += toread;
}
return toread;
}
int buffer_to_fd(buffer_t *buf, int fd)
{
int towrite = buffer_used(buf);
if(towrite == 0)
abort();
towrite = write(fd, buf->data, towrite);
if(towrite > 0) {
buffer_takedata(buf, NULL, towrite);
buf->total_out += towrite;
}
return towrite;
}
#endif
#ifndef NO_OPENSSL
static void int_ssl_check(SSL *s, int ret)
{
int e = SSL_get_error(s, ret);
switch(e) {
case SSL_ERROR_NONE:
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_X509_LOOKUP:
case SSL_ERROR_ZERO_RETURN:
return;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
SSL_set_app_data(s, (char *)1);
return;
default:
break;
}
abort();
}
void buffer_from_SSL(buffer_t *buf, SSL *ssl)
{
int ret;
if(!ssl || buffer_full(buf))
return;
ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
if(ret > 0) {
buf->used += ret;
buf->total_in += ret;
}
if(ret < 0)
int_ssl_check(ssl, ret);
}
void buffer_to_SSL(buffer_t *buf, SSL *ssl)
{
int ret;
if(!ssl || buffer_empty(buf))
return;
ret = SSL_write(ssl, buf->data, buf->used);
if(ret > 0) {
buffer_takedata(buf, NULL, ret);
buf->total_out += ret;
}
if(ret < 0)
int_ssl_check(ssl, ret);
}
void buffer_from_BIO(buffer_t *buf, BIO *bio)
{
int ret;
if(!bio || buffer_full(buf))
return;
ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
if(ret > 0) {
buf->used += ret;
buf->total_in += ret;
}
}
void buffer_to_BIO(buffer_t *buf, BIO *bio)
{
int ret;
if(!bio || buffer_empty(buf))
return;
ret = BIO_write(bio, buf->data, buf->used);
if(ret > 0) {
buffer_takedata(buf, NULL, ret);
buf->total_out += ret;
}
}
#endif
#endif