2
* Copyright (C) 2008 Nokia Corporation.
4
* Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
5
* <zeeshan.ali@nokia.com>
7
* This file is part of Rygel.
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.
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.
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.
25
#include <glib-object.h>
27
#include <libsoup/soup.h>
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))
35
typedef struct _RygelStateMachine RygelStateMachine;
36
typedef struct _RygelStateMachineIface RygelStateMachineIface;
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))
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)))
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);
57
struct _RygelHTTPResponse {
58
GObject parent_instance;
59
RygelHTTPResponsePrivate * priv;
63
struct _RygelHTTPResponseClass {
64
GObjectClass parent_class;
65
void (*run) (RygelHTTPResponse* self);
66
void (*end) (RygelHTTPResponse* self, gboolean aborted, guint status);
69
struct _RygelHTTPResponsePrivate {
71
GCancellable* _cancellable;
75
static gpointer rygel_http_response_parent_class = NULL;
76
static RygelStateMachineIface* rygel_http_response_rygel_state_machine_parent_iface = NULL;
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))
82
RYGEL_HTTP_RESPONSE_DUMMY_PROPERTY,
83
RYGEL_HTTP_RESPONSE_SERVER,
84
RYGEL_HTTP_RESPONSE_CANCELLABLE
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);
106
static gpointer _g_object_ref0 (gpointer self) {
107
return self ? g_object_ref (self) : NULL;
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);
116
RygelHTTPResponse* rygel_http_response_construct (GType object_type, SoupServer* server, SoupMessage* msg, gboolean partial, GCancellable* cancellable) {
117
RygelHTTPResponse * self;
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);
126
soup_message_set_status (self->msg, (guint) SOUP_STATUS_PARTIAL_CONTENT);
128
soup_message_set_status (self->msg, (guint) SOUP_STATUS_OK);
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);
136
static void _rygel_http_response_on_cancelled_g_cancellable_cancelled (GCancellable* _sender, gpointer self) {
137
rygel_http_response_on_cancelled (self, _sender);
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);
149
void rygel_http_response_run (RygelHTTPResponse* self) {
150
RYGEL_HTTP_RESPONSE_GET_CLASS (self)->run (self);
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);
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);
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);
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);
184
g_signal_emit_by_name ((RygelStateMachine*) self, "completed");
188
void rygel_http_response_end (RygelHTTPResponse* self, gboolean aborted, guint status) {
189
RYGEL_HTTP_RESPONSE_GET_CLASS (self)->end (self, aborted, status);
193
SoupServer* rygel_http_response_get_server (RygelHTTPResponse* self) {
195
g_return_val_if_fail (self != NULL, NULL);
196
result = self->priv->_server;
201
static void rygel_http_response_set_server (RygelHTTPResponse* self, SoupServer* value) {
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");
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;
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");
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");
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;
248
static void rygel_http_response_instance_init (RygelHTTPResponse * self) {
249
self->priv = RYGEL_HTTP_RESPONSE_GET_PRIVATE (self);
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);
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);
271
return rygel_http_response_type_id;
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));
282
case RYGEL_HTTP_RESPONSE_CANCELLABLE:
283
g_value_set_object (value, rygel_state_machine_get_cancellable ((RygelStateMachine*) self));
286
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
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));
299
case RYGEL_HTTP_RESPONSE_CANCELLABLE:
300
rygel_state_machine_set_cancellable ((RygelStateMachine*) self, g_value_get_object (value));
303
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);