~vcs-imports/bluez/master

6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
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
9677 by Johan Hedberg
gobex: Fix GPL version reference
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
 *
21
 */
22
7727 by Johan Hedberg
Revert "Ensure config.h is included by using CPPFLAGS"
23
#ifdef HAVE_CONFIG_H
24
#include <config.h>
25
#endif
26
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
27
#include <string.h>
28
#include <errno.h>
29
6379 by Johan Hedberg
gobex: Use GObexDataProducer type instead of (custom) GObexPacketDataFunc
30
#include "gobex-defs.h"
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
31
#include "gobex-packet.h"
6466 by Luiz Augusto von Dentz
gobex: log errors using G_OBEX_DEBUG_ERROR
32
#include "gobex-debug.h"
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
33
6330 by Johan Hedberg
gobex: Don't export final bit details in public API
34
#define FINAL_BIT 0x80
35
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
36
struct _GObexPacket {
37
	guint8 opcode;
38
	gboolean final;
39
40
	GObexDataPolicy data_policy;
41
42
	union {
43
		void *buf;		/* Non-header data */
44
		const void *buf_ref;	/* Reference to non-header data */
45
	} data;
6322 by Johan Hedberg
gobex: Use GLib size types
46
	gsize data_len;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
47
6322 by Johan Hedberg
gobex: Use GLib size types
48
	gsize hlen;		/* Length of all encoded headers */
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
49
	GSList *headers;
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
50
6379 by Johan Hedberg
gobex: Use GObexDataProducer type instead of (custom) GObexPacketDataFunc
51
	GObexDataProducer get_body;
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
52
	gpointer get_body_data;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
53
};
54
55
GObexHeader *g_obex_packet_get_header(GObexPacket *pkt, guint8 id)
56
{
57
	GSList *l;
58
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
59
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
60
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
61
	for (l = pkt->headers; l != NULL; l = g_slist_next(l)) {
62
		GObexHeader *hdr = l->data;
63
64
		if (g_obex_header_get_id(hdr) == id)
65
			return hdr;
66
	}
67
68
	return NULL;
69
}
70
6432 by Johan Hedberg
gobex: Add g_obex_packet_get_body convenience function
71
GObexHeader *g_obex_packet_get_body(GObexPacket *pkt)
72
{
73
	GObexHeader *body;
74
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
75
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
76
6432 by Johan Hedberg
gobex: Add g_obex_packet_get_body convenience function
77
	body = g_obex_packet_get_header(pkt, G_OBEX_HDR_BODY);
78
	if (body != NULL)
79
		return body;
80
81
	return g_obex_packet_get_header(pkt, G_OBEX_HDR_BODY_END);
82
}
83
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
84
guint8 g_obex_packet_get_operation(GObexPacket *pkt, gboolean *final)
85
{
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
86
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
87
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
88
	if (final)
89
		*final = pkt->final;
90
91
	return pkt->opcode;
92
}
93
6366 by Johan Hedberg
gobex: Add g_obex_packet_find_header and g_obex_packet_prepend_header
94
gboolean g_obex_packet_prepend_header(GObexPacket *pkt, GObexHeader *header)
95
{
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
96
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
97
6366 by Johan Hedberg
gobex: Add g_obex_packet_find_header and g_obex_packet_prepend_header
98
	pkt->headers = g_slist_prepend(pkt->headers, header);
99
	pkt->hlen += g_obex_header_get_length(header);
100
101
	return TRUE;
102
}
103
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
104
gboolean g_obex_packet_add_header(GObexPacket *pkt, GObexHeader *header)
105
{
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
106
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
107
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
108
	pkt->headers = g_slist_append(pkt->headers, header);
109
	pkt->hlen += g_obex_header_get_length(header);
110
111
	return TRUE;
112
}
113
6379 by Johan Hedberg
gobex: Use GObexDataProducer type instead of (custom) GObexPacketDataFunc
114
gboolean g_obex_packet_add_body(GObexPacket *pkt, GObexDataProducer func,
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
115
							gpointer user_data)
116
{
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
117
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
118
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
119
	if (pkt->get_body != NULL)
120
		return FALSE;
121
122
	pkt->get_body = func;
123
	pkt->get_body_data = user_data;
124
125
	return TRUE;
126
}
127
6450 by Johan Hedberg
gobex: Add OBEX packet header addition convenience functions
128
gboolean g_obex_packet_add_unicode(GObexPacket *pkt, guint8 id,
129
							const char *str)
130
{
131
	GObexHeader *hdr;
132
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
133
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
134
6450 by Johan Hedberg
gobex: Add OBEX packet header addition convenience functions
135
	hdr = g_obex_header_new_unicode(id, str);
136
	if (hdr == NULL)
137
		return FALSE;
138
139
	return g_obex_packet_add_header(pkt, hdr);
140
}
141
142
gboolean g_obex_packet_add_bytes(GObexPacket *pkt, guint8 id,
143
						const void *data, gsize len)
144
{
145
	GObexHeader *hdr;
146
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
147
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
148
6450 by Johan Hedberg
gobex: Add OBEX packet header addition convenience functions
149
	hdr = g_obex_header_new_bytes(id, data, len);
150
	if (hdr == NULL)
151
		return FALSE;
152
153
	return g_obex_packet_add_header(pkt, hdr);
154
}
155
156
gboolean g_obex_packet_add_uint8(GObexPacket *pkt, guint8 id, guint8 val)
157
{
158
	GObexHeader *hdr;
159
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
160
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
161
6450 by Johan Hedberg
gobex: Add OBEX packet header addition convenience functions
162
	hdr = g_obex_header_new_uint8(id, val);
163
	if (hdr == NULL)
164
		return FALSE;
165
166
	return g_obex_packet_add_header(pkt, hdr);
167
}
168
169
gboolean g_obex_packet_add_uint32(GObexPacket *pkt, guint8 id, guint32 val)
170
{
171
	GObexHeader *hdr;
172
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
173
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
174
6450 by Johan Hedberg
gobex: Add OBEX packet header addition convenience functions
175
	hdr = g_obex_header_new_uint32(id, val);
176
	if (hdr == NULL)
177
		return FALSE;
178
179
	return g_obex_packet_add_header(pkt, hdr);
180
}
181
6322 by Johan Hedberg
gobex: Use GLib size types
182
const void *g_obex_packet_get_data(GObexPacket *pkt, gsize *len)
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
183
{
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
184
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
185
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
186
	if (pkt->data_len == 0) {
187
		*len = 0;
188
		return NULL;
189
	}
190
191
	*len = pkt->data_len;
192
193
	switch (pkt->data_policy) {
194
	case G_OBEX_DATA_INHERIT:
195
	case G_OBEX_DATA_COPY:
196
		return pkt->data.buf;
197
	case G_OBEX_DATA_REF:
198
		return pkt->data.buf_ref;
199
	}
200
201
	g_assert_not_reached();
202
}
203
6322 by Johan Hedberg
gobex: Use GLib size types
204
gboolean g_obex_packet_set_data(GObexPacket *pkt, const void *data, gsize len,
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
205
						GObexDataPolicy data_policy)
206
{
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
207
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
208
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
209
	if (pkt->data.buf || pkt->data.buf_ref)
210
		return FALSE;
211
212
	pkt->data_policy = data_policy;
213
	pkt->data_len = len;
214
215
	switch (data_policy) {
216
	case G_OBEX_DATA_COPY:
217
		pkt->data.buf = g_memdup(data, len);
218
		break;
219
	case G_OBEX_DATA_REF:
220
		pkt->data.buf_ref = data;
221
		break;
222
	case G_OBEX_DATA_INHERIT:
223
		pkt->data.buf = (void *) data;
224
		break;
225
	}
226
227
	return TRUE;
228
}
229
6418 by Johan Hedberg
gobex: Add va-args based packet creation support
230
GObexPacket *g_obex_packet_new_valist(guint8 opcode, gboolean final,
18891 by Miao-chen Chou
gobex: Fix a compilation error for the compatibility with LLVM
231
					guint first_hdr_id, va_list args)
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
232
{
233
	GObexPacket *pkt;
234
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
235
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", opcode);
236
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
237
	pkt = g_new0(GObexPacket, 1);
238
239
	pkt->opcode = opcode;
240
	pkt->final = final;
6418 by Johan Hedberg
gobex: Add va-args based packet creation support
241
	pkt->headers = g_obex_header_create_list(first_hdr_id, args,
242
								&pkt->hlen);
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
243
	pkt->data_policy = G_OBEX_DATA_COPY;
244
245
	return pkt;
246
}
247
6418 by Johan Hedberg
gobex: Add va-args based packet creation support
248
GObexPacket *g_obex_packet_new(guint8 opcode, gboolean final,
18891 by Miao-chen Chou
gobex: Fix a compilation error for the compatibility with LLVM
249
						guint first_hdr_id, ...)
6418 by Johan Hedberg
gobex: Add va-args based packet creation support
250
{
251
	GObexPacket *pkt;
252
	va_list args;
253
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
254
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", opcode);
255
6418 by Johan Hedberg
gobex: Add va-args based packet creation support
256
	va_start(args, first_hdr_id);
257
	pkt = g_obex_packet_new_valist(opcode, final, first_hdr_id, args);
258
	va_end(args);
259
260
	return pkt;
261
}
262
19639 by Marcel Holtmann
gobex: Fix compiler warning from casting functions
263
static void header_free(void *data, void *user_data)
264
{
265
	g_obex_header_free(data);
266
}
267
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
268
void g_obex_packet_free(GObexPacket *pkt)
269
{
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
270
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
271
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
272
	switch (pkt->data_policy) {
273
	case G_OBEX_DATA_INHERIT:
274
	case G_OBEX_DATA_COPY:
275
		g_free(pkt->data.buf);
276
		break;
277
	case G_OBEX_DATA_REF:
278
		break;
279
	}
280
19639 by Marcel Holtmann
gobex: Fix compiler warning from casting functions
281
	g_slist_foreach(pkt->headers, header_free, NULL);
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
282
	g_slist_free(pkt->headers);
283
	g_free(pkt);
284
}
285
6322 by Johan Hedberg
gobex: Use GLib size types
286
static gboolean parse_headers(GObexPacket *pkt, const void *data, gsize len,
6324 by Johan Hedberg
gobex: Add initial GError support
287
						GObexDataPolicy data_policy,
288
						GError **err)
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
289
{
290
	const guint8 *buf = data;
291
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
292
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
293
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
294
	while (len > 0) {
295
		GObexHeader *header;
6322 by Johan Hedberg
gobex: Use GLib size types
296
		gsize parsed;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
297
6324 by Johan Hedberg
gobex: Add initial GError support
298
		header = g_obex_header_decode(buf, len, data_policy, &parsed,
299
									err);
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
300
		if (header == NULL)
301
			return FALSE;
302
303
		pkt->headers = g_slist_append(pkt->headers, header);
6325 by Johan Hedberg
gobex: Fix packet length updating when parsing headers
304
		pkt->hlen += parsed;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
305
306
		len -= parsed;
307
		buf += parsed;
308
	}
309
310
	return TRUE;
311
}
312
6322 by Johan Hedberg
gobex: Use GLib size types
313
static const guint8 *get_bytes(void *to, const guint8 *from, gsize count)
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
314
{
315
	memcpy(to, from, count);
316
	return (from + count);
317
}
318
6322 by Johan Hedberg
gobex: Use GLib size types
319
GObexPacket *g_obex_packet_decode(const void *data, gsize len,
320
						gsize header_offset,
6324 by Johan Hedberg
gobex: Add initial GError support
321
						GObexDataPolicy data_policy,
322
						GError **err)
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
323
{
324
	const guint8 *buf = data;
325
	guint16 packet_len;
326
	guint8 opcode;
327
	GObexPacket *pkt;
328
	gboolean final;
329
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
330
	g_obex_debug(G_OBEX_DEBUG_PACKET, "");
331
6324 by Johan Hedberg
gobex: Add initial GError support
332
	if (data_policy == G_OBEX_DATA_INHERIT) {
15390 by Luiz Augusto von Dentz
gobex: Fix crash when debug is enabled
333
		if (!err)
334
			return NULL;
6324 by Johan Hedberg
gobex: Add initial GError support
335
		g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_INVALID_ARGS,
336
							"Invalid data policy");
6466 by Luiz Augusto von Dentz
gobex: log errors using G_OBEX_DEBUG_ERROR
337
		g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
6324 by Johan Hedberg
gobex: Add initial GError support
338
		return NULL;
339
	}
340
6333 by Johan Hedberg
gobex: Fix length checks in packet decoding
341
	if (len < 3 + header_offset) {
15390 by Luiz Augusto von Dentz
gobex: Fix crash when debug is enabled
342
		if (!err)
343
			return NULL;
6324 by Johan Hedberg
gobex: Add initial GError support
344
		g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
345
					"Not enough data to decode packet");
6466 by Luiz Augusto von Dentz
gobex: log errors using G_OBEX_DEBUG_ERROR
346
		g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
6324 by Johan Hedberg
gobex: Add initial GError support
347
		return NULL;
348
	}
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
349
350
	buf = get_bytes(&opcode, buf, sizeof(opcode));
351
	buf = get_bytes(&packet_len, buf, sizeof(packet_len));
352
353
	packet_len = g_ntohs(packet_len);
6324 by Johan Hedberg
gobex: Add initial GError support
354
	if (packet_len != len) {
15390 by Luiz Augusto von Dentz
gobex: Fix crash when debug is enabled
355
		if (!err)
356
			return NULL;
6324 by Johan Hedberg
gobex: Add initial GError support
357
		g_set_error(err, G_OBEX_ERROR, G_OBEX_ERROR_PARSE_ERROR,
358
				"Incorrect packet length (%u != %zu)",
359
				packet_len, len);
6466 by Luiz Augusto von Dentz
gobex: log errors using G_OBEX_DEBUG_ERROR
360
		g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", (*err)->message);
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
361
		return NULL;
6324 by Johan Hedberg
gobex: Add initial GError support
362
	}
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
363
6330 by Johan Hedberg
gobex: Don't export final bit details in public API
364
	final = (opcode & FINAL_BIT) ? TRUE : FALSE;
365
	opcode &= ~FINAL_BIT;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
366
6419 by Johan Hedberg
gobex: Remove _ID_ from header type definitions
367
	pkt = g_obex_packet_new(opcode, final, G_OBEX_HDR_INVALID);
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
368
369
	if (header_offset == 0)
370
		goto headers;
371
6324 by Johan Hedberg
gobex: Add initial GError support
372
	g_obex_packet_set_data(pkt, buf, header_offset, data_policy);
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
373
	buf += header_offset;
374
375
headers:
6333 by Johan Hedberg
gobex: Fix length checks in packet decoding
376
	if (!parse_headers(pkt, buf, len - (3 + header_offset),
6324 by Johan Hedberg
gobex: Add initial GError support
377
							data_policy, err))
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
378
		goto failed;
379
380
	return pkt;
381
382
failed:
383
	g_obex_packet_free(pkt);
384
	return NULL;
385
}
386
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
387
static gssize get_body(GObexPacket *pkt, guint8 *buf, gsize len)
388
{
389
	guint16 u16;
390
	gssize ret;
391
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
392
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
393
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
394
	if (len < 3)
395
		return -ENOBUFS;
396
6379 by Johan Hedberg
gobex: Use GObexDataProducer type instead of (custom) GObexPacketDataFunc
397
	ret = pkt->get_body(buf + 3, len - 3, pkt->get_body_data);
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
398
	if (ret < 0)
399
		return ret;
400
401
	if (ret > 0)
6419 by Johan Hedberg
gobex: Remove _ID_ from header type definitions
402
		buf[0] = G_OBEX_HDR_BODY;
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
403
	else
6419 by Johan Hedberg
gobex: Remove _ID_ from header type definitions
404
		buf[0] = G_OBEX_HDR_BODY_END;
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
405
406
	u16 = g_htons(ret + 3);
407
	memcpy(&buf[1], &u16, sizeof(u16));
408
409
	return ret;
410
}
411
6322 by Johan Hedberg
gobex: Use GLib size types
412
gssize g_obex_packet_encode(GObexPacket *pkt, guint8 *buf, gsize len)
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
413
{
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
414
	gssize ret;
6322 by Johan Hedberg
gobex: Use GLib size types
415
	gsize count;
6343 by Johan Hedberg
gobex: Add support for on-demand headers
416
	guint16 u16;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
417
	GSList *l;
418
6470 by Luiz Augusto von Dentz
gobex: log packets using G_OBEX_DEBUG_PACKET
419
	g_obex_debug(G_OBEX_DEBUG_PACKET, "opcode 0x%02x", pkt->opcode);
420
6343 by Johan Hedberg
gobex: Add support for on-demand headers
421
	if (3 + pkt->data_len + pkt->hlen > len)
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
422
		return -ENOBUFS;
423
424
	buf[0] = pkt->opcode;
425
	if (pkt->final)
6330 by Johan Hedberg
gobex: Don't export final bit details in public API
426
		buf[0] |= FINAL_BIT;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
427
428
	if (pkt->data_len > 0) {
429
		if (pkt->data_policy == G_OBEX_DATA_REF)
430
			memcpy(&buf[3], pkt->data.buf_ref, pkt->data_len);
431
		else
432
			memcpy(&buf[3], pkt->data.buf, pkt->data_len);
433
	}
434
435
	count = 3 + pkt->data_len;
436
437
	for (l = pkt->headers; l != NULL; l = g_slist_next(l)) {
438
		GObexHeader *hdr = l->data;
6369 by Johan Hedberg
gobex: Make on-demand header callbacks able to fail cleanly
439
6343 by Johan Hedberg
gobex: Add support for on-demand headers
440
		if (count >= len)
441
			return -ENOBUFS;
6369 by Johan Hedberg
gobex: Make on-demand header callbacks able to fail cleanly
442
443
		ret = g_obex_header_encode(hdr, buf + count, len - count);
444
		if (ret < 0)
445
			return ret;
446
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
447
		count += ret;
448
	}
449
450
	if (pkt->get_body) {
451
		ret = get_body(pkt, buf + count, len - count);
452
		if (ret < 0)
453
			return ret;
6386 by Johan Hedberg
gobex: Fix also response code for on-demand data based packets
454
		if (ret == 0) {
455
			if (pkt->opcode == G_OBEX_RSP_CONTINUE)
456
				buf[0] = G_OBEX_RSP_SUCCESS;
6373 by Johan Hedberg
gobex: Fix end of body packets for on-demand headers
457
			buf[0] |= FINAL_BIT;
6386 by Johan Hedberg
gobex: Fix also response code for on-demand data based packets
458
		}
459
6378 by Johan Hedberg
gobex: Make on-demand body headers a GObexPacket feature
460
		count += ret + 3;
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
461
	}
462
6343 by Johan Hedberg
gobex: Add support for on-demand headers
463
	u16 = g_htons(count);
464
	memcpy(&buf[1], &u16, sizeof(u16));
6320 by Johan Hedberg
gobex: Split gobex.c into multiple modules
465
466
	return count;
467
}