1 /*
2 * librest - RESTful web services access
3 * Copyright (c) 2010 Intel Corporation.
4 *
5 * Authors: Rob Bradford <rob@linux.intel.com>
6 * Ross Burton <ross@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU Lesser General Public License,
10 * version 2.1, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this program; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23 #include <config.h>
24
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <libsoup/soup.h>
29 #include <rest/rest-proxy.h>
30
31 static int errors = 0;
32 static GMainLoop *loop = NULL;
33
34 #define NUM_CHUNKS 20
35 #define SIZE_CHUNK 4
36 static guint8 server_count = 0;
37 static guint8 client_count = 0;
38 static SoupServer *server;
39
40 static gboolean
send_chunks(gpointer user_data)41 send_chunks (gpointer user_data)
42 {
43 SoupMessage *msg = SOUP_MESSAGE (user_data);
44 guint i;
45 guint8 data[SIZE_CHUNK];
46
47 for (i = 0; i < SIZE_CHUNK; i++)
48 {
49 data[i] = server_count;
50 server_count++;
51 }
52
53 soup_message_body_append (msg->response_body, SOUP_MEMORY_COPY, data, SIZE_CHUNK);
54 soup_server_unpause_message (server, msg);
55
56 if (server_count == NUM_CHUNKS * SIZE_CHUNK)
57 {
58 soup_message_body_complete (msg->response_body);
59 return FALSE;
60 } else {
61 return TRUE;
62 }
63 }
64
65 static void
server_callback(SoupServer * server,SoupMessage * msg,const char * path,GHashTable * query,SoupClientContext * client,gpointer user_data)66 server_callback (SoupServer *server, SoupMessage *msg,
67 const char *path, GHashTable *query,
68 SoupClientContext *client, gpointer user_data)
69 {
70 if (g_str_equal (path, "/stream")) {
71 soup_message_set_status (msg, SOUP_STATUS_OK);
72 soup_message_headers_set_encoding (msg->response_headers,
73 SOUP_ENCODING_CHUNKED);
74 soup_server_pause_message (server, msg);
75
76 g_idle_add (send_chunks, msg);
77 }
78 }
79
80 static void
_call_continuous_cb(RestProxyCall * call,const gchar * buf,gsize len,const GError * error,GObject * weak_object,gpointer userdata)81 _call_continuous_cb (RestProxyCall *call,
82 const gchar *buf,
83 gsize len,
84 const GError *error,
85 GObject *weak_object,
86 gpointer userdata)
87 {
88 guint i;
89
90 if (error)
91 {
92 g_printerr ("Error: %s\n", error->message);
93 errors++;
94 goto out;
95 }
96
97 if (!REST_IS_PROXY (weak_object))
98 {
99 g_printerr ("weak object not as expected\n");
100 errors++;
101 goto out;
102 }
103
104 if (buf == NULL && len == 0)
105 {
106 if (client_count < NUM_CHUNKS * SIZE_CHUNK)
107 {
108 g_printerr ("stream ended prematurely\n");
109 errors++;
110 }
111 goto out;
112 }
113
114 for (i = 0; i < len; i++)
115 {
116 if (buf[i] != client_count)
117 {
118 g_printerr ("stream data not as expected (got %d, expected %d)\n",
119 (gint) buf[i], client_count);
120 errors++;
121 goto out;
122 }
123
124 client_count++;
125 }
126
127 return;
128 out:
129 g_main_loop_quit (loop);
130 return;
131 }
132
133 static void
stream_test(RestProxy * proxy)134 stream_test (RestProxy *proxy)
135 {
136 RestProxyCall *call;
137 GError *error = NULL;
138
139 call = rest_proxy_new_call (proxy);
140 rest_proxy_call_set_function (call, "stream");
141
142 if (!rest_proxy_call_continuous (call,
143 _call_continuous_cb,
144 (GObject *)proxy,
145 NULL,
146 &error))
147 {
148 g_printerr ("Making stream failed: %s", error->message);
149 g_error_free (error);
150 errors++;
151 return;
152 }
153
154 g_object_unref (call);
155 }
156
157 int
main(int argc,char ** argv)158 main (int argc, char **argv)
159 {
160 char *url;
161 RestProxy *proxy;
162
163 #if !GLIB_CHECK_VERSION (2, 36, 0)
164 g_type_init ();
165 #endif
166 loop = g_main_loop_new (NULL, FALSE);
167
168 server = soup_server_new (NULL);
169 soup_server_add_handler (server, NULL, server_callback, NULL, NULL);
170 soup_server_run_async (server);
171
172 url = g_strdup_printf ("http://127.0.0.1:%d/", soup_server_get_port (server));
173 proxy = rest_proxy_new (url, FALSE);
174 g_free (url);
175
176 stream_test (proxy);
177 g_main_loop_run (loop);
178
179 return errors != 0;
180 }
181