#ifndef __CSINK_H__ #define __CSINK_H__ /* csink.h * Author(s): Jim Meier, Cory Stone */ /* Headers */ #include #include #include #include #include #include #include #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 */ #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