From cdcde596874e3a698b674c4ef0c47f13232bbe8c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 10 Jul 2011 21:36:47 +0300 Subject: [PATCH] gobex: Add va-args based packet creation support --- gobex/gobex-header.c | 45 ++++++++++++++++++++++++++++++++++ gobex/gobex-header.h | 5 ++++ gobex/gobex-packet.c | 22 +++++++++++++---- gobex/gobex-packet.h | 6 ++++- gobex/gobex-transfer.c | 49 ++++++++++++++++++++++++++------------ gobex/gobex-transfer.h | 4 ++-- gobex/gobex.c | 15 +++++++----- tools/obex-server-tool.c | 3 ++- unit/test-gobex-packet.c | 42 +++++++++++++++++++++++++++++--- unit/test-gobex-transfer.c | 4 ++-- unit/test-gobex.c | 15 +++++++----- 11 files changed, 170 insertions(+), 40 deletions(-) diff --git a/gobex/gobex-header.c b/gobex/gobex-header.c index 1e5e534ac..bf7dc9d7c 100644 --- a/gobex/gobex-header.c +++ b/gobex/gobex-header.c @@ -397,3 +397,48 @@ guint16 g_obex_header_get_length(GObexHeader *header) { return header->hlen; } + +GSList *g_obex_header_create_list(guint8 first_hdr_id, va_list args, + gsize *total_len) +{ + unsigned int id = first_hdr_id; + GSList *l = NULL; + + *total_len = 0; + + while (id != G_OBEX_HDR_ID_INVALID) { + GObexHeader *hdr; + const char *str; + const void *bytes; + unsigned int val; + gsize len; + + switch (G_OBEX_HDR_TYPE(id)) { + case G_OBEX_HDR_TYPE_UNICODE: + str = va_arg(args, const char *); + hdr = g_obex_header_new_unicode(id, str); + break; + case G_OBEX_HDR_TYPE_BYTES: + bytes = va_arg(args, void *); + len = va_arg(args, gsize); + hdr = g_obex_header_new_bytes(id, bytes, len); + break; + case G_OBEX_HDR_TYPE_UINT8: + val = va_arg(args, unsigned int); + hdr = g_obex_header_new_uint8(id, val); + break; + case G_OBEX_HDR_TYPE_UINT32: + val = va_arg(args, unsigned int); + hdr = g_obex_header_new_uint32(id, val); + break; + default: + g_assert_not_reached(); + } + + l = g_slist_append(l, hdr); + *total_len += hdr->hlen; + id = va_arg(args, int); + } + + return l; +} diff --git a/gobex/gobex-header.h b/gobex/gobex-header.h index 721fc36f9..0a8ff3386 100644 --- a/gobex/gobex-header.h +++ b/gobex/gobex-header.h @@ -27,6 +27,8 @@ #include /* Header ID's */ +#define G_OBEX_HDR_ID_INVALID 0x00 + #define G_OBEX_HDR_ID_COUNT 0xc0 #define G_OBEX_HDR_ID_NAME 0x01 #define G_OBEX_HDR_ID_TYPE 0x42 @@ -66,6 +68,9 @@ GObexHeader *g_obex_header_new_bytes(guint8 id, const void *data, gsize len); GObexHeader *g_obex_header_new_uint8(guint8 id, guint8 val); GObexHeader *g_obex_header_new_uint32(guint8 id, guint32 val); +GSList *g_obex_header_create_list(guint8 first_hdr_id, va_list args, + gsize *total_len); + guint8 g_obex_header_get_id(GObexHeader *header); guint16 g_obex_header_get_length(GObexHeader *header); diff --git a/gobex/gobex-packet.c b/gobex/gobex-packet.c index 0e6528edf..10c1cf70a 100644 --- a/gobex/gobex-packet.c +++ b/gobex/gobex-packet.c @@ -154,7 +154,8 @@ gboolean g_obex_packet_set_data(GObexPacket *pkt, const void *data, gsize len, return TRUE; } -GObexPacket *g_obex_packet_new(guint8 opcode, gboolean final, GSList *headers) +GObexPacket *g_obex_packet_new_valist(guint8 opcode, gboolean final, + guint8 first_hdr_id, va_list args) { GObexPacket *pkt; @@ -162,13 +163,26 @@ GObexPacket *g_obex_packet_new(guint8 opcode, gboolean final, GSList *headers) pkt->opcode = opcode; pkt->final = final; - pkt->headers = headers; - + pkt->headers = g_obex_header_create_list(first_hdr_id, args, + &pkt->hlen); pkt->data_policy = G_OBEX_DATA_COPY; return pkt; } +GObexPacket *g_obex_packet_new(guint8 opcode, gboolean final, + guint8 first_hdr_id, ...) +{ + GObexPacket *pkt; + va_list args; + + va_start(args, first_hdr_id); + pkt = g_obex_packet_new_valist(opcode, final, first_hdr_id, args); + va_end(args); + + return pkt; +} + void g_obex_packet_free(GObexPacket *pkt) { switch (pkt->data_policy) { @@ -253,7 +267,7 @@ GObexPacket *g_obex_packet_decode(const void *data, gsize len, final = (opcode & FINAL_BIT) ? TRUE : FALSE; opcode &= ~FINAL_BIT; - pkt = g_obex_packet_new(opcode, final, NULL); + pkt = g_obex_packet_new(opcode, final, G_OBEX_HDR_ID_INVALID); if (header_offset == 0) goto headers; diff --git a/gobex/gobex-packet.h b/gobex/gobex-packet.h index 669cabf27..ea61d99be 100644 --- a/gobex/gobex-packet.h +++ b/gobex/gobex-packet.h @@ -22,6 +22,7 @@ #ifndef __GOBEX_PACKET_H #define __GOBEX_PACKET_H +#include #include #include @@ -90,7 +91,10 @@ gboolean g_obex_packet_add_body(GObexPacket *pkt, GObexDataProducer func, gboolean g_obex_packet_set_data(GObexPacket *pkt, const void *data, gsize len, GObexDataPolicy data_policy); const void *g_obex_packet_get_data(GObexPacket *pkt, gsize *len); -GObexPacket *g_obex_packet_new(guint8 opcode, gboolean final, GSList *headers); +GObexPacket *g_obex_packet_new(guint8 opcode, gboolean final, + guint8 first_hdr_id, ...); +GObexPacket *g_obex_packet_new_valist(guint8 opcode, gboolean final, + guint8 first_hdr_id, va_list args); void g_obex_packet_free(GObexPacket *pkt); GObexPacket *g_obex_packet_decode(const void *data, gsize len, diff --git a/gobex/gobex-transfer.c b/gobex/gobex-transfer.c index bdef9800a..75fa50ef0 100644 --- a/gobex/gobex-transfer.c +++ b/gobex/gobex-transfer.c @@ -32,8 +32,6 @@ struct transfer { GObex *obex; - GSList *hdrs; - guint req_id; gint put_id; @@ -102,7 +100,7 @@ static gssize put_get_data(void *buf, gsize len, gpointer user_data) if (ret >= 0) return ret; - req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_ID_INVALID); transfer->req_id = g_obex_send_req(transfer->obex, req, -1, transfer_abort_response, transfer, &err); @@ -161,7 +159,7 @@ static void transfer_response(GObex *obex, GError *err, GObexPacket *rsp, return; } - req = g_obex_packet_new(transfer->opcode, TRUE, NULL); + req = g_obex_packet_new(transfer->opcode, TRUE, G_OBEX_HDR_ID_INVALID); if (transfer->opcode == G_OBEX_OP_PUT) g_obex_packet_add_body(req, put_get_data, transfer); @@ -203,7 +201,7 @@ guint g_obex_put_req(GObex *obex, const char *type, const char *name, transfer = transfer_new(obex, G_OBEX_OP_PUT, complete_func, user_data); transfer->data_producer = data_func; - req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_ID_INVALID); if (type) { hdr = g_obex_header_new_bytes(G_OBEX_HDR_ID_TYPE, @@ -252,7 +250,7 @@ static void transfer_put_req(GObex *obex, GObexPacket *req, gpointer user_data) transfer->data_consumer(buf, len, transfer->user_data); } - rsp = g_obex_packet_new(rspcode, TRUE, NULL); + rsp = g_obex_packet_new(rspcode, TRUE, G_OBEX_HDR_ID_INVALID); if (!g_obex_send(obex, rsp, &err)) { transfer_complete(transfer, err); g_error_free(err); @@ -270,7 +268,8 @@ static void transfer_abort_req(GObex *obex, GObexPacket *req, gpointer user_data err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED, "Request was aborted"); - rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE, NULL); + rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE, + G_OBEX_HDR_ID_INVALID); g_obex_send(obex, rsp, NULL); transfer_complete(transfer, err); @@ -313,7 +312,7 @@ guint g_obex_get_req(GObex *obex, const char *type, const char *name, transfer = transfer_new(obex, G_OBEX_OP_GET, complete_func, user_data); transfer->data_consumer = data_func; - req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_ID_INVALID); if (type) { hdr = g_obex_header_new_bytes(G_OBEX_HDR_ID_TYPE, @@ -352,7 +351,8 @@ static gssize get_get_data(void *buf, gsize len, gpointer user_data) return ret; } - req = g_obex_packet_new(G_OBEX_RSP_INTERNAL_SERVER_ERROR, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_RSP_INTERNAL_SERVER_ERROR, TRUE, + G_OBEX_HDR_ID_INVALID); g_obex_send(transfer->obex, req, NULL); err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED, @@ -363,14 +363,30 @@ static gssize get_get_data(void *buf, gsize len, gpointer user_data) return ret; } +static void transfer_get_req_first(struct transfer *transfer, + guint8 first_hdr_id, va_list args) +{ + GError *err = NULL; + GObexPacket *rsp; + + rsp = g_obex_packet_new_valist(G_OBEX_RSP_CONTINUE, TRUE, + first_hdr_id, args); + g_obex_packet_add_body(rsp, get_get_data, transfer); + + if (!g_obex_send(transfer->obex, rsp, &err)) { + transfer_complete(transfer, err); + g_error_free(err); + } +} + static void transfer_get_req(GObex *obex, GObexPacket *req, gpointer user_data) { struct transfer *transfer = user_data; GError *err = NULL; GObexPacket *rsp; - rsp = g_obex_packet_new(G_OBEX_RSP_CONTINUE, TRUE, transfer->hdrs); - transfer->hdrs = NULL; + rsp = g_obex_packet_new(G_OBEX_RSP_CONTINUE, TRUE, + G_OBEX_HDR_ID_INVALID); g_obex_packet_add_body(rsp, get_get_data, transfer); if (!g_obex_send(obex, rsp, &err)) { @@ -379,18 +395,21 @@ static void transfer_get_req(GObex *obex, GObexPacket *req, gpointer user_data) } } -guint g_obex_get_rsp(GObex *obex, GSList *hdrs, GObexDataProducer data_func, +guint g_obex_get_rsp(GObex *obex, GObexDataProducer data_func, GObexFunc complete_func, gpointer user_data, - GError **err) + GError **err, guint8 first_hdr_id, ...) { struct transfer *transfer; + va_list args; gint id; transfer = transfer_new(obex, G_OBEX_OP_GET, complete_func, user_data); transfer->data_producer = data_func; - transfer->hdrs = hdrs; - transfer_get_req(obex, NULL, transfer); + va_start(args, first_hdr_id); + transfer_get_req_first(transfer, first_hdr_id, args); + va_end(args); + if (!g_slist_find(transfers, transfer)) return 0; diff --git a/gobex/gobex-transfer.h b/gobex/gobex-transfer.h index 21e14c85f..2dff42e74 100644 --- a/gobex/gobex-transfer.h +++ b/gobex/gobex-transfer.h @@ -39,9 +39,9 @@ guint g_obex_put_rsp(GObex *obex, GObexPacket *req, GObexDataConsumer data_func, GObexFunc complete_func, gpointer user_data, GError **err); -guint g_obex_get_rsp(GObex *obex, GSList *hdrs, GObexDataProducer data_func, +guint g_obex_get_rsp(GObex *obex, GObexDataProducer data_func, GObexFunc complete_func, gpointer user_data, - GError **err); + GError **err, guint8 first_hdr_id, ...); gboolean g_obex_cancel_transfer(guint id); diff --git a/gobex/gobex.c b/gobex/gobex.c index 9ac5c9590..b0d21ea14 100644 --- a/gobex/gobex.c +++ b/gobex/gobex.c @@ -422,7 +422,7 @@ static gboolean pending_req_abort(GObex *obex, GError **err) obex->pending_req->cancelled = TRUE; - pkt = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, NULL); + pkt = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_ID_INVALID); return g_obex_send(obex, pkt, err); } @@ -624,7 +624,8 @@ static void handle_request(GObex *obex, GObexPacket *req) return; } - rsp = g_obex_packet_new(G_OBEX_RSP_NOT_IMPLEMENTED, TRUE, NULL); + rsp = g_obex_packet_new(G_OBEX_RSP_NOT_IMPLEMENTED, TRUE, + G_OBEX_HDR_ID_INVALID); g_obex_send(obex, rsp, NULL); } @@ -913,7 +914,8 @@ guint g_obex_connect(GObex *obex, void *target, gsize target_len, GObexPacket *req; struct connect_data data; - req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, + G_OBEX_HDR_ID_INVALID); init_connect_data(obex, &data); g_obex_packet_set_data(req, &data, sizeof(data), G_OBEX_DATA_COPY); @@ -934,7 +936,7 @@ guint g_obex_setpath(GObex *obex, const char *path, GObexResponseFunc func, GObexPacket *req; struct setpath_data data; - req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, G_OBEX_HDR_ID_INVALID); memset(&data, 0, sizeof(data)); @@ -959,7 +961,8 @@ guint g_obex_mkdir(GObex *obex, const char *path, GObexResponseFunc func, GObexHeader *hdr; struct setpath_data data; - req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, + G_OBEX_HDR_ID_INVALID); memset(&data, 0, sizeof(data)); hdr = g_obex_header_new_unicode(G_OBEX_HDR_ID_NAME, path); @@ -976,7 +979,7 @@ guint g_obex_delete(GObex *obex, const char *name, GObexResponseFunc func, GObexPacket *req; GObexHeader *hdr; - req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_ID_INVALID); hdr = g_obex_header_new_unicode(G_OBEX_HDR_ID_NAME, name); g_obex_packet_add_header(req, hdr); diff --git a/tools/obex-server-tool.c b/tools/obex-server-tool.c index 1432203db..bfb6877ae 100644 --- a/tools/obex-server-tool.c +++ b/tools/obex-server-tool.c @@ -116,7 +116,8 @@ static void handle_connect(GObex *obex, GObexPacket *req, gpointer user_data) g_print("connect\n"); - rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE, NULL); + rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE, + G_OBEX_HDR_ID_INVALID); g_obex_send(obex, rsp, NULL); } diff --git a/unit/test-gobex-packet.c b/unit/test-gobex-packet.c index aa9054d65..d3e482537 100644 --- a/unit/test-gobex-packet.c +++ b/unit/test-gobex-packet.c @@ -39,11 +39,21 @@ static uint8_t pkt_put[] = { G_OBEX_OP_PUT, 0x00, 0x03 }; static uint8_t pkt_nval_len[] = { G_OBEX_OP_PUT, 0xab, 0xcd, 0x12 }; +static guint8 pkt_put_long[] = { G_OBEX_OP_PUT, 0x00, 0x32, + G_OBEX_HDR_ID_CONNECTION, 0x01, 0x02, 0x03, 0x04, + G_OBEX_HDR_ID_TYPE, 0x00, 0x0b, + 'f', 'o', 'o', '/', 'b', 'a', 'r', '\0', + G_OBEX_HDR_ID_NAME, 0x00, 0x15, + 0, 'f', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0, + G_OBEX_HDR_ID_ACTION, 0xab, + G_OBEX_HDR_ID_BODY, 0x00, 0x08, + 0, 1, 2, 3, 4 }; + static void test_pkt(void) { GObexPacket *pkt; - pkt = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, NULL); + pkt = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_ID_INVALID); g_assert(pkt != NULL); @@ -159,7 +169,7 @@ static void test_encode_on_demand(void) uint8_t buf[255]; gssize len; - pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, NULL); + pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_ID_INVALID); g_obex_packet_add_body(pkt, get_body_data, NULL); len = g_obex_packet_encode(pkt, buf, sizeof(buf)); @@ -184,7 +194,7 @@ static void test_encode_on_demand_fail(void) uint8_t buf[255]; gssize len; - pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, NULL); + pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_ID_INVALID); g_obex_packet_add_body(pkt, get_body_data_fail, NULL); len = g_obex_packet_encode(pkt, buf, sizeof(buf)); @@ -194,6 +204,30 @@ static void test_encode_on_demand_fail(void) g_obex_packet_free(pkt); } +static void test_create_args(void) +{ + GObexPacket *pkt; + guint8 buf[255], body[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; + gssize len; + + pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, + G_OBEX_HDR_ID_CONNECTION, 0x01020304, + G_OBEX_HDR_ID_TYPE, "foo/bar", strlen("foo/bar") + 1, + G_OBEX_HDR_ID_NAME, "file.txt", + G_OBEX_HDR_ID_ACTION, 0xab, + G_OBEX_HDR_ID_BODY, body, sizeof(body), + G_OBEX_HDR_ID_INVALID); + + g_assert(pkt != NULL); + + len = g_obex_packet_encode(pkt, buf, sizeof(buf)); + g_assert(len > 0); + + assert_memequal(pkt_put_long, sizeof(pkt_put_long), buf, len); + + g_obex_packet_free(pkt); +} + int main(int argc, char *argv[]) { g_test_init(&argc, &argv, NULL); @@ -213,6 +247,8 @@ int main(int argc, char *argv[]) g_test_add_func("/gobex/test_encode_on_demand_fail", test_encode_on_demand_fail); + g_test_add_func("/gobex/test_create_args", test_create_args); + g_test_run(); return 0; diff --git a/unit/test-gobex-transfer.c b/unit/test-gobex-transfer.c index 68c6a5176..cf391f098 100644 --- a/unit/test-gobex-transfer.c +++ b/unit/test-gobex-transfer.c @@ -273,8 +273,8 @@ static void handle_get(GObex *obex, GObexPacket *req, gpointer user_data) return; } - id = g_obex_get_rsp(obex, NULL, provide_data, transfer_complete, - d, &d->err); + id = g_obex_get_rsp(obex, provide_data, transfer_complete, d, &d->err, + G_OBEX_HDR_ID_INVALID); if (id == 0) g_main_loop_quit(d->mainloop); } diff --git a/unit/test-gobex.c b/unit/test-gobex.c index 6d14b516e..ce40bf609 100644 --- a/unit/test-gobex.c +++ b/unit/test-gobex.c @@ -252,7 +252,8 @@ static void send_connect(GObexResponseFunc rsp_func, GIOFunc send_rsp_func, GObexPacket *req; guint8 connect_data[] = { 0x10, 0x00, 0x10, 0x00 }; - req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, + G_OBEX_HDR_ID_INVALID); g_assert(req != NULL); g_obex_packet_set_data(req, connect_data, sizeof(connect_data), @@ -326,7 +327,7 @@ static void test_cancel_req_immediate(void) r.err = NULL; - req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_ID_INVALID); r.id = g_obex_send_req(r.obex, req, -1, req_done, &r, &r.err); g_assert_no_error(r.err); g_assert(r.id != 0); @@ -407,7 +408,7 @@ static void test_cancel_req_delay(int transport_type) r.err = NULL; - req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_ID_INVALID); r.id = g_obex_send_req(r.obex, req, -1, req_done, &r, &r.err); g_assert_no_error(r.err); g_assert(r.id != 0); @@ -502,7 +503,8 @@ static void test_send_connect(int transport_type) r.buf = pkt_connect_req; r.len = sizeof(pkt_connect_req); - req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_OP_CONNECT, TRUE, + G_OBEX_HDR_ID_INVALID); g_assert(req != NULL); g_obex_packet_set_data(req, connect_data, sizeof(connect_data), @@ -565,7 +567,8 @@ static void test_recv_unexpected(void) g_obex_set_disconnect_function(obex, unexpected_disconn, &err); - req = g_obex_packet_new(G_OBEX_RSP_CONTINUE, TRUE, NULL); + req = g_obex_packet_new(G_OBEX_RSP_CONTINUE, TRUE, + G_OBEX_HDR_ID_INVALID); len = g_obex_packet_encode(req, buf, sizeof(buf)); g_assert_cmpint(len, >=, 0); @@ -618,7 +621,7 @@ static void test_send_on_demand(int transport_type, GObexDataProducer func) r.buf = pkt_put_body; r.len = sizeof(pkt_put_body); - req = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, NULL); + req = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_ID_INVALID); g_obex_packet_add_body(req, func, &r); g_obex_send(obex, req, &r.err); -- 2.47.3