diff options
| author | Lennart Poettering <lennart@poettering.net> | 2004-05-09 23:20:43 +0000 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2004-05-09 23:20:43 +0000 | 
| commit | 63d51b566ea270b45b5b34b1feab37b8faa28232 (patch) | |
| tree | 42b190637551ceae31982f2591bec64c7b0b370a /client/daemon.c | |
| parent | ad9b08e8c6fb69636812a625e341ebbe83460a23 (diff) | |
main fieryfilter worktrunk@31
git-svn-id: file:///home/lennart/svn/public/fieryfilter/fieryfilter@31 79e6afc9-17da-0310-ae3c-b873bff394f4
Diffstat (limited to 'client/daemon.c')
| -rw-r--r-- | client/daemon.c | 198 | 
1 files changed, 198 insertions, 0 deletions
diff --git a/client/daemon.c b/client/daemon.c new file mode 100644 index 0000000..fd69ef5 --- /dev/null +++ b/client/daemon.c @@ -0,0 +1,198 @@ +#include <sys/socket.h> +#include <sys/un.h> +#include <stdio.h> +#include <gtk/gtk.h> + +#include "daemon.h" +#include "../daemon/common.h" +#include "connection.h" + +int sock = -1; +GIOChannel *channel = NULL; +GSList *send_message_queue = NULL; + +static void dispatch(message_t *m) { +    switch (m->code) { +        case MSG_PACKET : +            conn_new((ipq_packet_msg_t*) (m+1)); +            break; +        default: +            break; +    } +    g_free(m); +} + +static gboolean recv_work() { +    static guint8 temp[sizeof(message_t)]; +    static message_t *m = NULL; +    static guint index = 0; + +    guint8 *p; +    size_t l; +    ssize_t r; + +    if (index < sizeof(message_t)) { +        p = temp + index; +        l = sizeof(message_t); +    } else { +        p = ((guint8*) m) + index; +        l = m->length+sizeof(message_t); +    } + +    if ((r = read(sock, p, l-index)) < 0) { +        g_message("read() failed, exiting."); +        gtk_main_quit(); +        return FALSE; +    } + +    index += r; + +    if (index == sizeof(message_t)) { +        m = g_malloc(((message_t*) temp)->length + sizeof(message_t)); +        memcpy(m, temp, sizeof(message_t)); +    } + +    if (index >= sizeof(message_t)) +        if (index == sizeof(message_t) + m->length) { +            dispatch(m); +            m = NULL; +            index = 0; +        } + +    return TRUE; +} + +static gboolean send_work() { +    static message_t *m = NULL; +    static int index = 0; +    guint l, r; +    guint8* p; + +    if (!m) { +        if (!send_message_queue) +            return FALSE; +         +        m = (message_t*) send_message_queue->data; +        send_message_queue = g_slist_remove(send_message_queue, m); +         +        index = 0; +    } + +    p = ((guint8*) m) + index; +    l = m->length + sizeof(message_t); + +    if ((r = write(sock, p, l - index)) < 0) { +        g_message("write() failed, exiting"); +        gtk_main_quit(); +        return FALSE; +    } + +    index += r; + + +    if (index >= l) { +        g_free(m); +        m = NULL; +        index = 0; +    } + + +    return m || send_message_queue; +} + + +static gboolean callback(GIOChannel *source, GIOCondition condition, gpointer data) { +     +    if (condition & G_IO_HUP) { +        gtk_main_quit(); +        return FALSE; +    } +     +    if (condition & G_IO_IN) +        return recv_work(); + +    if (condition & G_IO_OUT) +        return send_work(); + +    g_error("Huch?"); +    return FALSE; +} + +static int enqueue_message(message_t *m) { + +    send_message_queue = g_slist_append(send_message_queue, m); + +    if (!send_message_queue->next) +        g_io_add_watch(channel, G_IO_OUT, callback, NULL);     + +    return 0; +} + +static message_t* new_message(message_code_t code, guint8* p, guint s) { +    message_t* m; + +    if (!p) +        s = 0; +     +    m = g_malloc(sizeof(message_t) + s); + +    m->code = code; +    m->pid = getpid(); +    m->length = s; + +    if (p) +        memcpy(m+1, p, s); +     +    return m; +} + +static int unix_socket(gchar *p) { +    struct sockaddr_un addr; +    int sock; +                                                                                                                                                 +    if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { +        perror("socket(PF_LOCAL, SOCK_STREAM, 0)"); +        return -1; +    } + +    addr.sun_family = AF_LOCAL; +    strncpy(addr.sun_path, p, sizeof(addr.sun_path)); +    addr.sun_path[sizeof(addr.sun_path)-1] = 0; + +    if (connect(sock, (struct sockaddr *) &addr, SUN_LEN(&addr)) < 0) { +        perror("connect()"); +        return -1; +    } + +    return sock; +} + +int daemon_init() { + +    if ((sock = unix_socket(SOCKET_PATH)) < 0) +        return -1; + +    channel = g_io_channel_unix_new(sock); +    g_io_add_watch(channel, G_IO_IN|G_IO_HUP, callback, NULL); +     +    return 0; +} + + +void daemon_done() { +    if (sock >= 0) +        close(sock); + +    if (channel) +        g_io_channel_unref(channel); +} + + +void daemon_verdict(unsigned long id, guint r) { +    static guint8 buf[sizeof(unsigned long) + sizeof(guint32)]; + +    *((unsigned long*) &buf[0]) = id; +    *((guint32*) &buf[sizeof(unsigned long)]) = r; + +    enqueue_message(new_message(MSG_VERDICT, buf, sizeof(buf))); +}  | 
