Tizen 2.0 release
[profile/ivi/obexd.git] / unit / test-gobex-transfer.c
1 /*
2  *
3  *  OBEX library with GLib integration
4  *
5  *  Copyright (C) 2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/stat.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include <fcntl.h>
31
32 #include <gobex/gobex.h>
33
34 #include "util.h"
35
36 #define FINAL_BIT 0x80
37 #define RANDOM_PACKETS 4
38
39 static guint8 put_req_first[] = { G_OBEX_OP_PUT, 0x00, 0x30,
40         G_OBEX_HDR_TYPE, 0x00, 0x0b,
41         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
42         G_OBEX_HDR_NAME, 0x00, 0x15,
43         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0,
44         G_OBEX_HDR_BODY, 0x00, 0x0d,
45         0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
46
47 static guint8 put_req_first_srm[] = { G_OBEX_OP_PUT, 0x00, 0x32,
48         G_OBEX_HDR_TYPE, 0x00, 0x0b,
49         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
50         G_OBEX_HDR_NAME, 0x00, 0x15,
51         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0,
52         G_OBEX_HDR_SRM, G_OBEX_SRM_ENABLE,
53         G_OBEX_HDR_BODY, 0x00, 0x0d,
54         0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
55
56 static guint8 put_req_zero[255] = { G_OBEX_OP_PUT, 0x00, 0xff,
57         G_OBEX_HDR_BODY, 0x00, 0xfc };
58
59 static guint8 put_req_last[] = { G_OBEX_OP_PUT | FINAL_BIT, 0x00, 0x06,
60                                         G_OBEX_HDR_BODY_END, 0x00, 0x03 };
61
62 static guint8 abort_req[] = { G_OBEX_OP_ABORT | FINAL_BIT, 0x00, 0x03 };
63
64 static guint8 put_rsp_first[] = { G_OBEX_RSP_CONTINUE | FINAL_BIT,
65                                                                 0x00, 0x03 };
66 static guint8 put_rsp_first_srm[] = { G_OBEX_RSP_CONTINUE | FINAL_BIT,
67                                                         0x00, 0x05,
68                                                         G_OBEX_HDR_SRM, 0x01 };
69 static guint8 put_rsp_first_srm_wait[] = { G_OBEX_RSP_CONTINUE | FINAL_BIT,
70                                                         0x00, 0x07,
71                                                         G_OBEX_HDR_SRM, 0x01,
72                                                         G_OBEX_HDR_SRMP, 0x01 };
73 static guint8 put_rsp_last[] = { G_OBEX_RSP_SUCCESS | FINAL_BIT, 0x00, 0x03 };
74
75 static guint8 get_req_first[] = { G_OBEX_OP_GET | FINAL_BIT, 0x00, 0x23,
76         G_OBEX_HDR_TYPE, 0x00, 0x0b,
77         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
78         G_OBEX_HDR_NAME, 0x00, 0x15,
79         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0 };
80
81 static guint8 get_req_first_app[] = { G_OBEX_OP_GET | FINAL_BIT, 0x00, 0x2a,
82         G_OBEX_HDR_TYPE, 0x00, 0x0b,
83         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
84         G_OBEX_HDR_NAME, 0x00, 0x15,
85         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0,
86         G_OBEX_HDR_APPARAM, 0x00, 0x07,
87         0, 1, 2, 3  };
88
89 static guint8 get_req_first_srm[] = { G_OBEX_OP_GET | FINAL_BIT, 0x00, 0x25,
90         G_OBEX_HDR_SRM, 0x01,
91         G_OBEX_HDR_TYPE, 0x00, 0x0b,
92         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
93         G_OBEX_HDR_NAME, 0x00, 0x15,
94         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0 };
95
96 static guint8 get_req_first_srm_wait[] = { G_OBEX_OP_GET | FINAL_BIT, 0x00, 0x27,
97         G_OBEX_HDR_SRM, 0x01,
98         G_OBEX_HDR_TYPE, 0x00, 0x0b,
99         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
100         G_OBEX_HDR_NAME, 0x00, 0x15,
101         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0,
102         G_OBEX_HDR_SRMP, 0x01 };
103
104 static guint8 get_req_last[] = { G_OBEX_OP_GET | FINAL_BIT, 0x00, 0x03, };
105
106 static guint8 get_rsp_first_app[] = { G_OBEX_RSP_CONTINUE | FINAL_BIT, 0x00, 0x0A,
107                                         G_OBEX_HDR_APPARAM, 0x00, 0x07,
108                                         0, 1, 2, 3 };
109 static guint8 get_rsp_first[] = { G_OBEX_RSP_CONTINUE | FINAL_BIT, 0x00, 0x10,
110                                         G_OBEX_HDR_BODY, 0x00, 0x0d,
111                                         0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
112 static guint8 get_rsp_first_srm[] = { G_OBEX_RSP_CONTINUE | FINAL_BIT, 0x00, 0x12,
113                                         G_OBEX_HDR_SRM, 0x01,
114                                         G_OBEX_HDR_BODY, 0x00, 0x0d,
115                                         0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
116 static guint8 get_rsp_first_srm_wait_next[] = { G_OBEX_RSP_CONTINUE | FINAL_BIT,
117                                         0x00, 0x14,
118                                         G_OBEX_HDR_SRM, 0x01,
119                                         G_OBEX_HDR_SRMP, 0x02,
120                                         G_OBEX_HDR_BODY, 0x00, 0x0d,
121                                         0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
122 static guint8 get_rsp_zero[255] = { G_OBEX_RSP_CONTINUE | FINAL_BIT, 0x00, 0xff,
123                                         G_OBEX_HDR_BODY, 0x00, 0xfc };
124 static guint8 get_rsp_zero_wait_next[255] = { G_OBEX_RSP_CONTINUE | FINAL_BIT,
125                                         0x00, 0xff,
126                                         G_OBEX_HDR_SRMP, 0x02,
127                                         G_OBEX_HDR_BODY, 0x00, 0xfa };
128 static guint8 get_rsp_last[] = { G_OBEX_RSP_SUCCESS | FINAL_BIT, 0x00, 0x06,
129                                         G_OBEX_HDR_BODY_END, 0x00, 0x03 };
130
131 static guint8 conn_req[] = { G_OBEX_OP_CONNECT | FINAL_BIT, 0x00, 0x07,
132                                         0x10, 0x00, 0x10, 0x00 };
133 static guint8 conn_rsp[] = { G_OBEX_RSP_SUCCESS | FINAL_BIT, 0x00, 0x0c,
134                                         0x10, 0x00, 0x10, 0x00,
135                                         G_OBEX_HDR_CONNECTION, 0x00, 0x00,
136                                         0x00, 0x01 };
137
138 static guint8 conn_req_srm[] = { G_OBEX_OP_CONNECT | FINAL_BIT, 0x00, 0x09,
139                                         0x10, 0x00, 0x10, 0x00,
140                                         G_OBEX_HDR_SRM, 0x02 };
141 static guint8 conn_rsp_srm[] = { G_OBEX_RSP_SUCCESS | FINAL_BIT, 0x00, 0x0e,
142                                         0x10, 0x00, 0x10, 0x00,
143                                         G_OBEX_HDR_CONNECTION, 0x00, 0x00,
144                                         0x00, 0x01,
145                                         G_OBEX_HDR_SRM, 0x01 };
146
147 static guint8 unavailable_rsp[] = { G_OBEX_RSP_SERVICE_UNAVAILABLE | FINAL_BIT,
148                                         0x00, 0x03 };
149
150 static guint8 conn_get_req_first[] = { G_OBEX_OP_GET | FINAL_BIT, 0x00, 0x28,
151         G_OBEX_HDR_CONNECTION, 0x00, 0x00, 0x00, 0x01,
152         G_OBEX_HDR_TYPE, 0x00, 0x0b,
153         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
154         G_OBEX_HDR_NAME, 0x00, 0x15,
155         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0 };
156
157 static guint8 conn_get_req_wrg[] = { G_OBEX_OP_GET | FINAL_BIT, 0x00, 0x28,
158         G_OBEX_HDR_CONNECTION, 0x00, 0x00, 0x00, 0xFF,
159         G_OBEX_HDR_TYPE, 0x00, 0x0b,
160         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
161         G_OBEX_HDR_NAME, 0x00, 0x15,
162         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0 };
163
164 static guint8 conn_put_req_first[] = { G_OBEX_OP_PUT, 0x00, 0x35,
165         G_OBEX_HDR_CONNECTION, 0x00, 0x00, 0x00, 0x01,
166         G_OBEX_HDR_TYPE, 0x00, 0x0b,
167         'f', 'o', 'o', '/', 'b', 'a', 'r', '\0',
168         G_OBEX_HDR_NAME, 0x00, 0x15,
169         0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0,
170         G_OBEX_HDR_BODY, 0x00, 0x0d,
171         0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
172
173 static guint8 hdr_type[] = "foo/bar";
174 static guint8 hdr_app[] = { 0, 1, 2, 3 };
175 static guint8 body_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
176
177 static void transfer_complete(GObex *obex, GError *err, gpointer user_data)
178 {
179         struct test_data *d = user_data;
180
181         if (err != NULL)
182                 d->err = g_error_copy(err);
183
184         g_main_loop_quit(d->mainloop);
185 }
186
187 static gboolean resume_obex(gpointer user_data)
188 {
189         g_obex_resume(user_data);
190         return FALSE;
191 }
192
193 static gssize provide_seq(void *buf, gsize len, gpointer user_data)
194 {
195         struct test_data *d = user_data;
196         int fd;
197         gssize ret;
198
199         if (d->count == RANDOM_PACKETS - 1)
200                 return 0;
201
202         fd = open("/dev/urandom", O_RDONLY | O_NOCTTY, 0);
203         if (fd < 0) {
204                 g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
205                                 "open(/dev/urandom): %s", strerror(errno));
206                 g_main_loop_quit(d->mainloop);
207                 return -1;
208         }
209
210         ret = read(fd, buf, len);
211         close(fd);
212         return ret;
213 }
214
215 static gssize provide_eagain(void *buf, gsize len, gpointer user_data)
216 {
217         struct test_data *d = user_data;
218
219         if (d->count > 0)
220                 return 0;
221
222         if (len < sizeof(body_data)) {
223                 g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
224                                 "Got data request for only %zu bytes", len);
225                 g_main_loop_quit(d->mainloop);
226                 return -1;
227         }
228
229         if (d->provide_delay > 0) {
230                 g_timeout_add(d->provide_delay, resume_obex, d->obex);
231                 d->provide_delay = 0;
232                 return -EAGAIN;
233         }
234
235         memcpy(buf, body_data, sizeof(body_data));
236
237         return sizeof(body_data);
238 }
239
240 static gssize provide_data(void *buf, gsize len, gpointer user_data)
241 {
242         struct test_data *d = user_data;
243
244         if (d->total > 0)
245                 return 0;
246
247         if (len < sizeof(body_data)) {
248                 g_set_error(&d->err, TEST_ERROR, TEST_ERROR_UNEXPECTED,
249                                 "Got data request for only %zu bytes", len);
250                 g_main_loop_quit(d->mainloop);
251                 return -1;
252         }
253
254         memcpy(buf, body_data, sizeof(body_data));
255
256         if (d->provide_delay > 0) {
257                 g_obex_suspend(d->obex);
258                 g_timeout_add(d->provide_delay, resume_obex, d->obex);
259         }
260
261         d->total += sizeof(body_data);
262
263         return sizeof(body_data);
264 }
265
266 static void test_put_req(void)
267 {
268         GIOChannel *io;
269         GIOCondition cond;
270         guint io_id, timer_id;
271         GObex *obex;
272         struct test_data d = { 0, NULL, {
273                                 { put_req_first, sizeof(put_req_first) },
274                                 { put_req_last, sizeof(put_req_last) } }, {
275                                 { put_rsp_first, sizeof(put_rsp_first) },
276                                 { put_rsp_last, sizeof(put_rsp_last) } } };
277
278         create_endpoints(&obex, &io, SOCK_STREAM);
279
280         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
281         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
282
283         d.mainloop = g_main_loop_new(NULL, FALSE);
284
285         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
286
287         g_obex_put_req(obex, provide_data, transfer_complete, &d, &d.err,
288                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
289                                 G_OBEX_HDR_NAME, "file.txt",
290                                 G_OBEX_HDR_INVALID);
291         g_assert_no_error(d.err);
292
293         g_main_loop_run(d.mainloop);
294
295         g_assert_cmpuint(d.count, ==, 2);
296
297         g_main_loop_unref(d.mainloop);
298
299         g_source_remove(timer_id);
300         g_io_channel_unref(io);
301         g_source_remove(io_id);
302         g_obex_unref(obex);
303
304         g_assert_no_error(d.err);
305 }
306
307 static gboolean rcv_data(const void *buf, gsize len, gpointer user_data)
308 {
309         struct test_data *d = user_data;
310
311         if (len != sizeof(body_data))
312                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
313                                         "Unexpected byte count %zu", len);
314
315         if (memcmp(buf, body_data, sizeof(body_data)) != 0) {
316                 dump_bufs(body_data, sizeof(body_data), buf, len);
317                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
318                                         "Unexpected byte count %zu", len);
319         }
320
321         return TRUE;
322 }
323
324 static void handle_put(GObex *obex, GObexPacket *req, gpointer user_data)
325 {
326         struct test_data *d = user_data;
327         guint8 op = g_obex_packet_get_operation(req, NULL);
328         guint id;
329
330         if (op != G_OBEX_OP_PUT) {
331                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
332                                         "Unexpected opcode 0x%02x", op);
333                 g_main_loop_quit(d->mainloop);
334                 return;
335         }
336
337         id = g_obex_put_rsp(obex, req, rcv_data, transfer_complete, d, &d->err,
338                                                         G_OBEX_HDR_INVALID);
339         if (id == 0)
340                 g_main_loop_quit(d->mainloop);
341 }
342
343 static void test_put_rsp(void)
344 {
345         GIOChannel *io;
346         GIOCondition cond;
347         guint io_id, timer_id;
348         GObex *obex;
349         struct test_data d = { 0, NULL, {
350                                 { put_rsp_first, sizeof(put_rsp_first) },
351                                 { put_rsp_last, sizeof(put_rsp_last) } }, {
352                                 { put_req_last, sizeof(put_req_last) },
353                                 { NULL, 0 } } };
354
355         create_endpoints(&obex, &io, SOCK_STREAM);
356
357         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
358         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
359
360         d.mainloop = g_main_loop_new(NULL, FALSE);
361
362         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
363
364         g_obex_add_request_function(obex, G_OBEX_OP_PUT, handle_put, &d);
365
366         g_io_channel_write_chars(io, (char *) put_req_first,
367                                         sizeof(put_req_first), NULL, &d.err);
368         g_assert_no_error(d.err);
369
370         g_main_loop_run(d.mainloop);
371
372         g_assert_cmpuint(d.count, ==, 1);
373
374         g_main_loop_unref(d.mainloop);
375
376         g_source_remove(timer_id);
377         g_io_channel_unref(io);
378         g_source_remove(io_id);
379         g_obex_unref(obex);
380
381         g_assert_no_error(d.err);
382 }
383
384 static gboolean rcv_seq(const void *buf, gsize len, gpointer user_data)
385 {
386         return TRUE;
387 }
388
389 static void handle_put_seq(GObex *obex, GObexPacket *req,
390                                                         gpointer user_data)
391 {
392         struct test_data *d = user_data;
393         guint8 op = g_obex_packet_get_operation(req, NULL);
394         guint id;
395
396         if (op != G_OBEX_OP_PUT) {
397                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
398                                         "Unexpected opcode 0x%02x", op);
399                 g_main_loop_quit(d->mainloop);
400                 return;
401         }
402
403         id = g_obex_put_rsp(obex, req, rcv_seq, transfer_complete, d,
404                                                 &d->err, G_OBEX_HDR_INVALID);
405         if (id == 0)
406                 g_main_loop_quit(d->mainloop);
407 }
408
409 static void test_stream_put_rsp(void)
410 {
411         GIOChannel *io;
412         GIOCondition cond;
413         guint io_id, timer_id;
414         GObex *obex;
415         struct test_data d = { 0, NULL, {
416                                 { put_rsp_first, sizeof(put_rsp_first) },
417                                 { put_rsp_first, sizeof(put_rsp_first) },
418                                 { put_rsp_first, sizeof(put_rsp_first) },
419                                 { put_rsp_last, sizeof(put_rsp_last) } }, {
420                                 { put_req_zero, sizeof(put_req_zero) },
421                                 { put_req_zero, sizeof(put_req_zero) },
422                                 { put_req_last, sizeof(put_req_last) },
423                                 { NULL, -1 } } };
424
425         create_endpoints(&obex, &io, SOCK_STREAM);
426
427         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
428         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
429
430         d.mainloop = g_main_loop_new(NULL, FALSE);
431
432         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
433
434         g_obex_add_request_function(obex, G_OBEX_OP_PUT, handle_put_seq,
435                                                                         &d);
436
437         g_io_channel_write_chars(io, (char *) put_req_first,
438                                         sizeof(put_req_first), NULL, &d.err);
439         g_assert_no_error(d.err);
440
441         g_main_loop_run(d.mainloop);
442
443         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS - 1);
444
445         g_main_loop_unref(d.mainloop);
446
447         g_source_remove(timer_id);
448         g_io_channel_unref(io);
449         g_source_remove(io_id);
450         g_obex_unref(obex);
451
452         g_assert_no_error(d.err);
453 }
454
455 static gboolean cancel_transfer(gpointer user_data)
456 {
457         struct test_data *d = user_data;
458
459         if (d->id > 0)
460                 g_obex_cancel_transfer(d->id, transfer_complete, user_data);
461
462         return FALSE;
463 }
464
465 static gssize abort_data(void *buf, gsize len, gpointer user_data)
466 {
467         g_idle_add_full(G_PRIORITY_HIGH, cancel_transfer, user_data, NULL);
468         return provide_data(buf, len, user_data);
469 }
470
471 static void test_stream_put_req_abort(void)
472 {
473         GIOChannel *io;
474         GIOCondition cond;
475         guint io_id, timer_id;
476         GObex *obex;
477         struct test_data d = { 0, NULL, {
478                                 { put_req_first, sizeof(put_req_first) },
479                                 { abort_req, sizeof(abort_req) } }, {
480                                 { put_rsp_last, sizeof(put_rsp_last) } } };
481
482         create_endpoints(&obex, &io, SOCK_STREAM);
483
484         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
485         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
486
487         d.mainloop = g_main_loop_new(NULL, FALSE);
488
489         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
490
491         d.id = g_obex_put_req(obex, abort_data, transfer_complete, &d, &d.err,
492                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
493                                 G_OBEX_HDR_NAME, "file.txt",
494                                 G_OBEX_HDR_INVALID);
495         g_assert_no_error(d.err);
496
497         g_main_loop_run(d.mainloop);
498
499         g_assert_cmpuint(d.count, ==, 2);
500
501         g_main_loop_unref(d.mainloop);
502
503         g_source_remove(timer_id);
504         g_io_channel_unref(io);
505         g_source_remove(io_id);
506         g_obex_unref(obex);
507
508         g_assert_error(d.err, G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED);
509 }
510
511 static void test_stream_put_rsp_abort(void)
512 {
513         GIOChannel *io;
514         GIOCondition cond;
515         guint io_id, timer_id;
516         GObex *obex;
517         struct test_data d = { 0, NULL, {
518                                 { put_rsp_first, sizeof(put_rsp_first) },
519                                 { put_rsp_first, sizeof(put_rsp_first) },
520                                 { put_rsp_first, sizeof(put_rsp_first) },
521                                 { put_rsp_last, sizeof(put_rsp_last) } }, {
522                                 { put_req_zero, sizeof(put_req_zero) },
523                                 { abort_req, sizeof(abort_req) },
524                                 { NULL, -1 },
525                                 { NULL, -1 } } };
526
527         create_endpoints(&obex, &io, SOCK_STREAM);
528
529         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
530         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
531
532         d.mainloop = g_main_loop_new(NULL, FALSE);
533
534         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
535
536         g_obex_add_request_function(obex, G_OBEX_OP_PUT, handle_put_seq, &d);
537
538         g_io_channel_write_chars(io, (char *) put_req_first,
539                                         sizeof(put_req_first), NULL, &d.err);
540         g_assert_no_error(d.err);
541
542         g_main_loop_run(d.mainloop);
543
544         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS - 2);
545
546         g_main_loop_unref(d.mainloop);
547
548         g_source_remove(timer_id);
549         g_io_channel_unref(io);
550         g_source_remove(io_id);
551         g_obex_unref(obex);
552
553         g_assert_error(d.err, G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED);
554 }
555
556 static void handle_put_seq_wait(GObex *obex, GObexPacket *req,
557                                                         gpointer user_data)
558 {
559         struct test_data *d = user_data;
560         guint8 op = g_obex_packet_get_operation(req, NULL);
561         guint id;
562
563         if (op != G_OBEX_OP_PUT) {
564                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
565                                         "Unexpected opcode 0x%02x", op);
566                 g_main_loop_quit(d->mainloop);
567                 return;
568         }
569
570         id = g_obex_put_rsp(obex, req, rcv_seq, transfer_complete, d,
571                                         &d->err,
572                                         G_OBEX_HDR_SRMP, G_OBEX_SRMP_WAIT,
573                                         G_OBEX_HDR_INVALID);
574         if (id == 0)
575                 g_main_loop_quit(d->mainloop);
576 }
577
578 static void test_packet_put_rsp_wait(void)
579 {
580         GIOChannel *io;
581         GIOCondition cond;
582         guint io_id, timer_id;
583         GObex *obex;
584         struct test_data d = { 0, NULL, {
585                 { put_rsp_first_srm_wait, sizeof(put_rsp_first_srm_wait) },
586                 { put_rsp_first, sizeof(put_rsp_first) },
587                 { NULL, -1 },
588                 { put_rsp_last, sizeof(put_rsp_last) } }, {
589                 { put_req_zero, sizeof(put_req_zero) },
590                 { put_req_zero, sizeof(put_req_zero) },
591                 { put_req_last, sizeof(put_req_last) },
592                 { NULL, 0 } } };
593
594         create_endpoints(&obex, &io, SOCK_SEQPACKET);
595
596         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
597         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
598
599         d.mainloop = g_main_loop_new(NULL, FALSE);
600
601         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
602
603         g_obex_add_request_function(obex, G_OBEX_OP_PUT,
604                                                 handle_put_seq_wait, &d);
605
606         g_io_channel_write_chars(io, (char *) put_req_first_srm,
607                                         sizeof(put_req_first_srm), NULL,
608                                         &d.err);
609         g_assert_no_error(d.err);
610
611         g_main_loop_run(d.mainloop);
612
613         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
614
615         g_main_loop_unref(d.mainloop);
616
617         g_source_remove(timer_id);
618         g_io_channel_unref(io);
619         g_source_remove(io_id);
620         g_obex_unref(obex);
621
622         g_assert_no_error(d.err);
623 }
624
625 static void test_packet_put_rsp(void)
626 {
627         GIOChannel *io;
628         GIOCondition cond;
629         guint io_id, timer_id;
630         GObex *obex;
631         struct test_data d = { 0, NULL, {
632                         { put_rsp_first_srm, sizeof(put_rsp_first_srm) },
633                         { NULL, -1 },
634                         { NULL, -1 },
635                         { put_rsp_last, sizeof(put_rsp_last) } }, {
636                         { put_req_zero, sizeof(put_req_zero) },
637                         { put_req_zero, sizeof(put_req_zero) },
638                         { put_req_last, sizeof(put_req_last) },
639                         { NULL, 0 } } };
640
641         create_endpoints(&obex, &io, SOCK_SEQPACKET);
642
643         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
644         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
645
646         d.mainloop = g_main_loop_new(NULL, FALSE);
647
648         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
649
650         g_obex_add_request_function(obex, G_OBEX_OP_PUT, handle_put_seq, &d);
651
652         g_io_channel_write_chars(io, (char *) put_req_first_srm,
653                                         sizeof(put_req_first_srm), NULL,
654                                         &d.err);
655         g_assert_no_error(d.err);
656
657         g_main_loop_run(d.mainloop);
658
659         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
660
661         g_main_loop_unref(d.mainloop);
662
663         g_source_remove(timer_id);
664         g_io_channel_unref(io);
665         g_source_remove(io_id);
666         g_obex_unref(obex);
667
668         g_assert_no_error(d.err);
669 }
670
671 static void test_get_req(void)
672 {
673         GIOChannel *io;
674         GIOCondition cond;
675         guint io_id, timer_id;
676         GObex *obex;
677         struct test_data d = { 0, NULL, {
678                                 { get_req_first, sizeof(get_req_first) },
679                                 { get_req_last, sizeof(get_req_last) } }, {
680                                 { get_rsp_first, sizeof(get_rsp_first) },
681                                 { get_rsp_last, sizeof(get_rsp_last) } } };
682
683         create_endpoints(&obex, &io, SOCK_STREAM);
684
685         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
686         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
687
688         d.mainloop = g_main_loop_new(NULL, FALSE);
689
690         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
691
692         g_obex_get_req(obex, rcv_data, transfer_complete, &d, &d.err,
693                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
694                                 G_OBEX_HDR_NAME, "file.txt",
695                                 G_OBEX_HDR_INVALID);
696         g_assert_no_error(d.err);
697
698         g_main_loop_run(d.mainloop);
699
700         g_assert_cmpuint(d.count, ==, 2);
701
702         g_main_loop_unref(d.mainloop);
703
704         g_source_remove(timer_id);
705         g_io_channel_unref(io);
706         g_source_remove(io_id);
707         g_obex_unref(obex);
708
709         g_assert_no_error(d.err);
710 }
711
712 static void test_stream_get_req(void)
713 {
714         GIOChannel *io;
715         GIOCondition cond;
716         guint io_id, timer_id;
717         GObex *obex;
718         struct test_data d = { 0, NULL, {
719                                 { get_req_first, sizeof(get_req_first) },
720                                 { NULL, 0 },
721                                 { NULL, 0 },
722                                 { get_req_last, sizeof(get_req_last) } }, {
723                                 { get_rsp_first, sizeof(get_rsp_first) },
724                                 { get_rsp_zero, sizeof(get_rsp_zero) },
725                                 { get_rsp_zero, sizeof(get_rsp_zero) },
726                                 { get_rsp_last, sizeof(get_rsp_last) } } };
727
728         create_endpoints(&obex, &io, SOCK_STREAM);
729
730         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
731         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
732
733         d.mainloop = g_main_loop_new(NULL, FALSE);
734
735         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
736
737         g_obex_get_req(obex, rcv_seq, transfer_complete, &d, &d.err,
738                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
739                                 G_OBEX_HDR_NAME, "file.txt",
740                                 G_OBEX_HDR_INVALID);
741         g_assert_no_error(d.err);
742
743         g_main_loop_run(d.mainloop);
744
745         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
746
747         g_main_loop_unref(d.mainloop);
748
749         g_source_remove(timer_id);
750         g_io_channel_unref(io);
751         g_source_remove(io_id);
752         g_obex_unref(obex);
753
754         g_assert_no_error(d.err);
755 }
756
757 static void test_packet_get_req(void)
758 {
759         GIOChannel *io;
760         GIOCondition cond;
761         guint io_id, timer_id;
762         GObex *obex;
763         struct test_data d = { 0, NULL, {
764                         { get_req_first_srm, sizeof(get_req_first_srm) },
765                         { NULL, -1 },
766                         { NULL, -1 },
767                         { get_req_last, sizeof(get_req_last) } }, {
768                         { get_rsp_first_srm, sizeof(get_rsp_first_srm) },
769                         { get_rsp_zero, sizeof(get_rsp_zero) },
770                         { get_rsp_zero, sizeof(get_rsp_zero) },
771                         { get_rsp_last, sizeof(get_rsp_last) } } };
772
773         create_endpoints(&obex, &io, SOCK_SEQPACKET);
774
775         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
776         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
777
778         d.mainloop = g_main_loop_new(NULL, FALSE);
779
780         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
781
782         g_obex_get_req(obex, rcv_seq, transfer_complete, &d, &d.err,
783                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
784                                 G_OBEX_HDR_NAME, "file.txt",
785                                 G_OBEX_HDR_INVALID);
786         g_assert_no_error(d.err);
787
788         g_main_loop_run(d.mainloop);
789
790         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
791
792         g_main_loop_unref(d.mainloop);
793
794         g_source_remove(timer_id);
795         g_io_channel_unref(io);
796         g_source_remove(io_id);
797         g_obex_unref(obex);
798
799         g_assert_no_error(d.err);
800 }
801
802 static void test_packet_get_req_wait(void)
803 {
804         GIOChannel *io;
805         GIOCondition cond;
806         guint io_id, timer_id;
807         GObex *obex;
808         struct test_data d = { 0, NULL, {
809                 { get_req_first_srm_wait, sizeof(get_req_first_srm_wait) },
810                 { get_req_last, sizeof(get_req_last) },
811                 { NULL, -1 },
812                 { get_req_last, sizeof(get_req_last) } }, {
813                 { get_rsp_first_srm, sizeof(get_rsp_first_srm) },
814                 { get_rsp_zero, sizeof(get_rsp_zero) },
815                 { get_rsp_zero, sizeof(get_rsp_zero) },
816                 { get_rsp_last, sizeof(get_rsp_last) } } };
817
818         create_endpoints(&obex, &io, SOCK_SEQPACKET);
819
820         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
821         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
822
823         d.mainloop = g_main_loop_new(NULL, FALSE);
824
825         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
826
827         g_obex_get_req(obex, rcv_seq, transfer_complete, &d, &d.err,
828                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
829                                 G_OBEX_HDR_NAME, "file.txt",
830                                 G_OBEX_HDR_SRMP, G_OBEX_SRMP_WAIT,
831                                 G_OBEX_HDR_INVALID);
832         g_assert_no_error(d.err);
833
834         g_main_loop_run(d.mainloop);
835
836         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
837
838         g_main_loop_unref(d.mainloop);
839
840         g_source_remove(timer_id);
841         g_io_channel_unref(io);
842         g_source_remove(io_id);
843         g_obex_unref(obex);
844
845         g_assert_no_error(d.err);
846 }
847
848 static void test_packet_get_req_wait_next(void)
849 {
850         GIOChannel *io;
851         GIOCondition cond;
852         guint io_id, timer_id;
853         GObex *obex;
854         struct test_data d = { 0, NULL, {
855                 { get_req_first_srm, sizeof(get_req_first_srm) },
856                 { get_req_last, sizeof(get_req_last) },
857                 { get_req_last, sizeof(get_req_last) },
858                 { get_req_last, sizeof(get_req_last) } }, {
859                 { get_rsp_first_srm_wait_next,
860                 sizeof(get_rsp_first_srm_wait_next) },
861                 { get_rsp_zero_wait_next, sizeof(get_rsp_zero_wait_next) },
862                 { get_rsp_zero_wait_next, sizeof(get_rsp_zero_wait_next) },
863                 { get_rsp_last, sizeof(get_rsp_last) } } };
864
865         create_endpoints(&obex, &io, SOCK_SEQPACKET);
866
867         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
868         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
869
870         d.mainloop = g_main_loop_new(NULL, FALSE);
871
872         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
873
874         g_obex_get_req(obex, rcv_seq, transfer_complete, &d, &d.err,
875                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
876                                 G_OBEX_HDR_NAME, "file.txt",
877                                 G_OBEX_HDR_INVALID);
878         g_assert_no_error(d.err);
879
880         g_main_loop_run(d.mainloop);
881
882         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
883
884         g_main_loop_unref(d.mainloop);
885
886         g_source_remove(timer_id);
887         g_io_channel_unref(io);
888         g_source_remove(io_id);
889         g_obex_unref(obex);
890
891         g_assert_no_error(d.err);
892 }
893
894 static void test_get_req_app(void)
895 {
896         GIOChannel *io;
897         GIOCondition cond;
898         guint io_id, timer_id;
899         GObex *obex;
900         struct test_data d = { 0, NULL, {
901                         { get_req_first_app, sizeof(get_req_first_app) },
902                         { get_req_last, sizeof(get_req_last) },
903                         { get_req_last, sizeof(get_req_last) } }, {
904                         { get_rsp_first_app, sizeof(get_rsp_first_app) },
905                         { get_rsp_first, sizeof(get_rsp_first) },
906                         { get_rsp_last, sizeof(get_rsp_last) } } };
907
908         create_endpoints(&obex, &io, SOCK_STREAM);
909
910         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
911         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
912
913         d.mainloop = g_main_loop_new(NULL, FALSE);
914
915         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
916
917         g_obex_get_req(obex, rcv_data, transfer_complete, &d, &d.err,
918                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
919                                 G_OBEX_HDR_NAME, "file.txt",
920                                 G_OBEX_HDR_APPARAM, hdr_app, sizeof(hdr_app),
921                                 G_OBEX_HDR_INVALID);
922         g_assert_no_error(d.err);
923
924         g_main_loop_run(d.mainloop);
925
926         g_assert_cmpuint(d.count, ==, 3);
927
928         g_main_loop_unref(d.mainloop);
929
930         g_source_remove(timer_id);
931         g_io_channel_unref(io);
932         g_source_remove(io_id);
933         g_obex_unref(obex);
934
935         g_assert_no_error(d.err);
936 }
937
938 static void handle_get_eagain(GObex *obex, GObexPacket *req,
939                                                 gpointer user_data)
940 {
941         struct test_data *d = user_data;
942         guint8 op = g_obex_packet_get_operation(req, NULL);
943         guint id;
944
945         if (op != G_OBEX_OP_GET) {
946                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
947                                         "Unexpected opcode 0x%02x", op);
948                 g_main_loop_quit(d->mainloop);
949                 return;
950         }
951
952         id = g_obex_get_rsp(obex, provide_eagain, transfer_complete, d,
953                                                 &d->err, G_OBEX_HDR_INVALID);
954         if (id == 0)
955                 g_main_loop_quit(d->mainloop);
956 }
957
958 static void handle_get(GObex *obex, GObexPacket *req, gpointer user_data)
959 {
960         struct test_data *d = user_data;
961         guint8 op = g_obex_packet_get_operation(req, NULL);
962         guint id;
963
964         if (op != G_OBEX_OP_GET) {
965                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
966                                         "Unexpected opcode 0x%02x", op);
967                 g_main_loop_quit(d->mainloop);
968                 return;
969         }
970
971         id = g_obex_get_rsp(obex, provide_data, transfer_complete, d, &d->err,
972                                                         G_OBEX_HDR_INVALID);
973         if (id == 0)
974                 g_main_loop_quit(d->mainloop);
975 }
976
977 static void test_stream_put_req(void)
978 {
979         GIOChannel *io;
980         GIOCondition cond;
981         guint io_id, timer_id;
982         GObex *obex;
983         struct test_data d = { 0, NULL, {
984                                 { NULL, 0 },
985                                 { NULL, 0 },
986                                 { NULL, 0 },
987                                 { put_req_last, sizeof(put_req_last) } }, {
988                                 { put_rsp_first, sizeof(put_rsp_first) },
989                                 { put_rsp_first, sizeof(put_rsp_first) },
990                                 { put_rsp_first, sizeof(put_rsp_first) },
991                                 { put_rsp_last, sizeof(put_rsp_last) } } };
992
993         create_endpoints(&obex, &io, SOCK_STREAM);
994         d.obex = obex;
995
996         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
997         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
998
999         d.mainloop = g_main_loop_new(NULL, FALSE);
1000
1001         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1002
1003         g_obex_put_req(obex, provide_seq, transfer_complete, &d, &d.err,
1004                                         G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1005                                         G_OBEX_HDR_NAME, "random.bin",
1006                                         G_OBEX_HDR_INVALID);
1007         g_assert_no_error(d.err);
1008
1009         g_main_loop_run(d.mainloop);
1010
1011         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
1012
1013         g_main_loop_unref(d.mainloop);
1014
1015         g_source_remove(timer_id);
1016         g_io_channel_unref(io);
1017         g_source_remove(io_id);
1018         g_obex_unref(obex);
1019
1020         g_assert_no_error(d.err);
1021 }
1022
1023 static void test_packet_put_req_wait(void)
1024 {
1025         GIOChannel *io;
1026         GIOCondition cond;
1027         guint io_id, timer_id;
1028         GObex *obex;
1029         struct test_data d = { 0, NULL, {
1030                 { NULL, 0 },
1031                 { NULL, 0 },
1032                 { NULL, 0 },
1033                 { put_req_last, sizeof(put_req_last) } }, {
1034                 { put_rsp_first_srm_wait, sizeof(put_rsp_first_srm_wait) },
1035                 { put_rsp_first, sizeof(put_rsp_first) },
1036                 { NULL, 0 },
1037                 { put_rsp_last, sizeof(put_rsp_last) } } };
1038
1039         create_endpoints(&obex, &io, SOCK_SEQPACKET);
1040         d.obex = obex;
1041
1042         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1043         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1044
1045         d.mainloop = g_main_loop_new(NULL, FALSE);
1046
1047         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1048
1049         g_obex_put_req(obex, provide_seq, transfer_complete, &d, &d.err,
1050                                         G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1051                                         G_OBEX_HDR_NAME, "random.bin",
1052                                         G_OBEX_HDR_INVALID);
1053         g_assert_no_error(d.err);
1054
1055         g_main_loop_run(d.mainloop);
1056
1057         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
1058
1059         g_main_loop_unref(d.mainloop);
1060
1061         g_source_remove(timer_id);
1062         g_io_channel_unref(io);
1063         g_source_remove(io_id);
1064         g_obex_unref(obex);
1065
1066         g_assert_no_error(d.err);
1067 }
1068
1069 static void test_packet_put_req(void)
1070 {
1071         GIOChannel *io;
1072         GIOCondition cond;
1073         guint io_id, timer_id;
1074         GObex *obex;
1075         struct test_data d = { 0, NULL, {
1076                         { NULL, 0 },
1077                         { NULL, 0 },
1078                         { NULL, 0 },
1079                         { put_req_last, sizeof(put_req_last) } }, {
1080                         { put_rsp_first_srm, sizeof(put_rsp_first_srm) },
1081                         { NULL, 0 },
1082                         { NULL, 0 },
1083                         { put_rsp_last, sizeof(put_rsp_last) } } };
1084
1085         create_endpoints(&obex, &io, SOCK_SEQPACKET);
1086         d.obex = obex;
1087
1088         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1089         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1090
1091         d.mainloop = g_main_loop_new(NULL, FALSE);
1092
1093         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1094
1095         g_obex_put_req(obex, provide_seq, transfer_complete, &d, &d.err,
1096                                         G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1097                                         G_OBEX_HDR_NAME, "random.bin",
1098                                         G_OBEX_HDR_INVALID);
1099         g_assert_no_error(d.err);
1100
1101         g_main_loop_run(d.mainloop);
1102
1103         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
1104
1105         g_main_loop_unref(d.mainloop);
1106
1107         g_source_remove(timer_id);
1108         g_io_channel_unref(io);
1109         g_source_remove(io_id);
1110         g_obex_unref(obex);
1111
1112         g_assert_no_error(d.err);
1113 }
1114
1115 static void test_put_req_eagain(void)
1116 {
1117         GIOChannel *io;
1118         GIOCondition cond;
1119         guint io_id, timer_id;
1120         GObex *obex;
1121         struct test_data d = { 0, NULL, {
1122                                 { put_req_first, sizeof(put_req_first) },
1123                                 { put_req_last, sizeof(put_req_last) } }, {
1124                                 { put_rsp_first, sizeof(put_rsp_first) },
1125                                 { put_rsp_last, sizeof(put_rsp_last) } } };
1126
1127         create_endpoints(&obex, &io, SOCK_STREAM);
1128         d.obex = obex;
1129         d.provide_delay = 200;
1130
1131         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1132         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1133
1134         d.mainloop = g_main_loop_new(NULL, FALSE);
1135
1136         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1137
1138         g_obex_put_req(obex, provide_eagain, transfer_complete, &d, &d.err,
1139                                         G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1140                                         G_OBEX_HDR_NAME, "file.txt",
1141                                         G_OBEX_HDR_INVALID);
1142         g_assert_no_error(d.err);
1143
1144         g_main_loop_run(d.mainloop);
1145
1146         g_assert_cmpuint(d.count, ==, 2);
1147
1148         g_main_loop_unref(d.mainloop);
1149
1150         g_source_remove(timer_id);
1151         g_io_channel_unref(io);
1152         g_source_remove(io_id);
1153         g_obex_unref(obex);
1154
1155         g_assert_no_error(d.err);
1156 }
1157
1158 static void test_get_rsp(void)
1159 {
1160         GIOChannel *io;
1161         GIOCondition cond;
1162         guint io_id, timer_id;
1163         GObex *obex;
1164         struct test_data d = { 0, NULL, {
1165                                 { get_rsp_first, sizeof(get_rsp_first) },
1166                                 { get_rsp_last, sizeof(get_rsp_last) } }, {
1167                                 { get_req_last, sizeof(get_req_last) },
1168                                 { NULL, 0 } } };
1169
1170         create_endpoints(&obex, &io, SOCK_STREAM);
1171
1172         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1173         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1174
1175         d.mainloop = g_main_loop_new(NULL, FALSE);
1176
1177         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1178
1179         g_obex_add_request_function(obex, G_OBEX_OP_GET, handle_get, &d);
1180
1181         g_io_channel_write_chars(io, (char *) get_req_first,
1182                                         sizeof(get_req_first), NULL, &d.err);
1183         g_assert_no_error(d.err);
1184
1185         g_main_loop_run(d.mainloop);
1186
1187         g_assert_cmpuint(d.count, ==, 1);
1188
1189         g_main_loop_unref(d.mainloop);
1190
1191         g_source_remove(timer_id);
1192         g_io_channel_unref(io);
1193         g_source_remove(io_id);
1194         g_obex_unref(obex);
1195
1196         g_assert_no_error(d.err);
1197 }
1198
1199 static void handle_get_seq(GObex *obex, GObexPacket *req,
1200                                                         gpointer user_data)
1201 {
1202         struct test_data *d = user_data;
1203         guint8 op = g_obex_packet_get_operation(req, NULL);
1204         guint id;
1205
1206         if (op != G_OBEX_OP_GET) {
1207                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
1208                                         "Unexpected opcode 0x%02x", op);
1209                 g_main_loop_quit(d->mainloop);
1210                 return;
1211         }
1212
1213         id = g_obex_get_rsp(obex, provide_seq, transfer_complete, d,
1214                                                 &d->err, G_OBEX_HDR_INVALID);
1215         if (id == 0)
1216                 g_main_loop_quit(d->mainloop);
1217 }
1218
1219 static void test_stream_get_rsp(void)
1220 {
1221         GIOChannel *io;
1222         GIOCondition cond;
1223         guint io_id, timer_id;
1224         GObex *obex;
1225         struct test_data d = { 0, NULL, {
1226                                 { NULL, 0 },
1227                                 { NULL, 0 },
1228                                 { NULL, 0 },
1229                                 { get_rsp_last, sizeof(get_rsp_last) } }, {
1230                                 { get_req_last, sizeof(get_req_last) },
1231                                 { get_req_last, sizeof(get_req_last) },
1232                                 { get_req_last, sizeof(get_req_last) } } };
1233
1234         create_endpoints(&obex, &io, SOCK_STREAM);
1235
1236         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1237         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1238
1239         d.mainloop = g_main_loop_new(NULL, FALSE);
1240
1241         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1242
1243         g_obex_add_request_function(obex, G_OBEX_OP_GET, handle_get_seq, &d);
1244
1245         g_io_channel_write_chars(io, (char *) get_req_first,
1246                                         sizeof(get_req_first), NULL, &d.err);
1247         g_assert_no_error(d.err);
1248
1249         g_main_loop_run(d.mainloop);
1250
1251         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS - 1);
1252
1253         g_main_loop_unref(d.mainloop);
1254
1255         g_source_remove(timer_id);
1256         g_io_channel_unref(io);
1257         g_source_remove(io_id);
1258         g_obex_unref(obex);
1259
1260         g_assert_no_error(d.err);
1261 }
1262
1263 static void test_packet_get_rsp(void)
1264 {
1265         GIOChannel *io;
1266         GIOCondition cond;
1267         guint io_id, timer_id;
1268         GObex *obex;
1269         struct test_data d = { 0, NULL, {
1270                                 { NULL, 0 },
1271                                 { NULL, 0 },
1272                                 { NULL, 0 },
1273                                 { get_rsp_last, sizeof(get_rsp_last) } }, {
1274                                 { NULL, 0 },
1275                                 { NULL, 0 },
1276                                 { get_req_last, sizeof(get_req_last) } } };
1277
1278         create_endpoints(&obex, &io, SOCK_SEQPACKET);
1279
1280         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1281         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1282
1283         d.mainloop = g_main_loop_new(NULL, FALSE);
1284
1285         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1286
1287         g_obex_add_request_function(obex, G_OBEX_OP_GET, handle_get_seq, &d);
1288
1289         g_io_channel_write_chars(io, (char *) get_req_first_srm,
1290                                         sizeof(get_req_first_srm), NULL,
1291                                         &d.err);
1292         g_assert_no_error(d.err);
1293
1294         g_main_loop_run(d.mainloop);
1295
1296         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS - 1);
1297
1298         g_main_loop_unref(d.mainloop);
1299
1300         g_source_remove(timer_id);
1301         g_io_channel_unref(io);
1302         g_source_remove(io_id);
1303         g_obex_unref(obex);
1304
1305         g_assert_no_error(d.err);
1306 }
1307
1308 static void handle_get_seq_srm_wait(GObex *obex, GObexPacket *req,
1309                                                         gpointer user_data)
1310 {
1311         struct test_data *d = user_data;
1312         guint8 op = g_obex_packet_get_operation(req, NULL);
1313         guint id;
1314
1315         if (op != G_OBEX_OP_GET) {
1316                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
1317                                         "Unexpected opcode 0x%02x", op);
1318                 g_main_loop_quit(d->mainloop);
1319                 return;
1320         }
1321
1322         id = g_obex_get_rsp(obex, provide_seq, transfer_complete, d,
1323                                         &d->err,
1324                                         G_OBEX_HDR_SRMP, G_OBEX_SRMP_WAIT,
1325                                         G_OBEX_HDR_INVALID);
1326         if (id == 0)
1327                 g_main_loop_quit(d->mainloop);
1328 }
1329
1330 static void test_packet_get_rsp_wait(void)
1331 {
1332         GIOChannel *io;
1333         GIOCondition cond;
1334         guint io_id, timer_id;
1335         GObex *obex;
1336         struct test_data d = { 0, NULL, {
1337                                 { NULL, 0 },
1338                                 { NULL, 0 },
1339                                 { NULL, 0 },
1340                                 { get_rsp_last, sizeof(get_rsp_last) } }, {
1341                                 { get_req_last, sizeof(get_req_last) },
1342                                 { NULL, 0 },
1343                                 { get_req_last, sizeof(get_req_last) } } };
1344
1345         create_endpoints(&obex, &io, SOCK_SEQPACKET);
1346
1347         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1348         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1349
1350         d.mainloop = g_main_loop_new(NULL, FALSE);
1351
1352         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1353
1354         g_obex_add_request_function(obex, G_OBEX_OP_GET,
1355                                         handle_get_seq_srm_wait, &d);
1356
1357         g_io_channel_write_chars(io, (char *) get_req_first_srm,
1358                                         sizeof(get_req_first_srm), NULL,
1359                                         &d.err);
1360         g_assert_no_error(d.err);
1361
1362         g_main_loop_run(d.mainloop);
1363
1364         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS - 1);
1365
1366         g_main_loop_unref(d.mainloop);
1367
1368         g_source_remove(timer_id);
1369         g_io_channel_unref(io);
1370         g_source_remove(io_id);
1371         g_obex_unref(obex);
1372
1373         g_assert_no_error(d.err);
1374 }
1375
1376 static void handle_get_app(GObex *obex, GObexPacket *req, gpointer user_data)
1377 {
1378         struct test_data *d = user_data;
1379         guint8 op = g_obex_packet_get_operation(req, NULL);
1380         GObexPacket *rsp;
1381
1382         if (op != G_OBEX_OP_GET) {
1383                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
1384                                         "Unexpected opcode 0x%02x", op);
1385                 g_main_loop_quit(d->mainloop);
1386                 return;
1387         }
1388
1389         g_obex_add_request_function(d->obex, G_OBEX_OP_GET, handle_get, d);
1390
1391         rsp = g_obex_packet_new(G_OBEX_RSP_CONTINUE, TRUE,
1392                                 G_OBEX_HDR_APPARAM, hdr_app, sizeof(hdr_app),
1393                                 G_OBEX_HDR_INVALID);
1394
1395         if (g_obex_send(d->obex, rsp, NULL) == FALSE)
1396                 g_main_loop_quit(d->mainloop);
1397 }
1398
1399 static void test_get_rsp_app(void)
1400 {
1401         GIOChannel *io;
1402         GIOCondition cond;
1403         guint io_id, timer_id;
1404         GObex *obex;
1405         struct test_data d = { 0, NULL, {
1406                         { get_rsp_first_app, sizeof(get_rsp_first_app) },
1407                         { get_rsp_first, sizeof(get_rsp_first) },
1408                         { get_rsp_last, sizeof(get_rsp_last) } }, {
1409                         { get_req_first, sizeof(get_req_first) },
1410                         { get_req_last, sizeof(get_req_last) },
1411                         { NULL, 0 } } };
1412
1413         create_endpoints(&obex, &io, SOCK_STREAM);
1414         d.obex = obex;
1415
1416         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1417         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1418
1419         d.mainloop = g_main_loop_new(NULL, FALSE);
1420
1421         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1422
1423         g_obex_add_request_function(obex, G_OBEX_OP_GET, handle_get_app, &d);
1424
1425         g_io_channel_write_chars(io, (char *) get_req_first_app,
1426                                         sizeof(get_req_first_app), NULL, &d.err);
1427         g_assert_no_error(d.err);
1428
1429         g_main_loop_run(d.mainloop);
1430
1431         g_assert_cmpuint(d.count, ==, 2);
1432
1433         g_main_loop_unref(d.mainloop);
1434
1435         g_source_remove(timer_id);
1436         g_io_channel_unref(io);
1437         g_source_remove(io_id);
1438         g_obex_unref(obex);
1439
1440         g_assert_no_error(d.err);
1441 }
1442
1443 static void test_put_req_delay(void)
1444 {
1445         GIOChannel *io;
1446         GIOCondition cond;
1447         guint io_id, timer_id;
1448         GObex *obex;
1449         struct test_data d = { 0, NULL, {
1450                                 { put_req_first, sizeof(put_req_first) },
1451                                 { put_req_last, sizeof(put_req_last) } }, {
1452                                 { put_rsp_first, sizeof(put_rsp_first) },
1453                                 { put_rsp_last, sizeof(put_rsp_last) } } };
1454
1455         create_endpoints(&obex, &io, SOCK_STREAM);
1456         d.obex = obex;
1457         d.provide_delay = 200;
1458
1459         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1460         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1461
1462         d.mainloop = g_main_loop_new(NULL, FALSE);
1463
1464         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1465
1466         g_obex_put_req(obex, provide_data, transfer_complete, &d, &d.err,
1467                                         G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1468                                         G_OBEX_HDR_NAME, "file.txt",
1469                                         G_OBEX_HDR_INVALID);
1470         g_assert_no_error(d.err);
1471
1472         g_main_loop_run(d.mainloop);
1473
1474         g_assert_cmpuint(d.count, ==, 2);
1475
1476         g_main_loop_unref(d.mainloop);
1477
1478         g_source_remove(timer_id);
1479         g_io_channel_unref(io);
1480         g_source_remove(io_id);
1481         g_obex_unref(obex);
1482
1483         g_assert_no_error(d.err);
1484 }
1485
1486 static void test_get_rsp_delay(void)
1487 {
1488         GIOChannel *io;
1489         GIOCondition cond;
1490         guint io_id, timer_id;
1491         GObex *obex;
1492         struct test_data d = { 0, NULL, {
1493                                 { get_rsp_first, sizeof(get_rsp_first) },
1494                                 { get_rsp_last, sizeof(get_rsp_last) } }, {
1495                                 { get_req_last, sizeof(get_req_last) },
1496                                 { NULL, 0 } } };
1497
1498         create_endpoints(&obex, &io, SOCK_STREAM);
1499         d.obex = obex;
1500         d.provide_delay = 200;
1501
1502         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1503         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1504
1505         d.mainloop = g_main_loop_new(NULL, FALSE);
1506
1507         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1508
1509         g_obex_add_request_function(obex, G_OBEX_OP_GET, handle_get, &d);
1510
1511         g_io_channel_write_chars(io, (char *) get_req_first,
1512                                         sizeof(get_req_first), NULL, &d.err);
1513         g_assert_no_error(d.err);
1514
1515         g_main_loop_run(d.mainloop);
1516
1517         g_assert_cmpuint(d.count, ==, 1);
1518
1519         g_main_loop_unref(d.mainloop);
1520
1521         g_source_remove(timer_id);
1522         g_io_channel_unref(io);
1523         g_source_remove(io_id);
1524         g_obex_unref(obex);
1525
1526         g_assert_no_error(d.err);
1527 }
1528
1529 static gboolean rcv_data_delay(const void *buf, gsize len, gpointer user_data)
1530 {
1531         struct test_data *d = user_data;
1532
1533         if (len != sizeof(body_data))
1534                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
1535                                         "Unexpected byte count %zu", len);
1536
1537         if (memcmp(buf, body_data, sizeof(body_data)) != 0) {
1538                 dump_bufs(body_data, sizeof(body_data), buf, len);
1539                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
1540                                         "Unexpected byte count %zu", len);
1541         }
1542
1543         if (d->provide_delay > 0) {
1544                 g_obex_suspend(d->obex);
1545                 g_timeout_add(d->provide_delay, resume_obex, d->obex);
1546         }
1547
1548         return TRUE;
1549 }
1550
1551 static void handle_put_delay(GObex *obex, GObexPacket *req, gpointer user_data)
1552 {
1553         struct test_data *d = user_data;
1554         guint8 op = g_obex_packet_get_operation(req, NULL);
1555         guint id;
1556
1557         if (op != G_OBEX_OP_PUT) {
1558                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
1559                                         "Unexpected opcode 0x%02x", op);
1560                 g_main_loop_quit(d->mainloop);
1561                 return;
1562         }
1563
1564         id = g_obex_put_rsp(obex, req, rcv_data_delay, transfer_complete, d,
1565                                                 &d->err, G_OBEX_HDR_INVALID);
1566         if (id == 0)
1567                 g_main_loop_quit(d->mainloop);
1568 }
1569
1570 static void test_put_rsp_delay(void)
1571 {
1572         GIOChannel *io;
1573         GIOCondition cond;
1574         guint io_id, timer_id;
1575         GObex *obex;
1576         struct test_data d = { 0, NULL, {
1577                                 { put_rsp_first, sizeof(put_rsp_first) },
1578                                 { put_rsp_last, sizeof(put_rsp_last) } }, {
1579                                 { put_req_last, sizeof(put_req_last) },
1580                                 { NULL, 0 } } };
1581
1582         create_endpoints(&obex, &io, SOCK_STREAM);
1583         d.obex = obex;
1584         d.provide_delay = 200;
1585
1586         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1587         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1588
1589         d.mainloop = g_main_loop_new(NULL, FALSE);
1590
1591         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1592
1593         g_obex_add_request_function(obex, G_OBEX_OP_PUT, handle_put_delay, &d);
1594
1595         g_io_channel_write_chars(io, (char *) put_req_first,
1596                                         sizeof(put_req_first), NULL, &d.err);
1597         g_assert_no_error(d.err);
1598
1599         g_main_loop_run(d.mainloop);
1600
1601         g_assert_cmpuint(d.count, ==, 1);
1602
1603         g_main_loop_unref(d.mainloop);
1604
1605         g_source_remove(timer_id);
1606         g_io_channel_unref(io);
1607         g_source_remove(io_id);
1608         g_obex_unref(obex);
1609
1610         g_assert_no_error(d.err);
1611 }
1612
1613 static void test_get_req_delay(void)
1614 {
1615         GIOChannel *io;
1616         GIOCondition cond;
1617         guint io_id, timer_id;
1618         GObex *obex;
1619         struct test_data d = { 0, NULL, {
1620                                 { get_req_first, sizeof(get_req_first) },
1621                                 { get_req_last, sizeof(get_req_last) } }, {
1622                                 { get_rsp_first, sizeof(get_rsp_first) },
1623                                 { get_rsp_last, sizeof(get_rsp_last) } } };
1624
1625         create_endpoints(&obex, &io, SOCK_STREAM);
1626         d.obex = obex;
1627         d.provide_delay = 200;
1628
1629         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1630         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1631
1632         d.mainloop = g_main_loop_new(NULL, FALSE);
1633
1634         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1635
1636         g_obex_get_req(obex, rcv_data_delay, transfer_complete, &d, &d.err,
1637                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1638                                 G_OBEX_HDR_NAME, "file.txt",
1639                                 G_OBEX_HDR_INVALID);
1640         g_assert_no_error(d.err);
1641
1642         g_main_loop_run(d.mainloop);
1643
1644         g_assert_cmpuint(d.count, ==, 2);
1645
1646         g_main_loop_unref(d.mainloop);
1647
1648         g_source_remove(timer_id);
1649         g_io_channel_unref(io);
1650         g_source_remove(io_id);
1651         g_obex_unref(obex);
1652
1653         g_assert_no_error(d.err);
1654 }
1655
1656 static void test_get_rsp_eagain(void)
1657 {
1658         GIOChannel *io;
1659         GIOCondition cond;
1660         guint io_id, timer_id;
1661         GObex *obex;
1662         struct test_data d = { 0, NULL, {
1663                                 { get_rsp_first, sizeof(get_rsp_first) },
1664                                 { get_rsp_last, sizeof(get_rsp_last) } }, {
1665                                 { get_req_last, sizeof(get_req_last) },
1666                                 { NULL, 0 } } };
1667
1668         create_endpoints(&obex, &io, SOCK_STREAM);
1669         d.obex = obex;
1670         d.provide_delay = 200;
1671
1672         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1673         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1674
1675         d.mainloop = g_main_loop_new(NULL, FALSE);
1676
1677         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1678
1679         g_obex_add_request_function(obex, G_OBEX_OP_GET, handle_get_eagain,
1680                                                                         &d);
1681
1682         g_io_channel_write_chars(io, (char *) get_req_first,
1683                                         sizeof(get_req_first), NULL, &d.err);
1684         g_assert_no_error(d.err);
1685
1686         g_main_loop_run(d.mainloop);
1687
1688         g_assert_cmpuint(d.count, ==, 1);
1689
1690         g_main_loop_unref(d.mainloop);
1691
1692         g_source_remove(timer_id);
1693         g_io_channel_unref(io);
1694         g_source_remove(io_id);
1695         g_obex_unref(obex);
1696
1697         g_assert_no_error(d.err);
1698 }
1699
1700 static void conn_complete(GObex *obex, GError *err, GObexPacket *rsp,
1701                                                         gpointer user_data)
1702 {
1703         struct test_data *d = user_data;
1704
1705         if (err != NULL)
1706                 d->err = g_error_copy(err);
1707
1708         g_main_loop_quit(d->mainloop);
1709 }
1710
1711 static void test_conn_req(void)
1712 {
1713         GIOChannel *io;
1714         GIOCondition cond;
1715         guint io_id, timer_id;
1716         GObex *obex;
1717         struct test_data d = { 0, NULL, {
1718                                 { conn_req, sizeof(conn_req) } }, {
1719                                 { conn_rsp, sizeof(conn_rsp) } } };
1720
1721         create_endpoints(&obex, &io, SOCK_STREAM);
1722         d.obex = obex;
1723
1724         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1725         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1726
1727         d.mainloop = g_main_loop_new(NULL, FALSE);
1728
1729         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1730
1731         g_obex_connect(obex, conn_complete, &d, &d.err, G_OBEX_HDR_INVALID);
1732         g_assert_no_error(d.err);
1733
1734         g_main_loop_run(d.mainloop);
1735
1736         g_assert_cmpuint(d.count, ==, 1);
1737
1738         g_main_loop_unref(d.mainloop);
1739
1740         g_source_remove(timer_id);
1741         g_io_channel_unref(io);
1742         g_source_remove(io_id);
1743         g_obex_unref(obex);
1744
1745         g_assert_no_error(d.err);
1746 }
1747
1748 static void handle_conn_rsp(GObex *obex, GObexPacket *req,
1749                                                 gpointer user_data)
1750 {
1751         struct test_data *d = user_data;
1752         guint8 op = g_obex_packet_get_operation(req, NULL);
1753         GObexPacket *rsp;
1754
1755         if (op != G_OBEX_OP_CONNECT) {
1756                 d->err = g_error_new(TEST_ERROR, TEST_ERROR_UNEXPECTED,
1757                                         "Unexpected opcode 0x%02x", op);
1758                 g_main_loop_quit(d->mainloop);
1759                 return;
1760         }
1761
1762         rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE,
1763                                                 G_OBEX_HDR_CONNECTION, 1,
1764                                                 G_OBEX_HDR_INVALID);
1765         g_obex_send(obex, rsp, &d->err);
1766 }
1767
1768 static void test_conn_rsp(void)
1769 {
1770         GIOChannel *io;
1771         GIOCondition cond;
1772         guint io_id, timer_id;
1773         GObex *obex;
1774         struct test_data d = { 0, NULL, {
1775                         { conn_rsp, sizeof(conn_rsp) } }, {
1776                         { NULL, -1 } } };
1777
1778         create_endpoints(&obex, &io, SOCK_STREAM);
1779         d.obex = obex;
1780
1781         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1782         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1783
1784         d.mainloop = g_main_loop_new(NULL, FALSE);
1785
1786         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1787
1788         g_obex_add_request_function(obex, G_OBEX_OP_CONNECT,
1789                                                 handle_conn_rsp, &d);
1790
1791         g_io_channel_write_chars(io, (char *) conn_req, sizeof(conn_req),
1792                                                                 NULL, &d.err);
1793         g_assert_no_error(d.err);
1794
1795         g_main_loop_run(d.mainloop);
1796
1797         g_assert_cmpuint(d.count, ==, 1);
1798
1799         g_main_loop_unref(d.mainloop);
1800
1801         g_source_remove(timer_id);
1802         g_io_channel_unref(io);
1803         g_source_remove(io_id);
1804         g_obex_unref(obex);
1805
1806         g_assert_no_error(d.err);
1807 }
1808
1809 static void conn_complete_get_req(GObex *obex, GError *err, GObexPacket *rsp,
1810                                                         gpointer user_data)
1811 {
1812         struct test_data *d = user_data;
1813
1814         if (err != NULL) {
1815                 d->err = g_error_copy(err);
1816                 g_main_loop_quit(d->mainloop);
1817         }
1818
1819         g_obex_get_req(obex, rcv_data, transfer_complete, d, &d->err,
1820                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1821                                 G_OBEX_HDR_NAME, "file.txt",
1822                                 G_OBEX_HDR_INVALID);
1823 }
1824
1825 static void test_conn_get_req(void)
1826 {
1827         GIOChannel *io;
1828         GIOCondition cond;
1829         guint io_id, timer_id;
1830         GObex *obex;
1831         struct test_data d = { 0, NULL, {
1832                         { conn_req, sizeof(conn_req) },
1833                         { conn_get_req_first, sizeof(conn_get_req_first) },
1834                         { get_req_last, sizeof(get_req_last) }}, {
1835                         { conn_rsp, sizeof(conn_rsp) } ,
1836                         { get_rsp_first, sizeof(get_rsp_first) },
1837                         { get_rsp_last, sizeof(get_rsp_last) } } };
1838
1839         create_endpoints(&obex, &io, SOCK_STREAM);
1840         d.obex = obex;
1841
1842         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1843         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1844
1845         d.mainloop = g_main_loop_new(NULL, FALSE);
1846
1847         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1848
1849         g_obex_connect(obex, conn_complete_get_req, &d, &d.err,
1850                                                         G_OBEX_HDR_INVALID);
1851         g_assert_no_error(d.err);
1852
1853         g_main_loop_run(d.mainloop);
1854
1855         g_assert_cmpuint(d.count, ==, 3);
1856
1857         g_main_loop_unref(d.mainloop);
1858
1859         g_source_remove(timer_id);
1860         g_io_channel_unref(io);
1861         g_source_remove(io_id);
1862         g_obex_unref(obex);
1863
1864         g_assert_no_error(d.err);
1865 }
1866
1867 static void test_conn_get_rsp(void)
1868 {
1869         GIOChannel *io;
1870         GIOCondition cond;
1871         guint io_id, timer_id;
1872         GObex *obex;
1873         struct test_data d = { 0, NULL, {
1874                         { conn_rsp, sizeof(conn_rsp) },
1875                         { get_rsp_first, sizeof(get_rsp_first) },
1876                         { get_rsp_last, sizeof(get_rsp_last) } }, {
1877                         { conn_get_req_first, sizeof(conn_get_req_first) },
1878                         { get_req_last, sizeof(get_req_last) },
1879                         { NULL, 0 } } };
1880
1881         create_endpoints(&obex, &io, SOCK_STREAM);
1882         d.obex = obex;
1883
1884         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1885         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1886
1887         d.mainloop = g_main_loop_new(NULL, FALSE);
1888
1889         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1890
1891         g_obex_add_request_function(obex, G_OBEX_OP_CONNECT,
1892                                                 handle_conn_rsp, &d);
1893
1894         g_obex_add_request_function(obex, G_OBEX_OP_GET,
1895                                                 handle_get, &d);
1896
1897         g_io_channel_write_chars(io, (char *) conn_req, sizeof(conn_req),
1898                                                                 NULL, &d.err);
1899         g_assert_no_error(d.err);
1900
1901         g_main_loop_run(d.mainloop);
1902
1903         g_assert_cmpuint(d.count, ==, 2);
1904
1905         g_main_loop_unref(d.mainloop);
1906
1907         g_source_remove(timer_id);
1908         g_io_channel_unref(io);
1909         g_source_remove(io_id);
1910         g_obex_unref(obex);
1911
1912         g_assert_no_error(d.err);
1913 }
1914
1915 static void conn_complete_put_req(GObex *obex, GError *err, GObexPacket *rsp,
1916                                                         gpointer user_data)
1917 {
1918         struct test_data *d = user_data;
1919
1920         if (err != NULL) {
1921                 d->err = g_error_copy(err);
1922                 g_main_loop_quit(d->mainloop);
1923         }
1924
1925         g_obex_put_req(obex, provide_data, transfer_complete, d, &d->err,
1926                                 G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
1927                                 G_OBEX_HDR_NAME, "file.txt",
1928                                 G_OBEX_HDR_INVALID);
1929 }
1930
1931 static void test_conn_put_req(void)
1932 {
1933         GIOChannel *io;
1934         GIOCondition cond;
1935         guint io_id, timer_id;
1936         GObex *obex;
1937         struct test_data d = { 0, NULL, {
1938                         { conn_req, sizeof(conn_req) },
1939                         { conn_put_req_first, sizeof(conn_put_req_first) },
1940                         { put_req_last, sizeof(put_req_last) }}, {
1941                         { conn_rsp, sizeof(conn_rsp) } ,
1942                         { put_rsp_first, sizeof(put_rsp_first) },
1943                         { put_rsp_last, sizeof(put_rsp_last) } } };
1944
1945         create_endpoints(&obex, &io, SOCK_STREAM);
1946         d.obex = obex;
1947
1948         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1949         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1950
1951         d.mainloop = g_main_loop_new(NULL, FALSE);
1952
1953         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1954
1955         g_obex_connect(obex, conn_complete_put_req, &d, &d.err,
1956                                                         G_OBEX_HDR_INVALID);
1957         g_assert_no_error(d.err);
1958
1959         g_main_loop_run(d.mainloop);
1960
1961         g_assert_cmpuint(d.count, ==, 3);
1962
1963         g_main_loop_unref(d.mainloop);
1964
1965         g_source_remove(timer_id);
1966         g_io_channel_unref(io);
1967         g_source_remove(io_id);
1968         g_obex_unref(obex);
1969
1970         g_assert_no_error(d.err);
1971 }
1972
1973 static void test_conn_put_rsp(void)
1974 {
1975         GIOChannel *io;
1976         GIOCondition cond;
1977         guint io_id, timer_id;
1978         GObex *obex;
1979         struct test_data d = { 0, NULL, {
1980                         { conn_rsp, sizeof(conn_rsp) },
1981                         { put_rsp_first, sizeof(put_rsp_first) },
1982                         { put_rsp_last, sizeof(put_rsp_last) } }, {
1983                         { conn_put_req_first, sizeof(conn_put_req_first) },
1984                         { put_req_last, sizeof(put_req_last) },
1985                         { NULL, 0 } } };
1986
1987         create_endpoints(&obex, &io, SOCK_STREAM);
1988         d.obex = obex;
1989
1990         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1991         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
1992
1993         d.mainloop = g_main_loop_new(NULL, FALSE);
1994
1995         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
1996
1997         g_obex_add_request_function(obex, G_OBEX_OP_CONNECT,
1998                                                 handle_conn_rsp, &d);
1999
2000         g_obex_add_request_function(obex, G_OBEX_OP_PUT,
2001                                                 handle_put, &d);
2002
2003         g_io_channel_write_chars(io, (char *) conn_req, sizeof(conn_req),
2004                                                                 NULL, &d.err);
2005         g_assert_no_error(d.err);
2006
2007         g_main_loop_run(d.mainloop);
2008
2009         g_assert_cmpuint(d.count, ==, 2);
2010
2011         g_main_loop_unref(d.mainloop);
2012
2013         g_source_remove(timer_id);
2014         g_io_channel_unref(io);
2015         g_source_remove(io_id);
2016         g_obex_unref(obex);
2017
2018         g_assert_no_error(d.err);
2019 }
2020
2021 static void test_conn_get_wrg_rsp(void)
2022 {
2023         GIOChannel *io;
2024         GIOCondition cond;
2025         guint io_id, timer_id;
2026         GObex *obex;
2027         struct test_data d = { 0, NULL, {
2028                         { conn_rsp, sizeof(conn_rsp) },
2029                         { unavailable_rsp, sizeof(unavailable_rsp) } }, {
2030                         { conn_get_req_wrg, sizeof(conn_get_req_wrg) },
2031                         { NULL, -1 } } };
2032
2033         create_endpoints(&obex, &io, SOCK_STREAM);
2034         d.obex = obex;
2035
2036         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
2037         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
2038
2039         d.mainloop = g_main_loop_new(NULL, FALSE);
2040
2041         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
2042
2043         g_obex_add_request_function(obex, G_OBEX_OP_CONNECT,
2044                                                 handle_conn_rsp, &d);
2045
2046         g_io_channel_write_chars(io, (char *) conn_req, sizeof(conn_req),
2047                                                                 NULL, &d.err);
2048         g_assert_no_error(d.err);
2049
2050         g_main_loop_run(d.mainloop);
2051
2052         g_assert_cmpuint(d.count, ==, 2);
2053
2054         g_main_loop_unref(d.mainloop);
2055
2056         g_source_remove(timer_id);
2057         g_io_channel_unref(io);
2058         g_source_remove(io_id);
2059         g_obex_unref(obex);
2060
2061         g_assert_no_error(d.err);
2062 }
2063
2064 static void conn_complete_put_req_seq(GObex *obex, GError *err,
2065                                         GObexPacket *rsp, gpointer user_data)
2066 {
2067         struct test_data *d = user_data;
2068
2069         if (err != NULL) {
2070                 d->err = g_error_copy(err);
2071                 g_main_loop_quit(d->mainloop);
2072         }
2073
2074         g_obex_put_req(obex, provide_seq, transfer_complete, d, &d->err,
2075                                         G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
2076                                         G_OBEX_HDR_NAME, "random.bin",
2077                                         G_OBEX_HDR_INVALID);
2078 }
2079
2080 static void test_conn_put_req_seq(void)
2081 {
2082         GIOChannel *io;
2083         GIOCondition cond;
2084         guint io_id, timer_id;
2085         GObex *obex;
2086         struct test_data d = { 0, NULL, {
2087                                 { conn_req, sizeof(conn_req) } ,
2088                                 { NULL, 0 },
2089                                 { NULL, 0 },
2090                                 { put_req_last, sizeof(put_req_last) } }, {
2091                                 { conn_rsp, sizeof(conn_rsp) } ,
2092                                 { put_rsp_first, sizeof(put_rsp_first) },
2093                                 { put_rsp_first, sizeof(put_rsp_first) },
2094                                 { put_rsp_last, sizeof(put_rsp_last) } } };
2095
2096         create_endpoints(&obex, &io, SOCK_STREAM);
2097         d.obex = obex;
2098
2099         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
2100         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
2101
2102         d.mainloop = g_main_loop_new(NULL, FALSE);
2103
2104         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
2105
2106         g_obex_connect(obex, conn_complete_put_req_seq, &d, &d.err,
2107                                                         G_OBEX_HDR_INVALID);
2108         g_assert_no_error(d.err);
2109
2110         g_main_loop_run(d.mainloop);
2111
2112         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
2113
2114         g_main_loop_unref(d.mainloop);
2115
2116         g_source_remove(timer_id);
2117         g_io_channel_unref(io);
2118         g_source_remove(io_id);
2119         g_obex_unref(obex);
2120
2121         g_assert_no_error(d.err);
2122 }
2123
2124 static void conn_complete_put_req_seq_srm(GObex *obex, GError *err,
2125                                         GObexPacket *rsp, gpointer user_data)
2126 {
2127         struct test_data *d = user_data;
2128
2129         if (err != NULL) {
2130                 d->err = g_error_copy(err);
2131                 g_main_loop_quit(d->mainloop);
2132         }
2133
2134         g_obex_put_req(obex, provide_seq, transfer_complete, d, &d->err,
2135                                         G_OBEX_HDR_TYPE, hdr_type, sizeof(hdr_type),
2136                                         G_OBEX_HDR_NAME, "random.bin",
2137                                         G_OBEX_HDR_INVALID);
2138 }
2139
2140 static void test_conn_put_req_seq_srm(void)
2141 {
2142         GIOChannel *io;
2143         GIOCondition cond;
2144         guint io_id, timer_id;
2145         GObex *obex;
2146         struct test_data d = { 0, NULL, {
2147                                 { conn_req_srm, sizeof(conn_req_srm) } ,
2148                                 { NULL, 0 },
2149                                 { NULL, 0 },
2150                                 { put_req_last, sizeof(put_req_last) } }, {
2151                                 { conn_rsp_srm, sizeof(conn_rsp_srm) } ,
2152                                 { NULL, 0 },
2153                                 { NULL, 0 },
2154                                 { put_rsp_last, sizeof(put_rsp_last) } } };
2155
2156         create_endpoints(&obex, &io, SOCK_SEQPACKET);
2157         d.obex = obex;
2158
2159         cond = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
2160         io_id = g_io_add_watch(io, cond, test_io_cb, &d);
2161
2162         d.mainloop = g_main_loop_new(NULL, FALSE);
2163
2164         timer_id = g_timeout_add_seconds(1, test_timeout, &d);
2165
2166         g_obex_connect(obex, conn_complete_put_req_seq_srm, &d, &d.err,
2167                                         G_OBEX_HDR_SRM, G_OBEX_SRM_INDICATE,
2168                                         G_OBEX_HDR_INVALID);
2169         g_assert_no_error(d.err);
2170
2171         g_main_loop_run(d.mainloop);
2172
2173         g_assert_cmpuint(d.count, ==, RANDOM_PACKETS);
2174
2175         g_main_loop_unref(d.mainloop);
2176
2177         g_source_remove(timer_id);
2178         g_io_channel_unref(io);
2179         g_source_remove(io_id);
2180         g_obex_unref(obex);
2181
2182         g_assert_no_error(d.err);
2183 }
2184
2185 int main(int argc, char *argv[])
2186 {
2187         g_test_init(&argc, &argv, NULL);
2188
2189         g_test_add_func("/gobex/test_conn_req", test_conn_req);
2190         g_test_add_func("/gobex/test_conn_rsp", test_conn_rsp);
2191
2192         g_test_add_func("/gobex/test_put_req", test_put_req);
2193         g_test_add_func("/gobex/test_put_rsp", test_put_rsp);
2194
2195         g_test_add_func("/gobex/test_get_req", test_get_req);
2196         g_test_add_func("/gobex/test_get_rsp", test_get_rsp);
2197
2198         g_test_add_func("/gobex/test_get_req_app", test_get_req_app);
2199         g_test_add_func("/gobex/test_get_rsp_app", test_get_rsp_app);
2200
2201         g_test_add_func("/gobex/test_put_req_delay", test_put_req_delay);
2202         g_test_add_func("/gobex/test_put_rsp_delay", test_put_rsp_delay);
2203
2204         g_test_add_func("/gobex/test_get_req_delay", test_get_req_delay);
2205         g_test_add_func("/gobex/test_get_rsp_delay", test_get_rsp_delay);
2206
2207         g_test_add_func("/gobex/test_put_req_eagain", test_put_req_eagain);
2208         g_test_add_func("/gobex/test_get_req_eagain", test_get_rsp_eagain);
2209
2210         g_test_add_func("/gobex/test_stream_put_req", test_stream_put_req);
2211         g_test_add_func("/gobex/test_stream_put_rsp", test_stream_put_rsp);
2212
2213         g_test_add_func("/gobex/test_stream_put_req_abort",
2214                                                 test_stream_put_req_abort);
2215         g_test_add_func("/gobex/test_stream_put_rsp_abort",
2216                                                 test_stream_put_rsp_abort);
2217
2218         g_test_add_func("/gobex/test_stream_get_req", test_stream_get_req);
2219         g_test_add_func("/gobex/test_stream_get_rsp", test_stream_get_rsp);
2220
2221         g_test_add_func("/gobex/test_conn_get_req", test_conn_get_req);
2222         g_test_add_func("/gobex/test_conn_get_rsp", test_conn_get_rsp);
2223
2224         g_test_add_func("/gobex/test_conn_put_req", test_conn_put_req);
2225         g_test_add_func("/gobex/test_conn_put_rsp", test_conn_put_rsp);
2226
2227         g_test_add_func("/gobex/test_conn_get_wrg_rsp", test_conn_get_wrg_rsp);
2228
2229         g_test_add_func("/gobex/test_conn_put_req_seq",
2230                                                 test_conn_put_req_seq);
2231
2232         g_test_add_func("/gobex/test_packet_put_req", test_packet_put_req);
2233         g_test_add_func("/gobex/test_packet_put_req_wait",
2234                                                 test_packet_put_req_wait);
2235
2236         g_test_add_func("/gobex/test_packet_put_rsp", test_packet_put_rsp);
2237         g_test_add_func("/gobex/test_packet_put_rsp_wait",
2238                                                 test_packet_put_rsp_wait);
2239
2240         g_test_add_func("/gobex/test_packet_get_rsp", test_packet_get_rsp);
2241         g_test_add_func("/gobex/test_packet_get_rsp_wait",
2242                                                 test_packet_get_rsp_wait);
2243
2244         g_test_add_func("/gobex/test_packet_get_req", test_packet_get_req);
2245         g_test_add_func("/gobex/test_packet_get_req_wait",
2246                                                 test_packet_get_req_wait);
2247
2248         g_test_add_func("/gobex/test_packet_get_req_wait_next",
2249                                                 test_packet_get_req_wait_next);
2250
2251         g_test_add_func("/gobex/test_conn_put_req_seq_srm",
2252                                                 test_conn_put_req_seq_srm);
2253
2254         g_test_run();
2255
2256         return 0;
2257 }