~ubuntu-branches/ubuntu/precise/rygel/precise

« back to all changes in this revision

Viewing changes to src/rygel/rygel-http-response.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Henriksson
  • Date: 2009-09-26 14:04:05 UTC
  • Revision ID: james.westby@ubuntu.com-20090926140405-d5x3j13k10psa1gu
Tags: upstream-0.4.1
ImportĀ upstreamĀ versionĀ 0.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 Nokia Corporation.
 
3
 *
 
4
 * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
 
5
 *                               <zeeshan.ali@nokia.com>
 
6
 *
 
7
 * This file is part of Rygel.
 
8
 *
 
9
 * Rygel is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU Lesser General Public License as published by
 
11
 * the Free Software Foundation; either version 2 of the License, or
 
12
 * (at your option) any later version.
 
13
 *
 
14
 * Rygel is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public License
 
20
 * along with this program; if not, write to the Free Software Foundation,
 
21
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
22
 */
 
23
 
 
24
#include <glib.h>
 
25
#include <glib-object.h>
 
26
#include <gio/gio.h>
 
27
#include <libsoup/soup.h>
 
28
 
 
29
 
 
30
#define RYGEL_TYPE_STATE_MACHINE (rygel_state_machine_get_type ())
 
31
#define RYGEL_STATE_MACHINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_STATE_MACHINE, RygelStateMachine))
 
32
#define RYGEL_IS_STATE_MACHINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_STATE_MACHINE))
 
33
#define RYGEL_STATE_MACHINE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), RYGEL_TYPE_STATE_MACHINE, RygelStateMachineIface))
 
34
 
 
35
typedef struct _RygelStateMachine RygelStateMachine;
 
36
typedef struct _RygelStateMachineIface RygelStateMachineIface;
 
37
 
 
38
#define RYGEL_TYPE_HTTP_RESPONSE (rygel_http_response_get_type ())
 
39
#define RYGEL_HTTP_RESPONSE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RYGEL_TYPE_HTTP_RESPONSE, RygelHTTPResponse))
 
40
#define RYGEL_HTTP_RESPONSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RYGEL_TYPE_HTTP_RESPONSE, RygelHTTPResponseClass))
 
41
#define RYGEL_IS_HTTP_RESPONSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RYGEL_TYPE_HTTP_RESPONSE))
 
42
#define RYGEL_IS_HTTP_RESPONSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RYGEL_TYPE_HTTP_RESPONSE))
 
43
#define RYGEL_HTTP_RESPONSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RYGEL_TYPE_HTTP_RESPONSE, RygelHTTPResponseClass))
 
44
 
 
45
typedef struct _RygelHTTPResponse RygelHTTPResponse;
 
46
typedef struct _RygelHTTPResponseClass RygelHTTPResponseClass;
 
47
typedef struct _RygelHTTPResponsePrivate RygelHTTPResponsePrivate;
 
48
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
 
49
 
 
50
struct _RygelStateMachineIface {
 
51
        GTypeInterface parent_iface;
 
52
        void (*run) (RygelStateMachine* self);
 
53
        GCancellable* (*get_cancellable) (RygelStateMachine* self);
 
54
        void (*set_cancellable) (RygelStateMachine* self, GCancellable* value);
 
55
};
 
56
 
 
57
struct _RygelHTTPResponse {
 
58
        GObject parent_instance;
 
59
        RygelHTTPResponsePrivate * priv;
 
60
        SoupMessage* msg;
 
61
};
 
62
 
 
63
struct _RygelHTTPResponseClass {
 
64
        GObjectClass parent_class;
 
65
        void (*run) (RygelHTTPResponse* self);
 
66
        void (*end) (RygelHTTPResponse* self, gboolean aborted, guint status);
 
67
};
 
68
 
 
69
struct _RygelHTTPResponsePrivate {
 
70
        SoupServer* _server;
 
71
        GCancellable* _cancellable;
 
72
};
 
73
 
 
74
 
 
75
static gpointer rygel_http_response_parent_class = NULL;
 
76
static RygelStateMachineIface* rygel_http_response_rygel_state_machine_parent_iface = NULL;
 
77
 
 
78
GType rygel_state_machine_get_type (void);
 
79
GType rygel_http_response_get_type (void);
 
80
#define RYGEL_HTTP_RESPONSE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RYGEL_TYPE_HTTP_RESPONSE, RygelHTTPResponsePrivate))
 
81
enum  {
 
82
        RYGEL_HTTP_RESPONSE_DUMMY_PROPERTY,
 
83
        RYGEL_HTTP_RESPONSE_SERVER,
 
84
        RYGEL_HTTP_RESPONSE_CANCELLABLE
 
85
};
 
86
static void rygel_http_response_set_server (RygelHTTPResponse* self, SoupServer* value);
 
87
void rygel_state_machine_set_cancellable (RygelStateMachine* self, GCancellable* value);
 
88
static void rygel_http_response_on_request_aborted (RygelHTTPResponse* self, SoupServer* server, SoupMessage* msg, SoupClientContext* client);
 
89
static void _rygel_http_response_on_request_aborted_soup_server_request_aborted (SoupServer* _sender, SoupMessage* msg, SoupClientContext* client, gpointer self);
 
90
SoupServer* rygel_http_response_get_server (RygelHTTPResponse* self);
 
91
RygelHTTPResponse* rygel_http_response_construct (GType object_type, SoupServer* server, SoupMessage* msg, gboolean partial, GCancellable* cancellable);
 
92
GCancellable* rygel_state_machine_get_cancellable (RygelStateMachine* self);
 
93
static void rygel_http_response_on_cancelled (RygelHTTPResponse* self, GCancellable* cancellable);
 
94
static void _rygel_http_response_on_cancelled_g_cancellable_cancelled (GCancellable* _sender, gpointer self);
 
95
void rygel_http_response_run (RygelHTTPResponse* self);
 
96
static void rygel_http_response_real_run (RygelHTTPResponse* self);
 
97
void rygel_http_response_end (RygelHTTPResponse* self, gboolean aborted, guint status);
 
98
void rygel_http_response_push_data (RygelHTTPResponse* self, void* data, gsize length);
 
99
static void rygel_http_response_real_end (RygelHTTPResponse* self, gboolean aborted, guint status);
 
100
static void rygel_http_response_finalize (GObject* obj);
 
101
static void rygel_http_response_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);
 
102
static void rygel_http_response_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec);
 
103
 
 
104
 
 
105
 
 
106
static gpointer _g_object_ref0 (gpointer self) {
 
107
        return self ? g_object_ref (self) : NULL;
 
108
}
 
109
 
 
110
 
 
111
static void _rygel_http_response_on_request_aborted_soup_server_request_aborted (SoupServer* _sender, SoupMessage* msg, SoupClientContext* client, gpointer self) {
 
112
        rygel_http_response_on_request_aborted (self, _sender, msg, client);
 
113
}
 
114
 
 
115
 
 
116
RygelHTTPResponse* rygel_http_response_construct (GType object_type, SoupServer* server, SoupMessage* msg, gboolean partial, GCancellable* cancellable) {
 
117
        RygelHTTPResponse * self;
 
118
        SoupMessage* _tmp0_;
 
119
        g_return_val_if_fail (server != NULL, NULL);
 
120
        g_return_val_if_fail (msg != NULL, NULL);
 
121
        self = (RygelHTTPResponse*) g_object_new (object_type, NULL);
 
122
        rygel_http_response_set_server (self, server);
 
123
        self->msg = (_tmp0_ = _g_object_ref0 (msg), _g_object_unref0 (self->msg), _tmp0_);
 
124
        rygel_state_machine_set_cancellable ((RygelStateMachine*) self, cancellable);
 
125
        if (partial) {
 
126
                soup_message_set_status (self->msg, (guint) SOUP_STATUS_PARTIAL_CONTENT);
 
127
        } else {
 
128
                soup_message_set_status (self->msg, (guint) SOUP_STATUS_OK);
 
129
        }
 
130
        soup_message_body_set_accumulate (self->msg->response_body, FALSE);
 
131
        g_signal_connect_object (self->priv->_server, "request-aborted", (GCallback) _rygel_http_response_on_request_aborted_soup_server_request_aborted, self, 0);
 
132
        return self;
 
133
}
 
134
 
 
135
 
 
136
static void _rygel_http_response_on_cancelled_g_cancellable_cancelled (GCancellable* _sender, gpointer self) {
 
137
        rygel_http_response_on_cancelled (self, _sender);
 
138
}
 
139
 
 
140
 
 
141
static void rygel_http_response_real_run (RygelHTTPResponse* self) {
 
142
        g_return_if_fail (self != NULL);
 
143
        if (rygel_state_machine_get_cancellable ((RygelStateMachine*) self) != NULL) {
 
144
                g_signal_connect_object (rygel_state_machine_get_cancellable ((RygelStateMachine*) self), "cancelled", (GCallback) _rygel_http_response_on_cancelled_g_cancellable_cancelled, self, 0);
 
145
        }
 
146
}
 
147
 
 
148
 
 
149
void rygel_http_response_run (RygelHTTPResponse* self) {
 
150
        RYGEL_HTTP_RESPONSE_GET_CLASS (self)->run (self);
 
151
}
 
152
 
 
153
 
 
154
static void rygel_http_response_on_cancelled (RygelHTTPResponse* self, GCancellable* cancellable) {
 
155
        g_return_if_fail (self != NULL);
 
156
        g_return_if_fail (cancellable != NULL);
 
157
        rygel_http_response_end (self, TRUE, (guint) SOUP_STATUS_CANCELLED);
 
158
}
 
159
 
 
160
 
 
161
static void rygel_http_response_on_request_aborted (RygelHTTPResponse* self, SoupServer* server, SoupMessage* msg, SoupClientContext* client) {
 
162
        g_return_if_fail (self != NULL);
 
163
        g_return_if_fail (server != NULL);
 
164
        g_return_if_fail (msg != NULL);
 
165
        g_return_if_fail (client != NULL);
 
166
        if (msg == self->msg) {
 
167
                rygel_http_response_end (self, TRUE, (guint) SOUP_STATUS_NONE);
 
168
        }
 
169
}
 
170
 
 
171
 
 
172
void rygel_http_response_push_data (RygelHTTPResponse* self, void* data, gsize length) {
 
173
        g_return_if_fail (self != NULL);
 
174
        soup_message_body_append (self->msg->response_body, SOUP_MEMORY_COPY, data, length);
 
175
        soup_server_unpause_message (self->priv->_server, self->msg);
 
176
}
 
177
 
 
178
 
 
179
static void rygel_http_response_real_end (RygelHTTPResponse* self, gboolean aborted, guint status) {
 
180
        g_return_if_fail (self != NULL);
 
181
        if (status != SOUP_STATUS_NONE) {
 
182
                soup_message_set_status (self->msg, status);
 
183
        }
 
184
        g_signal_emit_by_name ((RygelStateMachine*) self, "completed");
 
185
}
 
186
 
 
187
 
 
188
void rygel_http_response_end (RygelHTTPResponse* self, gboolean aborted, guint status) {
 
189
        RYGEL_HTTP_RESPONSE_GET_CLASS (self)->end (self, aborted, status);
 
190
}
 
191
 
 
192
 
 
193
SoupServer* rygel_http_response_get_server (RygelHTTPResponse* self) {
 
194
        SoupServer* result;
 
195
        g_return_val_if_fail (self != NULL, NULL);
 
196
        result = self->priv->_server;
 
197
        return result;
 
198
}
 
199
 
 
200
 
 
201
static void rygel_http_response_set_server (RygelHTTPResponse* self, SoupServer* value) {
 
202
        SoupServer* _tmp0_;
 
203
        g_return_if_fail (self != NULL);
 
204
        self->priv->_server = (_tmp0_ = _g_object_ref0 (value), _g_object_unref0 (self->priv->_server), _tmp0_);
 
205
        g_object_notify ((GObject *) self, "server");
 
206
}
 
207
 
 
208
 
 
209
static GCancellable* rygel_http_response_real_get_cancellable (RygelStateMachine* base) {
 
210
        GCancellable* result;
 
211
        RygelHTTPResponse* self;
 
212
        self = (RygelHTTPResponse*) base;
 
213
        result = self->priv->_cancellable;
 
214
        return result;
 
215
}
 
216
 
 
217
 
 
218
static void rygel_http_response_real_set_cancellable (RygelStateMachine* base, GCancellable* value) {
 
219
        RygelHTTPResponse* self;
 
220
        GCancellable* _tmp0_;
 
221
        self = (RygelHTTPResponse*) base;
 
222
        self->priv->_cancellable = (_tmp0_ = _g_object_ref0 (value), _g_object_unref0 (self->priv->_cancellable), _tmp0_);
 
223
        g_object_notify ((GObject *) self, "cancellable");
 
224
}
 
225
 
 
226
 
 
227
static void rygel_http_response_class_init (RygelHTTPResponseClass * klass) {
 
228
        rygel_http_response_parent_class = g_type_class_peek_parent (klass);
 
229
        g_type_class_add_private (klass, sizeof (RygelHTTPResponsePrivate));
 
230
        RYGEL_HTTP_RESPONSE_CLASS (klass)->run = rygel_http_response_real_run;
 
231
        RYGEL_HTTP_RESPONSE_CLASS (klass)->end = rygel_http_response_real_end;
 
232
        G_OBJECT_CLASS (klass)->get_property = rygel_http_response_get_property;
 
233
        G_OBJECT_CLASS (klass)->set_property = rygel_http_response_set_property;
 
234
        G_OBJECT_CLASS (klass)->finalize = rygel_http_response_finalize;
 
235
        g_object_class_install_property (G_OBJECT_CLASS (klass), RYGEL_HTTP_RESPONSE_SERVER, g_param_spec_object ("server", "server", "server", SOUP_TYPE_SERVER, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
 
236
        g_object_class_override_property (G_OBJECT_CLASS (klass), RYGEL_HTTP_RESPONSE_CANCELLABLE, "cancellable");
 
237
}
 
238
 
 
239
 
 
240
static void rygel_http_response_rygel_state_machine_interface_init (RygelStateMachineIface * iface) {
 
241
        rygel_http_response_rygel_state_machine_parent_iface = g_type_interface_peek_parent (iface);
 
242
        iface->run = (void (*)(RygelStateMachine*)) rygel_http_response_run;
 
243
        iface->get_cancellable = rygel_http_response_real_get_cancellable;
 
244
        iface->set_cancellable = rygel_http_response_real_set_cancellable;
 
245
}
 
246
 
 
247
 
 
248
static void rygel_http_response_instance_init (RygelHTTPResponse * self) {
 
249
        self->priv = RYGEL_HTTP_RESPONSE_GET_PRIVATE (self);
 
250
}
 
251
 
 
252
 
 
253
static void rygel_http_response_finalize (GObject* obj) {
 
254
        RygelHTTPResponse * self;
 
255
        self = RYGEL_HTTP_RESPONSE (obj);
 
256
        _g_object_unref0 (self->priv->_server);
 
257
        _g_object_unref0 (self->msg);
 
258
        _g_object_unref0 (self->priv->_cancellable);
 
259
        G_OBJECT_CLASS (rygel_http_response_parent_class)->finalize (obj);
 
260
}
 
261
 
 
262
 
 
263
GType rygel_http_response_get_type (void) {
 
264
        static GType rygel_http_response_type_id = 0;
 
265
        if (rygel_http_response_type_id == 0) {
 
266
                static const GTypeInfo g_define_type_info = { sizeof (RygelHTTPResponseClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) rygel_http_response_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RygelHTTPResponse), 0, (GInstanceInitFunc) rygel_http_response_instance_init, NULL };
 
267
                static const GInterfaceInfo rygel_state_machine_info = { (GInterfaceInitFunc) rygel_http_response_rygel_state_machine_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
 
268
                rygel_http_response_type_id = g_type_register_static (G_TYPE_OBJECT, "RygelHTTPResponse", &g_define_type_info, G_TYPE_FLAG_ABSTRACT);
 
269
                g_type_add_interface_static (rygel_http_response_type_id, RYGEL_TYPE_STATE_MACHINE, &rygel_state_machine_info);
 
270
        }
 
271
        return rygel_http_response_type_id;
 
272
}
 
273
 
 
274
 
 
275
static void rygel_http_response_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
 
276
        RygelHTTPResponse * self;
 
277
        self = RYGEL_HTTP_RESPONSE (object);
 
278
        switch (property_id) {
 
279
                case RYGEL_HTTP_RESPONSE_SERVER:
 
280
                g_value_set_object (value, rygel_http_response_get_server (self));
 
281
                break;
 
282
                case RYGEL_HTTP_RESPONSE_CANCELLABLE:
 
283
                g_value_set_object (value, rygel_state_machine_get_cancellable ((RygelStateMachine*) self));
 
284
                break;
 
285
                default:
 
286
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
287
                break;
 
288
        }
 
289
}
 
290
 
 
291
 
 
292
static void rygel_http_response_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
 
293
        RygelHTTPResponse * self;
 
294
        self = RYGEL_HTTP_RESPONSE (object);
 
295
        switch (property_id) {
 
296
                case RYGEL_HTTP_RESPONSE_SERVER:
 
297
                rygel_http_response_set_server (self, g_value_get_object (value));
 
298
                break;
 
299
                case RYGEL_HTTP_RESPONSE_CANCELLABLE:
 
300
                rygel_state_machine_set_cancellable ((RygelStateMachine*) self, g_value_get_object (value));
 
301
                break;
 
302
                default:
 
303
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
304
                break;
 
305
        }
 
306
}
 
307
 
 
308
 
 
309
 
 
310