~xig-team/xig/debian

« back to all changes in this revision

Viewing changes to src/xig-client.c

  • Committer: Robert Ancell
  • Date: 2011-11-29 01:32:22 UTC
  • mfrom: (119.1.16 xig)
  • Revision ID: robert.ancell@canonical.com-20111129013222-ze72jct47juqdod9
MergeĀ upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2011 Canonical Ltd.
 
3
 * 
 
4
 * This library is free software; you can redistribute it and/or modify it under
 
5
 * the terms of the GNU Lesser General Public License version 3 as published by
 
6
 * the Free Software Foundation. See http://www.gnu.org/copyleft/lgpl.html the
 
7
 * full text of the license.
 
8
 */
 
9
 
 
10
#include <stdlib.h>
 
11
#include <stdio.h>
 
12
#include <string.h>
 
13
#include <errno.h>
 
14
#include <sys/types.h>
 
15
#include <sys/socket.h>
 
16
#include <gio/gio.h>
 
17
#include <gio/gunixsocketaddress.h>
 
18
 
 
19
#include "xig/xig-client.h"
 
20
#include "xig-common.h"
 
21
 
 
22
G_DEFINE_TYPE (XigClient, xig_client, G_TYPE_OBJECT);
 
23
 
 
24
struct XigClientPrivate
 
25
{
 
26
    /* Socket to server */
 
27
    GSocket *socket;  
 
28
    GIOChannel *channel;
 
29
 
 
30
    /* Byte order being used */
 
31
    ByteOrder byte_order;
 
32
 
 
33
    /* TRUE if client has connected */
 
34
    gboolean connected;
 
35
 
 
36
    /* Server properties */
 
37
    guint16 protocol_major_version;
 
38
    guint16 protocol_minor_version;
 
39
    guint32 release_number;
 
40
    guint32 motion_buffer_size;
 
41
    guint32 maximum_request_length;
 
42
    guint8 image_byte_order;
 
43
    guint8 bitmap_format_bit_order;
 
44
    guint8 bitmap_format_scanline_unit;
 
45
    guint8 bitmap_format_scanline_pad;
 
46
    guint8 min_keycode;
 
47
    guint8 max_keycode;
 
48
    gchar *vendor;
 
49
 
 
50
    /* Allocated resource IDs */
 
51
    guint32 resource_id_base;
 
52
    guint32 resource_id_mask;
 
53
 
 
54
    gboolean log_messages;
 
55
};
 
56
 
 
57
enum
 
58
{
 
59
    DISCONNECTED,
 
60
    LAST_SIGNAL
 
61
};
 
62
static guint signals[LAST_SIGNAL] = { 0 };
 
63
 
 
64
XigClient *
 
65
xig_client_new_from_environment (void)
 
66
{
 
67
    XigClient *client;
 
68
 
 
69
    client = g_object_new (xig_client_get_type (), NULL);  
 
70
 
 
71
    return client;
 
72
}
 
73
 
 
74
void
 
75
xig_client_set_log_messages (XigClient *client, gboolean log_messages)
 
76
{
 
77
    client->priv->log_messages = log_messages;
 
78
}
 
79
 
 
80
GInetAddress *
 
81
xig_client_get_server_address (XigClient *client)
 
82
{
 
83
    GSocketAddress *socket_address;
 
84
    GError *error = NULL;
 
85
 
 
86
    socket_address = g_socket_get_remote_address (client->priv->socket, &error);
 
87
    if (error)
 
88
        g_warning ("Error getting remote socket address");
 
89
    g_clear_error (&error);
 
90
    if (!socket_address)
 
91
        return NULL;
 
92
 
 
93
    if (G_IS_INET_SOCKET_ADDRESS (socket_address))
 
94
        return g_inet_socket_address_get_address (G_INET_SOCKET_ADDRESS (socket_address));
 
95
    else
 
96
        return NULL;
 
97
}
 
98
 
 
99
void
 
100
xig_client_disconnect (XigClient *client)
 
101
{
 
102
    g_io_channel_shutdown (client->priv->channel, TRUE, NULL);
 
103
}
 
104
 
 
105
static void
 
106
decode_connection_response (XigClient *client, const guint8 *buffer, gssize buffer_length)
 
107
{
 
108
    guint8 response_code, n_screens, n_formats;
 
109
    gsize offset = 0;
 
110
    guint16 vendor_length;
 
111
    int i;
 
112
 
 
113
    response_code = read_card8 (buffer, buffer_length, &offset);
 
114
    if (response_code != Success)
 
115
        return;
 
116
  
 
117
    read_padding (1, &offset);
 
118
    client->priv->protocol_major_version = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset);
 
119
    client->priv->protocol_minor_version = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset);
 
120
    /*n =*/ read_card16 (buffer, buffer_length, client->priv->byte_order, &offset);
 
121
    client->priv->release_number = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset);
 
122
    client->priv->resource_id_base = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset);
 
123
    client->priv->resource_id_mask = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset);
 
124
    client->priv->motion_buffer_size = read_card32 (buffer, buffer_length, client->priv->byte_order, &offset);
 
125
    vendor_length = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset);
 
126
    client->priv->maximum_request_length = read_card16 (buffer, buffer_length, client->priv->byte_order, &offset);
 
127
    n_screens = read_card8 (buffer, buffer_length, &offset);
 
128
    n_formats = read_card8 (buffer, buffer_length, &offset);
 
129
    client->priv->image_byte_order = read_card8 (buffer, buffer_length, &offset);
 
130
    client->priv->bitmap_format_bit_order = read_card8 (buffer, buffer_length, &offset);
 
131
    client->priv->bitmap_format_scanline_unit = read_card8 (buffer, buffer_length, &offset);
 
132
    client->priv->bitmap_format_scanline_pad = read_card8 (buffer, buffer_length, &offset);
 
133
    client->priv->min_keycode = read_card8 (buffer, buffer_length, &offset);
 
134
    client->priv->max_keycode = read_card8 (buffer, buffer_length, &offset);
 
135
    read_padding (4, &offset);
 
136
    client->priv->vendor = read_padded_string (buffer, buffer_length, vendor_length, &offset);
 
137
  
 
138
    for (i = 0; i < n_formats; i++)
 
139
    {
 
140
         read_card8 (buffer, buffer_length, &offset);
 
141
         read_card8 (buffer, buffer_length, &offset);
 
142
         read_card8 (buffer, buffer_length, &offset);
 
143
         read_padding (5, &offset);
 
144
    }
 
145
  
 
146
    for (i = 0; i < n_screens; i++)
 
147
    {
 
148
           
 
149
    }
 
150
}
 
151
 
 
152
static void
 
153
decode_response (XigClient *client, const guint8 *buffer, gssize buffer_length)
 
154
{
 
155
    int opcode;
 
156
    gsize offset = 0;
 
157
 
 
158
    while (offset < buffer_length)
 
159
    {
 
160
        opcode = read_card8 (buffer, buffer_length, &offset);
 
161
 
 
162
        switch (opcode)
 
163
        {
 
164
        default:
 
165
            //send_error (client, Implementation, opcode, 0, client->priv->sequence_number, 0);
 
166
            break;
 
167
        }
 
168
    }
 
169
}
 
170
 
 
171
static gboolean
 
172
socket_data_cb (GIOChannel *channel, GIOCondition condition, gpointer data)
 
173
{
 
174
    XigClient *client = data;
 
175
    guint8 buffer[MAXIMUM_REQUEST_LENGTH];
 
176
    gssize n_read;
 
177
  
 
178
    n_read = recv (g_io_channel_unix_get_fd (channel), buffer, MAXIMUM_REQUEST_LENGTH, 0);
 
179
    if (n_read < 0)
 
180
        g_warning ("Error reading from socket: %s", strerror (errno));
 
181
    else if (n_read == 0)
 
182
    {      
 
183
        g_signal_emit (client, signals[DISCONNECTED], 0);
 
184
        return FALSE;
 
185
    }
 
186
    else
 
187
    {
 
188
        if (client->priv->connected)
 
189
            decode_response (client, buffer, n_read);
 
190
        else
 
191
            decode_connection_response (client, buffer, n_read);
 
192
    }
 
193
 
 
194
    return TRUE;
 
195
}
 
196
 
 
197
gboolean
 
198
xig_client_connect_sync (XigClient *client, GError **error)
 
199
{
 
200
    client->priv->socket = g_socket_new (G_SOCKET_FAMILY_UNIX, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, error);
 
201
    if (client->priv->socket == NULL)
 
202
        return FALSE;
 
203
 
 
204
    client->priv->channel = g_io_channel_unix_new (g_socket_get_fd (client->priv->socket));
 
205
    g_io_add_watch (client->priv->channel, G_IO_IN, socket_data_cb, client);
 
206
  
 
207
    return TRUE;
 
208
}
 
209
 
 
210
static void
 
211
xig_client_init (XigClient *client)
 
212
{
 
213
    client->priv = G_TYPE_INSTANCE_GET_PRIVATE (client, xig_client_get_type (), XigClientPrivate);
 
214
}
 
215
 
 
216
static void
 
217
xig_client_finalize (GObject *object)
 
218
{
 
219
    XigClient *client = XIG_CLIENT (object);
 
220
 
 
221
    g_free (client->priv->vendor);
 
222
}
 
223
 
 
224
static void
 
225
xig_client_class_init (XigClientClass *klass)
 
226
{
 
227
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
228
 
 
229
    object_class->finalize = xig_client_finalize;
 
230
 
 
231
    g_type_class_add_private (klass, sizeof (XigClientPrivate));
 
232
 
 
233
    signals[DISCONNECTED] =
 
234
        g_signal_new ("disconnected",
 
235
                      G_TYPE_FROM_CLASS (klass),
 
236
                      G_SIGNAL_RUN_LAST,
 
237
                      G_STRUCT_OFFSET (XigClientClass, disconnected),
 
238
                      NULL, NULL,
 
239
                      g_cclosure_marshal_VOID__VOID,
 
240
                      G_TYPE_NONE, 0);
 
241
}