#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <glib.h>
#include "entity.h"
/* The way an raw-io tag can look in the xml. * <raw-io * name="thisio" *
* fd="1" * oncanread="get_part" * oncanwrite="can_write" *
* onerror="got_messed" * /> */
static void
rendio_raw_io_do (ENode * node, int source, char *function)
{
enode_call_ignore_return (node, function, "");
}
static int
rendio_raw_io_ready_callback (gint source, EIOCond cond, ENode * node)
{
gchar *oncanread;
gchar *oncanwrite;
gchar *onerror;
EDEBUG (
("raw-io-renderer", "in rendio_raw_io_ready_callback, cond = %i",
cond));
if (cond & EIO_READ) {
oncanread = enode_attrib_str (node, "oncanread", NULL);
rendio_raw_io_do (node, source, oncanread);
}
if (cond & EIO_WRITE) {
oncanwrite = enode_attrib_str (node, "oncanwrite", NULL);
rendio_raw_io_do (node, source, oncanwrite);
}
if (cond & EIO_ERROR) {
onerror = enode_attrib_str (node, "onerror", NULL);
rendio_raw_io_do (node, source, onerror);
}
return FALSE;
}
static EIOCond
rendio_raw_io_get_condition (ENode * node)
{
EIOCond cond = EIO_READ;
char *oncanread;
char *oncanwrite;
char *onerror;
oncanread = enode_attrib_str (node, "oncanread", NULL);
oncanwrite = enode_attrib_str (node, "oncanwrite", NULL);
onerror = enode_attrib_str (node, "onerror", NULL);
if (oncanread && strlen (oncanread)) {
cond |= EIO_READ;
}
if (oncanwrite && strlen (oncanwrite)) {
cond |= EIO_WRITE;
}
if (onerror && strlen (onerror)) {
cond |= EIO_READ;
}
EDEBUG (("raw-io-renderer", "cond = %i, read = %i", cond, EIO_READ));
return cond;
}
static int
rendio_raw_io_fd_attr_set (ENode * node, EBuf * attr, EBuf * value)
{
EIOCond cond;
int source;
gpointer tag;
gpointer old_tag;
old_tag = enode_get_kv (node, "rendio-raw-io-tag");
source = erend_get_integer (value);
if (source < 0) {
/* need to delete the old tag and callback connection. */
EDEBUG (("raw-io-renderer", "going to delete old tag"));
if (old_tag) {
entity_mainloop->io_remove (old_tag);
}
return TRUE; /* Source of <0 means disconnect completely. */
}
if (old_tag) {
/* need to delete the old tag and callback connection. */
entity_mainloop->io_remove (old_tag);
}
cond = rendio_raw_io_get_condition (node);
/* No blocking io is alowed... */
fcntl (source, F_SETFL, O_NONBLOCK);
EDEBUG (("raw-io-renderer", "source = %i, cond = %i", source, cond));
tag = entity_mainloop->io_add (source, cond,
(void *) rendio_raw_io_ready_callback, node);
enode_set_kv (node, "rendio-raw-io-tag", tag);
return TRUE;
}
static void
rendio_raw_io_render (ENode * node)
{
enode_attribs_sync (node);
enode_set_kv (node, "rendio-raw-io-tag", NULL);
}
static void
rendio_raw_io_destroy (ENode * node)
{
gpointer tag;
tag = enode_get_kv (node, "rendio-raw-io-tag");
if (tag)
entity_mainloop->io_remove (tag);
}
static void
rendio_raw_io_parent (ENode * parent_node, ENode * child_node)
{
/* Short curcuit the node so that you can stick the timer node anywhere */
parent_node->entity_data = child_node->entity_data;
}
void
raw_io_renderer_register (void)
{
Element *element;
ElementAttr *e_attr;
element = g_new0 (Element, 1);
element->render_func = rendio_raw_io_render;
element->destroy_func = rendio_raw_io_destroy;
element->parent_func = rendio_raw_io_parent;
element->tag = "raw-io";
element->description =
"Event driven IO watcher. Feed it a file descriptor, and it'll call you when data arrives, or is ready to be sent.";
element_register (element);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "fd";
e_attr->description = "Sepcify the file descripter to watch";
e_attr->value_desc = "integer";
e_attr->possible_values = "-1,*";
e_attr->set_attr_func = rendio_raw_io_fd_attr_set;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "oncanread";
e_attr->description = "Function to call when the fd is ready for reading.";
e_attr->value_desc = "function";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "oncanwrite";
e_attr->description = "Function to call when the fd is ready for writing.";
e_attr->value_desc = "function";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "onerror";
e_attr->description =
"Function to call when an exception occurs on the fd.";
e_attr->value_desc = "function";
e_attr->set_attr_func = NULL;
element_register_attrib (element, e_attr);
}
syntax highlighted by Code2HTML, v. 0.9.1