~ubuntu-branches/ubuntu/jaunty/imms/jaunty

« back to all changes in this revision

Viewing changes to immscore/giosocket.h

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Veber
  • Date: 2005-04-13 23:43:11 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050413234311-kzr68z9l7z5mv551
Tags: 2.0.3-2
Build depend on xmms-dev (>= 1.2.10+cvs20050209)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef __GIOSOCKET_H
 
2
#define __GIOSOCKET_H
 
3
 
 
4
#include <glib.h>
 
5
 
 
6
#include <string>
 
7
#include <list>
 
8
#include <iostream>
 
9
#include <unistd.h>
 
10
#include <fcntl.h>
 
11
#include <assert.h>
 
12
 
 
13
#include "immsconf.h"
 
14
 
 
15
using std::string;
 
16
 
 
17
class GIOSocket
 
18
{
 
19
public:
 
20
    GIOSocket() : con(0), read_tag(0), write_tag(0), outp(0) {}
 
21
    virtual ~GIOSocket() { close(); }
 
22
 
 
23
    bool isok() { return con; }
 
24
 
 
25
    void init(int fd)
 
26
    {
 
27
        fcntl(fd, F_SETFD, O_NONBLOCK);
 
28
 
 
29
        con = g_io_channel_unix_new(fd);
 
30
        read_tag = g_io_add_watch(con,
 
31
                (GIOCondition)(G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP),
 
32
                _read_event, this);
 
33
    }
 
34
 
 
35
    void write(const string &line)
 
36
    {
 
37
        if (outbuf.empty())
 
38
            write_tag = g_io_add_watch(con, G_IO_OUT, _write_event, this);
 
39
 
 
40
        outbuf.push_back(line);
 
41
    }
 
42
 
 
43
    void close()
 
44
    {
 
45
        if (con)
 
46
        {
 
47
            g_io_channel_close(con);
 
48
            g_io_channel_unref(con);
 
49
        }
 
50
        if (write_tag)
 
51
            g_source_remove(write_tag);
 
52
        if (read_tag)
 
53
            g_source_remove(read_tag);
 
54
        write_tag = read_tag = 0;
 
55
        inbuf = "";
 
56
        outbuf.clear();
 
57
        outp = 0;
 
58
        con = 0;
 
59
    }
 
60
 
 
61
    virtual void process_line(const string &line) = 0;
 
62
    virtual void connection_lost() = 0;
 
63
 
 
64
    static gboolean _read_event(GIOChannel *source,
 
65
            GIOCondition condition, gpointer data)
 
66
    {
 
67
        GIOSocket *s = (GIOSocket*)data;
 
68
        return s->read_event(condition);
 
69
    }
 
70
 
 
71
    static gboolean _write_event(GIOChannel *source,
 
72
            GIOCondition condition, gpointer data)
 
73
    {
 
74
        GIOSocket *s = (GIOSocket*)data;
 
75
        return s->write_event(condition);
 
76
    }
 
77
 
 
78
    bool write_event(GIOCondition condition)
 
79
    {
 
80
        if (!con)
 
81
            return false;
 
82
 
 
83
        assert(condition & G_IO_OUT);
 
84
 
 
85
        if (!outp && !outbuf.empty())
 
86
            outp = outbuf.front().c_str();
 
87
 
 
88
        if (!outp)
 
89
            return (write_tag = 0);
 
90
 
 
91
        unsigned len = strlen(outp);
 
92
        gsize n = 0;
 
93
        GIOError e = g_io_channel_write(con, (char*)outp, len, &n);
 
94
        if (e == G_IO_ERROR_NONE)
 
95
        {
 
96
            if (n == len)
 
97
            {
 
98
                outbuf.pop_front();
 
99
                outp = 0;
 
100
                return outbuf.empty() ? (write_tag = 0) : 1;
 
101
            }
 
102
            outp += n;
 
103
        }
 
104
 
 
105
        return true;
 
106
    }
 
107
 
 
108
    bool read_event(GIOCondition condition)
 
109
    {
 
110
        if (!con)
 
111
            return false;
 
112
 
 
113
        if (condition & G_IO_HUP)
 
114
        {
 
115
            connection_lost();
 
116
            close();
 
117
#ifdef DEBUG
 
118
            std::cerr << "Connection terminated." << std::endl;
 
119
#endif
 
120
            return false;
 
121
        }
 
122
 
 
123
        if (condition & G_IO_IN)
 
124
        {
 
125
            gsize n = 0;
 
126
            GIOError e = g_io_channel_read(con, buf, sizeof(buf) - 1, &n);
 
127
            if (e == G_IO_ERROR_NONE)
 
128
            {
 
129
                buf[n] = '\0';
 
130
                char *lineend, *cur = buf;
 
131
                while ((lineend = strchr(cur, '\n')))
 
132
                {
 
133
                    *lineend = '\0';
 
134
                    inbuf += cur;
 
135
                    cur = lineend + 1;
 
136
                    process_line(inbuf);
 
137
                    inbuf = "";
 
138
                }
 
139
                inbuf += cur;
 
140
            }
 
141
        }
 
142
 
 
143
        return true;
 
144
    }
 
145
 
 
146
private:
 
147
    char buf[128];
 
148
 
 
149
    GIOChannel *con;
 
150
    int read_tag, write_tag;
 
151
    string inbuf;
 
152
    const char *outp;
 
153
    std::list<string> outbuf;
 
154
};
 
155
 
 
156
#endif