diff options
Diffstat (limited to 'src/libmowgli/vio/vio.h')
-rw-r--r-- | src/libmowgli/vio/vio.h | 283 |
1 files changed, 197 insertions, 86 deletions
diff --git a/src/libmowgli/vio/vio.h b/src/libmowgli/vio/vio.h index 37b5c37..aafab2a 100644 --- a/src/libmowgli/vio/vio.h +++ b/src/libmowgli/vio/vio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Elizabeth J. Myers. All rights reserved. + * Copyright (c) 2012 Elizabeth J. Myers. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,19 +22,25 @@ /* Types and structs */ typedef struct _mowgli_vio mowgli_vio_t; -typedef enum { - MOWGLI_VIO_ERR_NONE, - MOWGLI_VIO_ERR_REMOTE_HANGUP, - MOWGLI_VIO_ERR_ERRCODE, - MOWGLI_VIO_ERR_API, - MOWGLI_VIO_ERR_CUSTOM, +/* Error type */ +typedef enum +{ + MOWGLI_VIO_ERR_NONE = 0,/* Wat, no error. */ + MOWGLI_VIO_ERR_REMOTE_HANGUP, /* Remote end hung up on us, how rude */ + MOWGLI_VIO_ERR_ERRCODE, /* An errno error or something like that */ + MOWGLI_VIO_ERR_API, /* Programmer was a dumbass */ + MOWGLI_VIO_ERR_CUSTOM, /* Use this for custom errors */ } mowgli_vio_error_type_t; -typedef enum { - MOWGLI_VIO_ERR_OP_NONE, +/* Errors with specific functions correspondng to the VIO op it's named + * after */ +typedef enum +{ + MOWGLI_VIO_ERR_OP_NONE = 0, /* Wat. */ MOWGLI_VIO_ERR_OP_SOCKET, MOWGLI_VIO_ERR_OP_LISTEN, MOWGLI_VIO_ERR_OP_ACCEPT, + MOWGLI_VIO_ERR_OP_REUSEADDR, MOWGLI_VIO_ERR_OP_CONNECT, MOWGLI_VIO_ERR_OP_READ, MOWGLI_VIO_ERR_OP_WRITE, @@ -44,41 +50,59 @@ typedef enum { MOWGLI_VIO_ERR_OP_OTHER, } mowgli_vio_error_op_t; -typedef struct _mowgli_vio_error { +typedef struct _mowgli_vio_error +{ mowgli_vio_error_op_t op; mowgli_vio_error_type_t type; - int code; - char string[128]; + unsigned long code; /* Unsigned long for OpenSSL fuckery */ + char string[128]; /* Friendly name for error */ } mowgli_vio_error_t; -typedef struct _mowgli_vio_sockaddr { +/* Custom sockaddr member to have a uniform sockaddr as opposed to the + * bullshit in the Berkeley sockets API with struct sockaddr/struct + * sockaddr_storage/struct sockaddr_in/struct sockaddr_in6 and associated + * API inconsistency and braindamage + */ +typedef struct _mowgli_vio_sockaddr +{ struct sockaddr_storage addr; + socklen_t addrlen; } mowgli_vio_sockaddr_t; -typedef struct _mowgli_vio_sockdata { - char host[39]; /* max length of IPv6 address */ +#ifndef INET6_ADDRSTRLEN +# define INET6_ADDRSTRLEN 46 /* Good enough I tell you */ +#endif + +/* Socket data */ +typedef struct _mowgli_vio_sockdata +{ + char host[INET6_ADDRSTRLEN]; /* max length of IPv6 address */ uint16_t port; } mowgli_vio_sockdata_t; -typedef int mowgli_vio_func_t(mowgli_vio_t *); -typedef int mowgli_vio_bind_connect_func_t(mowgli_vio_t *, mowgli_vio_sockaddr_t *); -typedef int mowgli_vio_read_func_t(mowgli_vio_t *, void *, size_t); -typedef int mowgli_vio_write_func_t(mowgli_vio_t *, const void *, size_t); -typedef int mowgli_vio_sendto_func_t(mowgli_vio_t *, const void *, size_t, mowgli_vio_sockaddr_t *); -typedef int mowgli_vio_recvfrom_func_t(mowgli_vio_t *, void *, size_t, mowgli_vio_sockaddr_t *); -typedef int mowgli_vio_connect_func_t(mowgli_vio_t *); -typedef int mowgli_vio_accept_func_t(mowgli_vio_t *, mowgli_vio_t *); -typedef int mowgli_vio_listen_func_t(mowgli_vio_t *, int); -typedef int mowgli_vio_socket_func_t(mowgli_vio_t *, int, int, int); -typedef int mowgli_vio_seek_func_t(mowgli_vio_t *, long, int); - -typedef struct { +/* Various typedefs bleh */ +typedef int mowgli_vio_func_t (mowgli_vio_t *); +typedef int mowgli_vio_bind_connect_func_t (mowgli_vio_t *, mowgli_vio_sockaddr_t *); +typedef int mowgli_vio_read_func_t (mowgli_vio_t *, void *, size_t); +typedef int mowgli_vio_write_func_t (mowgli_vio_t *, const void *, size_t); +typedef int mowgli_vio_sendto_func_t (mowgli_vio_t *, const void *, size_t, mowgli_vio_sockaddr_t *); +typedef int mowgli_vio_recvfrom_func_t (mowgli_vio_t *, void *, size_t, mowgli_vio_sockaddr_t *); +typedef int mowgli_vio_connect_func_t (mowgli_vio_t *); +typedef int mowgli_vio_accept_func_t (mowgli_vio_t *, mowgli_vio_t *); +typedef int mowgli_vio_listen_func_t (mowgli_vio_t *, int); +typedef int mowgli_vio_socket_func_t (mowgli_vio_t *, int, int, int); +typedef int mowgli_vio_seek_func_t (mowgli_vio_t *, long, int); + +/* These are workalikes vis-a-vis the Berkeley sockets API */ +typedef struct +{ mowgli_vio_socket_func_t *socket; mowgli_vio_bind_connect_func_t *bind; mowgli_vio_bind_connect_func_t *connect; mowgli_vio_listen_func_t *listen; mowgli_vio_accept_func_t *accept; + mowgli_vio_func_t *reuseaddr; mowgli_vio_read_func_t *read; mowgli_vio_write_func_t *write; mowgli_vio_sendto_func_t *sendto; @@ -89,61 +113,89 @@ typedef struct { mowgli_vio_func_t *tell; } mowgli_vio_ops_t; -struct _mowgli_vio { - mowgli_vio_ops_t ops; - - mowgli_eventloop_io_t *io; - mowgli_descriptor_t fd; +/* Callbacks for eventloop stuff */ +typedef struct +{ + mowgli_eventloop_io_cb_t *read_cb; + mowgli_eventloop_io_cb_t *write_cb; +} mowgli_vio_evops_t; +struct _mowgli_vio +{ + mowgli_vio_ops_t *ops; /* VIO operations */ + mowgli_vio_evops_t *evops; /* Eventloop operations */ + + /* eventloop IO object or descriptor + * If the eventloop member is non-null use io + * else use fd + */ + union + { + mowgli_eventloop_io_t *e; + mowgli_descriptor_t fd; + } io; + + /* Eventloop object we're attached to */ mowgli_eventloop_t *eventloop; + /* struct sockaddr portable workalike -- usage is + * context specific. + * + * For accept()'ed VIO objects, this is the client's + * struct sockaddr stuff, for connect()'ed objects it + * is the remote end's sockaddr (even with previous call + * to bind, for bind()'ed objects it is the sockaddr passed + * to bind + */ mowgli_vio_sockaddr_t addr; - mowgli_vio_error_t error; + mowgli_vio_error_t error; /* Error information lives here */ - int flags; + unsigned int flags; /* Connection flags */ - void *userdata; - void *privdata; + void *userdata; /* User data for VIO object */ + void *privdata; /* Private data for stuff like SSL */ }; -typedef struct _mowgli_vio_ssl_settings { - char cert_path[FILENAME_MAX]; - char privatekey_path[FILENAME_MAX]; +/* SSL settings... members subject to change */ +typedef struct _mowgli_vio_ssl_settings +{ + const char *cert_path; + const char *privatekey_path; int ssl_version; int (*password_func)(char *, int, int, void *); int (*verify_func)(int, void *); } mowgli_vio_ssl_settings_t; - /* Flags */ -#define MOWGLI_VIO_FLAGS_ISCONNECTING 0x00001 -#define MOWGLI_VIO_FLAGS_ISSSLCONNECTING 0x00002 -#define MOWGLI_VIO_FLAGS_ISCLOSED 0x00004 +#define MOWGLI_VIO_FLAGS_ISCONNECTING 0x00001 +#define MOWGLI_VIO_FLAGS_ISSSLCONNECTING 0x00002 +#define MOWGLI_VIO_FLAGS_ISCLOSED 0x00004 -#define MOWGLI_VIO_FLAGS_ISCLIENT 0x00008 -#define MOWGLI_VIO_FLAGS_ISSERVER 0x00010 +#define MOWGLI_VIO_FLAGS_ISCLIENT 0x00008 +#define MOWGLI_VIO_FLAGS_ISSERVER 0x00010 -#define MOWGLI_VIO_FLAGS_ISONHEAP 0x00020 +#define MOWGLI_VIO_FLAGS_ISONHEAP 0x00020 -#define MOWGLI_VIO_FLAGS_NEEDREAD 0x00040 -#define MOWGLI_VIO_FLAGS_NEEDWRITE 0x00080 +#define MOWGLI_VIO_FLAGS_NEEDREAD 0x00040 +#define MOWGLI_VIO_FLAGS_NEEDWRITE 0x00080 /* SSL flags */ -#define MOWGLI_VIO_SSLFLAGS_SSLV2 0x00001 -#define MOWGLI_VIO_SSLFLAGS_SSLV3 0x00002 -#define MOWGLI_VIO_SSLFLAGS_TLSV10 0x00004 -#define MOWGLI_VIO_SSLFLAGS_TLSV11 0x00008 -#define MOWGLI_VIO_SSLFLAGS_TLSV12 0x00010 - +#define MOWGLI_VIO_SSLFLAGS_SSLV2 0x00001 +#define MOWGLI_VIO_SSLFLAGS_SSLV3 0x00002 +#define MOWGLI_VIO_SSLFLAGS_TLSV10 0x00004 +#define MOWGLI_VIO_SSLFLAGS_TLSV11 0x00008 +#define MOWGLI_VIO_SSLFLAGS_TLSV12 0x00010 /* Flag setting/getting */ -static inline bool mowgli_vio_hasflag(mowgli_vio_t *vio, int flag) +static inline bool +mowgli_vio_hasflag(mowgli_vio_t *vio, int flag) { return (vio->flags & flag) != 0 ? true : false; } -static inline void mowgli_vio_setflag(mowgli_vio_t *vio, int flag, bool setting) +static inline void +mowgli_vio_setflag(mowgli_vio_t *vio, int flag, bool setting) { if (setting) vio->flags |= flag; @@ -151,32 +203,68 @@ static inline void mowgli_vio_setflag(mowgli_vio_t *vio, int flag, bool setting) vio->flags &= ~flag; } +/* Get file descriptor */ +static inline mowgli_descriptor_t +mowgli_vio_getfd(mowgli_vio_t *vio) +{ + return_val_if_fail(vio, -1); + + if (vio->eventloop) + { + mowgli_eventloop_pollable_t *pollable = mowgli_eventloop_io_pollable(vio->io.e); + + if (pollable) + return pollable->fd; + } + + return vio->io.fd; +} /* Macros */ -#define MOWGLI_VIO_SET_CLOSED(v) \ - mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_ISCONNECTING, false); \ - mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_ISCLOSED, true); \ +#define MOWGLI_VIO_SET_CLOSED(v) \ + mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_ISCONNECTING, false); \ + mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_ISCLOSED, true); \ mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_ISSSLCONNECTING, false); \ - mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_NEEDREAD, false); \ - mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_NEEDWRITE, false); + mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_NEEDREAD, false); \ + mowgli_vio_setflag(v, MOWGLI_VIO_FLAGS_NEEDWRITE, false) +#define MOWGLI_VIO_IS_CLOSED(v) mowgli_vio_hasflag(v, MOWGLI_VIO_FLAGS_ISCLOSED) + +#define MOWGLI_VIO_SETREAD(vio) \ + if (vio->eventloop && vio->io.e && vio->evops && vio->evops->read_cb) \ + { \ + mowgli_pollable_setselect(vio->eventloop, vio->io.e, MOWGLI_EVENTLOOP_IO_READ, vio->evops->read_cb); \ + } + +#define MOWGLI_VIO_SETWRITE(vio) \ + if (vio->eventloop && vio->io.e && vio->evops && vio->evops->write_cb) \ + { \ + mowgli_pollable_setselect(vio->eventloop, vio->io.e, MOWGLI_EVENTLOOP_IO_WRITE, vio->evops->write_cb); \ + } + +#define MOWGLI_VIO_UNSETWRITE(vio) \ + if (vio->eventloop && vio->io.e) \ + { \ + mowgli_pollable_setselect(vio->eventloop, vio->io.e, MOWGLI_EVENTLOOP_IO_WRITE, NULL); \ + } /* Decls */ -extern mowgli_vio_t * mowgli_vio_create(void *userdata); +extern mowgli_vio_t *mowgli_vio_create(void *userdata); extern void mowgli_vio_init(mowgli_vio_t *vio, void *userdata); extern void mowgli_vio_destroy(mowgli_vio_t *vio); -extern void mowgli_vio_eventloop_attach(mowgli_vio_t *vio, mowgli_eventloop_t *eventloop); +extern void mowgli_vio_eventloop_attach(mowgli_vio_t *vio, mowgli_eventloop_t *eventloop, mowgli_vio_evops_t *evops); extern void mowgli_vio_eventloop_detach(mowgli_vio_t *vio); -extern mowgli_vio_sockaddr_t * mowgli_vio_sockaddr_create(mowgli_vio_sockaddr_t *naddr, int proto, const char *addr, int port); -extern mowgli_vio_sockaddr_t * mowgli_vio_sockaddr_from_struct(mowgli_vio_sockaddr_t *naddr, const void *addr, socklen_t size); +extern mowgli_vio_sockaddr_t *mowgli_vio_sockaddr_create(mowgli_vio_sockaddr_t *naddr, int proto, const char *addr, int port); +extern mowgli_vio_sockaddr_t *mowgli_vio_sockaddr_from_struct(mowgli_vio_sockaddr_t *naddr, const void *addr, socklen_t size); extern int mowgli_vio_sockaddr_info(const mowgli_vio_sockaddr_t *addr, mowgli_vio_sockdata_t *data); extern int mowgli_vio_default_socket(mowgli_vio_t *vio, int family, int type, int proto); extern int mowgli_vio_default_bind(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *addr); extern int mowgli_vio_default_listen(mowgli_vio_t *vio, int backlog); extern int mowgli_vio_default_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio); +extern int mowgli_vio_default_reuseaddr(mowgli_vio_t *vio); extern int mowgli_vio_default_connect(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *addr); extern int mowgli_vio_default_read(mowgli_vio_t *vio, void *buffer, size_t len); extern int mowgli_vio_default_write(mowgli_vio_t *vio, const void *buffer, size_t len); @@ -188,32 +276,55 @@ extern int mowgli_vio_default_seek(mowgli_vio_t *vio, long offset, int whence); extern int mowgli_vio_default_tell(mowgli_vio_t *vio); extern int mowgli_vio_err_errcode(mowgli_vio_t *vio, char *(*int_to_error)(int), int errcode); -extern int mowgli_vio_err_sslerrcode(mowgli_vio_t *vio, int errcode); +extern int mowgli_vio_err_sslerrcode(mowgli_vio_t *vio, unsigned long int errcode); + +extern int mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *settings, mowgli_vio_ops_t *ops); -extern int mowgli_vio_openssl_setssl(mowgli_vio_t *vio, mowgli_vio_ssl_settings_t *settings); /* These are void ptr's so they can be null ops if SSL isn't available */ -extern void * mowgli_vio_openssl_getsslhandle(mowgli_vio_t *vio); -extern void * mowgli_vio_openssl_getsslcontext(mowgli_vio_t *vio); +extern void *mowgli_vio_openssl_getsslhandle(mowgli_vio_t *vio); +extern void *mowgli_vio_openssl_getsslcontext(mowgli_vio_t *vio); + +#ifdef HAVE_OPENSSL +extern int mowgli_vio_openssl_default_connect(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *addr); +extern int mowgli_vio_openssl_default_listen(mowgli_vio_t *vio, int backlog); +extern int mowgli_vio_openssl_default_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio); +extern int mowgli_vio_openssl_default_read(mowgli_vio_t *vio, void *buffer, size_t len); +extern int mowgli_vio_openssl_default_write(mowgli_vio_t *vio, const void *buffer, size_t len); +extern int mowgli_vio_openssl_default_close(mowgli_vio_t *vio); + +#else +# define NOSSLSUPPORT { mowgli_log("Attempting to use default OpenSSL op with no SSL support; this will not work!"); return -255; } +static inline int mowgli_vio_openssl_default_connect(mowgli_vio_t *vio, mowgli_vio_sockaddr_t *addr) NOSSLSUPPORT +static inline int mowgli_vio_openssl_default_listen(mowgli_vio_t *vio, int backlog) NOSSLSUPPORT +static inline int mowgli_vio_openssl_default_accept(mowgli_vio_t *vio, mowgli_vio_t *newvio) NOSSLSUPPORT +static inline int mowgli_vio_openssl_default_read(mowgli_vio_t *vio, void *buffer, size_t len) NOSSLSUPPORT +static inline int mowgli_vio_openssl_default_write(mowgli_vio_t *vio, const void *buffer, size_t len) NOSSLSUPPORT +static inline int mowgli_vio_openssl_default_close(mowgli_vio_t *vio) NOSSLSUPPORT +#endif +/* Default ops -- change these if you want something besides the default */ extern mowgli_vio_ops_t mowgli_vio_default_ops; +/* Default evops -- they do nothing unless you change them */ +extern mowgli_vio_evops_t mowgli_vio_default_evops; /* Sundry operations on vio functables */ -#define mowgli_vio_set_op(vio, op, func) vio->ops.op = func; - -#define mowgli_vio_socket(vio, ...) vio->ops.socket(vio, __VA_ARGS__) -#define mowgli_vio_listen(vio, ...) vio->ops.listen(vio, __VA_ARGS__) -#define mowgli_vio_bind(vio, ...) vio->ops.bind(vio, __VA_ARGS__) -#define mowgli_vio_accept(vio, ...) vio->ops.accept(vio, __VA_ARGS__) -#define mowgli_vio_connect(vio, ...) vio->ops.connect(vio, __VA_ARGS__) -#define mowgli_vio_read(vio, ...) vio->ops.read(vio, __VA_ARGS__) -#define mowgli_vio_write(vio, ...) vio->ops.write(vio, __VA_ARGS__) -#define mowgli_vio_sendto(vio, ...) vio->ops.sendto(vio, __VA_ARGS__) -#define mowgli_vio_recvfrom(vio, ...) vio->ops.recvfrom(vio, __VA_ARGS__) -#define mowgli_vio_error(vio) vio->ops.error(vio); -#define mowgli_vio_close(vio) vio->ops.close(vio); -#define mowgli_vio_seek(vio, ...) vio->ops.seek(vio, __VA_ARGS__) -#define mowgli_vio_tell(vio) vio->ops.tell(vio) +#define mowgli_vio_ops_set_op(ops, op, func) ops->op = func + +/* Wrappers for the VIO ops */ +#define mowgli_vio_socket(vio, ...) vio->ops->socket(vio, __VA_ARGS__) +#define mowgli_vio_listen(vio, ...) vio->ops->listen(vio, __VA_ARGS__) +#define mowgli_vio_bind(vio, ...) vio->ops->bind(vio, __VA_ARGS__) +#define mowgli_vio_accept(vio, ...) vio->ops->accept(vio, __VA_ARGS__) +#define mowgli_vio_reuseaddr(vio) vio->ops->reuseaddr(vio) +#define mowgli_vio_connect(vio, ...) vio->ops->connect(vio, __VA_ARGS__) +#define mowgli_vio_read(vio, ...) vio->ops->read(vio, __VA_ARGS__) +#define mowgli_vio_write(vio, ...) vio->ops->write(vio, __VA_ARGS__) +#define mowgli_vio_sendto(vio, ...) vio->ops->sendto(vio, __VA_ARGS__) +#define mowgli_vio_recvfrom(vio, ...) vio->ops->recvfrom(vio, __VA_ARGS__) +#define mowgli_vio_error(vio) vio->ops->error(vio) +#define mowgli_vio_close(vio) vio->ops->close(vio) +#define mowgli_vio_seek(vio, ...) vio->ops->seek(vio, __VA_ARGS__) +#define mowgli_vio_tell(vio) vio->ops->tell(vio) #endif - |