#ifndef __CSINK_H__
#define __CSINK_H__
/* csink.h
* Author(s): Jim Meier, Cory Stone
*/
/* Headers */
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <glib.h>
#include <errno.h>
#include "cbuf.h"
#include "csinkerr.h"
/* Toplevel code should only check the ->flags member. Only implementaions
* that own the csink are alowed to modify that ->flags member. This
* will make it so the user code doesn't have to know what kind of csink
* it is using.
*
*/
/* The type value for a base csink. */
#define CSINK_TYPE 0xdeadbeef
/* This is not part of glib but it should be. */
void g_ptr_array_add_at_start(GPtrArray *array, gpointer data);
#ifdef ENTITY_EMBED
#include "entity.h"
#define CDEBUG(x) edebug x
#else /* not ENTITY_EMBED */
/* #include <cdebug.h> */
#include "edebug.h"
#define CDEBUG(x) edebug x
/* Typedefs for mainloop registration. */
typedef enum /* This looks exactly the same as entity's eio's. */
{
EIO_READ = 1 << 0,
EIO_WRITE = 1 << 1,
EIO_ERROR = 1 << 2
} EIOCond;
typedef int (*EIOFunc) (int fd, EIOCond cond, void *data);
typedef void *(*EIOAddFunc) (int fd, EIOCond cond, EIOFunc, void *data);
typedef void (*EIORemoveFunc) (void *tag);
#endif /* ENTITY_EMBED */
typedef enum
{
CSSF_CLOSED = (0),
CSSF_TRYING = (1 << 0),
CSSF_SHOULD_READ = (1 << 1), /* Not yet, used... */
CSSF_CAN_WRITE = (1 << 2),
} CSStatusFlags;
/* Casting macros */
#define CSINK(sink) ( (CSink*)sink )
typedef struct _CSink CSink;
/* Callback types */
typedef void (*CSinkFreeFunc) (CSink * sink);
typedef void (*CSinkCloseFunc) (CSink * sink);
typedef CBuf *(*CSinkReadFunc) (CSink * sink);
typedef CSink *(*CSinkCreateFunc) (CSink * old_sink);
typedef gint (*CSinkWriteFunc) (CSink * sink, CBuf * data);
typedef void (*CSinkOpenFunc) (CSink * sink);
typedef void (*CSinkCallbackFunc) (CSink * sink); /* Generic callback. */
struct _CSink {
int csink_type; /* The type of csink. */
CSStatusFlags flags; /* Top level flags. */
/* In and out queues both buffer messages up to available memory. */
GPtrArray *inQueue; /* Incoming messages, in order. */
GPtrArray *outQueue; /* Unsent outgoing messages, in order. */
int closed; /* open/closed flag. */
int err; /* Error flag. Should become status flag. */
CSink_Error *error_record; /* The current error. */
/* Some basic method pointers. */
CSinkReadFunc read;
CSinkWriteFunc write;
CSinkOpenFunc open;
CSinkCloseFunc close;
CSinkFreeFunc free;
CSinkCreateFunc create;
CSinkCallbackFunc on_error; /* Error signalled. */
CSinkCallbackFunc on_new_data; /* New data available. */
CSinkCallbackFunc on_close; /* Sink connection closed. */
CSinkCallbackFunc on_connect; /* Sink connection is active. */
CSinkCallbackFunc on_empty_send_queue; /* I don't think this is needed. */
gpointer user_data; /* Associated user data.
* Not managed or freed by csink. */
/* The object system implies delegation. These
* two fields provide that structure. */
CSink *child; /* Pointer to the wrapped sink. */
CSink *parent; /* Pointer to the wrapping sink. */
};
/*===============================*/
/* Functions to get and set the user data. */
void *csink_get_user_data (CSink * sink);
void csink_set_user_data (CSink * sink, void *data);
/* Functions to modify the callbacks. */
void csink_set_new_data_func (CSink * sink, CSinkCallbackFunc func);
void csink_set_empty_send_queue_func (CSink * sink, CSinkCallbackFunc func);
void csink_set_error_func (CSink * sink, CSinkCallbackFunc func);
void csink_set_close_func (CSink * sink, CSinkCallbackFunc func);
void csink_set_connect_func (CSink * sink, CSinkCallbackFunc func);
/* Error handling funcs. */
gchar *csink_errstr (CSink * sink);
gint csink_error (CSink * sink);
gchar *csink_errname(CSink *sink);
gchar *csink_errormsg (CSink * sink); /* unimplemented */
/* Initialize and unregister funcs. */
void csink_init (CSink *sink);
void csink_release (CSink *sink);
/* Basic interaction methods. */
void csink_open (CSink * sink); /* Tries to open a connection. */
CBuf *csink_read (CSink * sink); /* Read from the sink,
* NULL if no message */
gint csink_write (CSink * sink, CBuf * data); /* Write data to the out queue. */
void csink_close (CSink * sink); /* Close the connection. */
void csink_free (CSink * sink); /* Free all data associated
* with the sink */
CSink * csink_create (CSink * sink); /* The allocate function. */
/* Information about the buffers. */
gint csink_send_queue_size (CSink * sink); /* in bytes */
gint csink_receive_queue_size (CSink * sink); /* in bytes */
/* Call the associated callbacks and do standard associated actions */
void csink_on_connect (CSink * sink);
void csink_on_new_data (CSink * sink);
/* Set error before calling the on_error func. */
#define csink_on_error(sink, errname) \
csink_on_error__P (sink, errname, __FILE__, __LINE__)
void csink_on_error__P (CSink * sink, char *errname,
char *file, int line);
/*===============================================*/
/* FD Watching interface */
/* CSinks will use whatever functions the user wants to watch activity on
* fds. Also, a simple polling implementaiton is provided. */
typedef EIOCond CSinkFDCondition;
typedef EIOFunc CSinkFDCallbackFunc;
typedef void *(*CSinkAddFDFunc) (int fd, CSinkFDCondition cond,
CSinkFDCallbackFunc func, CSink * sink, char * info);
typedef void (*CSinkRemoveFDFunc) (void *tag, char *info);
void csink_init_funcs (CSinkAddFDFunc fd_add_func,
CSinkRemoveFDFunc fd_remove_func);
void *csink_add_fd (int fd, CSinkFDCondition cond, CSinkCallbackFunc func,
CSink * sink, char * info);
void csink_remove_fd (void * tag, char * info);
/* The polling implementation. Use csink_set_polling_fd_funcs to set it up,
* then call csink_do_poll somewhere in your main loop. */
void csink_set_polling_fd_funcs (void);
void csink_do_poll (void);
/* Add to the queue. */
gint csink_default_write (CSink *sink, CBuf *msg);
/* Sanity checker for write. */
gint csink_write_sanity (CSink * sink, CBuf * message);
#endif
syntax highlighted by Code2HTML, v. 0.9.1