/*
* socket.h
*/
#ifndef __SOCKET_H
# define __SOCKET_H
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#ifdef HAVE_POLL_H
# include <poll.h>
#elif HAVE_SYS_POLL_H
# include <sys/poll.h>
#else
#ifndef USE_SELECT
#define USE_SELECT
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
struct pollfd
{
int fd; /* File descriptor to poll. */
short int events; /* Types of events poller cares about. */
short int revents; /* Types of events that actually occurred. */
};
#define POLLIN 0x001 /* There is data to read. */
#define POLLPRI 0x002 /* There is urgent data to read. */
#define POLLOUT 0x004 /* Writing now will not block. */
#define POLLERR 0x008 /* Error condition. */
#define POLLHUP 0x010 /* Hung up. */
#define POLLNVAL 0x020 /* Invalid polling request. */
#endif
#ifdef _USE_SSL
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#endif
#include "dynbuff.h"
class pollsocket
{
protected:
int fd;
static int num_socks;
static pollsocket **table;
static int MAX_SOCKETS;
dynbuff * ibuff;
dynbuff * obuff;
#ifdef _USE_SSL
static SSL_CTX *ssl_ctx;
static char *tls_rand_file;
static int seed_PRNG(void);
SSL *ssl;
#endif
#ifdef USE_SELECT
static fd_set fds_read, fds_write;
static fd_set res_read, res_write;
static int highest_fd;
#else
static int num_pfds;
static pollfd * pfds;
static struct pollfd * find_empty_slot();
int idx;
#endif
public:
pollsocket(int f, bool * success, int events = POLLIN | POLLOUT, int = 512, int = 0);
virtual ~pollsocket();
virtual int event_handler(const struct pollfd *) = 0;
static int create_table(int );
static int poll_all(int );
static int compress(void);
int close(void);
int set_events(int);
int set_revents(int);
/** (buffered) reads and writes
int read(int = 0);
int queue(const void *, int);
int write(const void * , int);
*** Flush input buffer ... ***
int flush(pollsocket *); ** ... to another socket (output buff) **
int flush(int, int); ** ... to a raw file descriptor **
*** Flush output buffer ... ***
int flushO(pollsocket *); ** ... to another socket (input buff) **
int flushO(int = 0); ** ... out our own fd
*** To clear buffers ***
void clear();
void clearO();
**/
void optimize_buffers(void);
int printf(const char *, ...);
int printf_raw(const char *, va_list *);
#ifdef _USE_SSL
bool switch_to_ssl(void);
bool accept_to_ssl(void);
static int init_ssl(const char *);
static int shutdown_ssl(void);
#endif
#ifdef USE_SELECT
int events() const;
int revents() const;
int revents(int) const;
#else
/* Get the events flag */
int events() const
{
if (fd > -1)
return pfds[idx].events;
return 0;
}
/* Returns the result flags */
int revents() const
{
if (fd > -1)
return pfds[idx].revents;
return 0;
}
/* Tries to match a result flag */
int revents(int r) const
{
if (fd > -1)
return (pfds[idx].revents & r);
return 0;
}
#endif
/*
* read() from file descriptor & add to buffer
* return: > 0 = success (bytes added)
* 0 = nothing to add
* < 0 = error condition
* [... error codes same as dynbuff error codes ...]
*/
int read(int b = 0)
{
#ifdef _USE_SSL
if (ssl)
return ibuff->add(ssl, b);
#endif
return ibuff->add(fd, b);
}
/* buffer size bytes, and attempt to send as much as possible
* return # bytes sent */
int write(const void * data , int size)
{
int r = queue(data, size);
if (r < 0)
return r;
return obuff->flush(fd);
}
/* buffer 'size' bytes, but do not send
* return # bytes queued */
int queue(const void * data, int size)
{
return obuff->add((const char *) data, size);
}
/* flush input buffer to output buffer of
* socket */
int flush(pollsocket * target)
{
return ibuff->transfer(target->obuff);
}
#if 0
/* flush input buffer to a file descriptor */
int flush(int fd, int size)
{
return ibuff->flush(fd, size);
}
#endif
/* flush output buffer to input buffer of
* another socket */
int flushO(pollsocket * target)
{
return obuff->transfer(target->ibuff);
}
/* flush output buffer out our own fd */
int flushO(int size = 0)
{
#ifdef _USE_SSL
if (ssl)
return obuff->flush(ssl, size);
#endif
return obuff->flush(this->fd, size);
}
/* clear input buffer */
void clear()
{
ibuff->reset();
}
void clearO()
{
obuff->reset();
}
};
enum {
SOCK_ERR_READ = DYNBUFF_ERR_READ,
SOCK_ERR_WRITE = DYNBUFF_ERR_WRITE,
SOCK_ERR_MEM = DYNBUFF_ERR_MEM,
SOCK_ERR_FULL = DYNBUFF_ERR_FULL
};
#endif
syntax highlighted by Code2HTML, v. 0.9.1