Hi,
these patches will enable sending and receiving of user defined headers
in gwobex.
Two new functions will enable to start an asynchronous get or put
transfer, taking as an argument a list of structures describing
the headers to be sent. The headers are sent out in the order
of appearance on the list.
Likewise all response headers that would have been previously ignored
by gwobex are now inserted to a list in the current gw_obex_xfer
object, and so can be retrieved later after the asynchrous transfer
has finished.
Additionally, the order of sending headers in gwobex is changed
to the one mandated by BIP, i.e.:
Connection ID->Type->Name->Application Parameters->User Defined Headers.
Jakub Adamek (10):
Add a_header struct for additional header data
Add list to store received headers
Store received headers in gw_obex_xfer object
Add functions to get, put w. a_header list
Parse headers in a PUT response packet
Add functions for async requests w a_header list
Reorder headers to conform to BIP's requirements
Handle partial content response from server
Convenience method to make deep copy of a_header
Add func for fetching header by id from list
gwobex/gw-obex.h | 39 +++++++++++++
gwobex/obex-priv.c | 151 +++++++++++++++++++++++++++++++++++++---------------
gwobex/obex-priv.h | 29 ++++++++++
gwobex/obex-xfer.c | 70 ++++++++++++++++++++++++
gwobex/obex-xfer.h | 15 +++++
5 files changed, 261 insertions(+), 43 deletions(-)
Hi,
2011/6/20 Luiz Augusto von Dentz <[email protected]>:
> Hi Jakub,
>
> On Sun, Jun 19, 2011 at 3:59 AM, Jakub Adamek <[email protected]> wrote:
>> ---
>> ?gwobex/obex-priv.c | ? 22 ++++++++++++++++++++++
>> ?1 files changed, 22 insertions(+), 0 deletions(-)
>>
>> diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
>> index aba7dd7..b9216e5 100644
>> --- a/gwobex/obex-priv.c
>> +++ b/gwobex/obex-priv.c
>> @@ -39,6 +39,7 @@
>> ?#include <sys/socket.h>
>>
>> ?#include <openobex/obex.h>
>> +#include <openobex/obex_const.h>
>>
>> ?#ifdef HAVE_CONFIG_H
>> ?# include "config.h"
>> @@ -335,6 +336,7 @@ static void get_non_body_headers(obex_t *handle, obex_object_t *object,
>> ? ? obex_headerdata_t hv;
>> ? ? uint8_t hi;
>> ? ? unsigned int hlen;
>> + ? ?struct a_header *ah;
>>
>> ? ? xfer->target_size = GW_OBEX_UNKNOWN_LENGTH;
>> ? ? xfer->modtime = -1;
>> @@ -358,6 +360,26 @@ static void get_non_body_headers(obex_t *handle, obex_object_t *object,
>> ? ? ? ? ? ? ? ? ? ? xfer->apparam_size = 0;
>> ? ? ? ? ? ? ? ? break;
>> ? ? ? ? ? ? default:
>> + ? ? ? ? ? ? ? ?ah = g_new0(struct a_header, 1);
>> + ? ? ? ? ? ? ? ?ah->hi = hi;
>> + ? ? ? ? ? ? ? ?ah->hv_size = hlen;
>> + ? ? ? ? ? ? ? ?switch (hi & OBEX_HDR_TYPE_MASK) {
>> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_UINT8:
>> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_UINT32:
>> + ? ? ? ? ? ? ? ? ? ? ? ?ah->hv = hv;
>> + ? ? ? ? ? ? ? ? ? ? ? ?break;
>> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_BYTES:
>> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_UNICODE:
>> + ? ? ? ? ? ? ? ? ? ? ? ?ah->hv.bs = g_try_malloc(hlen);
>> + ? ? ? ? ? ? ? ? ? ? ? ?if (ah->hv.bs) {
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?memcpy((void *) ah->hv.bs, hv.bs, hlen);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?ah->hv_size = hlen;
>> + ? ? ? ? ? ? ? ? ? ? ? ?} else {
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?ah->hv_size = hlen;
>> + ? ? ? ? ? ? ? ? ? ? ? ?}
>
> No need to add braces for single line statements.
Will fix. In any case this is badly done, since I think I should test
if g_try_malloc returned NULL because of hlen=0 or because of failure.
>
>> + ? ? ? ? ? ? ? ? ? ? ? ?break;
>> + ? ? ? ? ? ? ? ?}
>> + ? ? ? ? ? ? ? ?xfer->aheaders = g_slist_append(xfer->aheaders, ah);
>
> I would suggest having this code separated in another function e.g.
> get_aheader, it is easier to identify what the code is doing and
> switch inside a switch is not very nice to read/understand IMO.
Ok.
>
> --
> Luiz Augusto von Dentz
>
Hi Jakub,
On Sun, Jun 19, 2011 at 3:59 AM, Jakub Adamek <[email protected]> wrote:
> ---
> ?gwobex/obex-xfer.c | ? 10 ++++++++++
> ?gwobex/obex-xfer.h | ? ?2 ++
> ?2 files changed, 12 insertions(+), 0 deletions(-)
>
> diff --git a/gwobex/obex-xfer.c b/gwobex/obex-xfer.c
> index 20a3221..413fed9 100644
> --- a/gwobex/obex-xfer.c
> +++ b/gwobex/obex-xfer.c
> @@ -472,6 +472,16 @@ void a_header_free(struct a_header *ah) {
> ? ? g_free(ah);
> ?}
>
> +struct a_header *a_header_find(GSList *aheaders, uint8_t hi) {
> + ? ?while (aheaders) {
Avoid casts, use a proper variable e.g. struct a_header *ah =
aheaders->data and avoid braces for single line if statements.
> + ? ? ? ?if (((struct a_header *)aheaders->data)->hi == hi) {
> + ? ? ? ? ? ?return aheaders->data;
> + ? ? ? ?}
> + ? ? ? ?aheaders = g_slist_next(aheaders);
> + ? ?}
> + ? ?return NULL;
> +}
> +
> ?void _gw_obex_xfer_free(struct gw_obex_xfer *xfer) {
> ? ? GSList *aheaders = xfer->aheaders;
> ? ? while (aheaders) {
> diff --git a/gwobex/obex-xfer.h b/gwobex/obex-xfer.h
> index 61aa048..50dadad 100644
> --- a/gwobex/obex-xfer.h
> +++ b/gwobex/obex-xfer.h
> @@ -95,6 +95,8 @@ void a_header_free(struct a_header *ah);
>
> ?struct a_header *a_header_copy(struct a_header *ah);
>
> +struct a_header *a_header_find(GSList *aheaders, uint8_t hi);
> +
> ?struct gw_obex_xfer *gw_obex_xfer_new(struct gw_obex *ctx, gboolean async, int stream_fd);
>
> ?void _gw_obex_xfer_free(struct gw_obex_xfer *xfer);
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
--
Luiz Augusto von Dentz
Hi Jakub,
On Sun, Jun 19, 2011 at 3:59 AM, Jakub Adamek <[email protected]> wrote:
> These are to be used by client for performing async get or put
> operations with sending additional headers.
> ---
> ?gwobex/gw-obex.h ? | ? 32 ++++++++++++++++++++++++++++++++
> ?gwobex/obex-xfer.c | ? 27 +++++++++++++++++++++++++++
> ?2 files changed, 59 insertions(+), 0 deletions(-)
>
> diff --git a/gwobex/gw-obex.h b/gwobex/gw-obex.h
> index 0638f45..238d695 100644
> --- a/gwobex/gw-obex.h
> +++ b/gwobex/gw-obex.h
> @@ -510,6 +510,24 @@ gboolean gw_obex_copy(GwObex *ctx, const gchar *src, const gchar *dst,
> ?GwObexXfer *gw_obex_put_async(GwObex *ctx, const char *name, const char *type,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? gint size, time_t time, gint *error);
>
> +/** Start a PUT operation asynchronously with additional headers
> + *
> + * @param ctx ? Pointer returned by gw_obex_setup()
> + * @param name ?Name of the object (null terminated UTF-8)
> + * @param type ?Type of the object (null terminated UTF-8), or NULL
> + * @param apparam ? ? ?Application parameters of the object
> + * @param apparam_size Application paramters' size
> + * @param aheaders ? ? ?List of additional headers
> + * @param size ?Size of the object (GW_OBEX_UNKNOWN_LENGTH if not known)
> + * @param time ?Last modification time of the object (-1 if not known)
> + * @param error Place to store error code on failure (NULL if not interested)
> + *
> + * @returns a new GwObexXfer object on success, NULL on failure
> + */
> +GwObexXfer *gw_obex_put_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const guint8 *apparam, gint apparam_size,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?const GSList *aheaders,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?gint size, time_t time, gint *error);
>
> ?/** Start a GET operation asynchronously
> ?*
> @@ -537,6 +555,20 @@ GwObexXfer *gw_obex_get_async(GwObex *ctx, const char *name, const char *type, g
> ?GwObexXfer *gw_obex_get_async_with_apparam(GwObex *ctx, const char *name, const char *type,
> ? ? ? ? ? ? ? ?const guint8 ?*apparam, gint apparam_size, gint *error);
>
> +/** Start a GET operation asynchronously with additional headers
> + *
> + * @param ctx ? Pointer returned by gw_obex_setup()
> + * @param name ?Name of the object (null terminated UTF-8)
> + * @param type ?Type of the object (null terminated UTF-8), or NULL
> + * @param aheaders ? ? ?List of additional headers
> + * @param error Place to store error code on failure (NULL if not interested)
> + *
> + * @returns a new GwObexXfer object on success, NULL on failure
> + */
> +
> +GwObexXfer *gw_obex_get_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
> + ? ? ? ?const guint8 *apparam, gint apparam_size,
> + ? ? ? ?const GSList *aheaders, gint *error);
>
> ?/** Set a callback function for a GwObexXfer object
> ?* The callback function will be called in the following situations:
> diff --git a/gwobex/obex-xfer.c b/gwobex/obex-xfer.c
> index 1430f10..6d65197 100644
> --- a/gwobex/obex-xfer.c
> +++ b/gwobex/obex-xfer.c
> @@ -124,6 +124,20 @@ GwObexXfer *gw_obex_put_async(GwObex *ctx, const char *name, const char *type,
> ? ? return ret ? ctx->xfer : NULL;
> ?}
>
> +GwObexXfer *gw_obex_put_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
> + ? ? ? ? ? ? ? const guint8 *apparam, gint apparam_size,
> + ? ? ? ?const GSList *aheaders,
> + ? ? ? ?gint size, time_t time, gint *error) {
> + ? ?gboolean ret;
> + ? ?GW_OBEX_LOCK(ctx);
> + ? ?CHECK_DISCONNECT(NULL, error, ctx);
> + ? ?ret = gw_obex_put_with_aheaders(ctx, NULL, name, type, apparam, apparam_size, aheaders, NULL, size, time, -1, TRUE);
It looks like this is well over 80 columns, isn't it?
> + ? ?if (ret == FALSE)
> + ? ? ? ?gw_obex_get_error(ctx, error);
> + ? ?GW_OBEX_UNLOCK(ctx);
> + ? ?return ret ? ctx->xfer : NULL;
> +}
> +
> ?GwObexXfer *gw_obex_get_async(GwObex *ctx, const char *name, const char *type, gint *error) {
> ? ? gboolean ret;
> ? ? GW_OBEX_LOCK(ctx);
> @@ -147,6 +161,19 @@ GwObexXfer *gw_obex_get_async_with_apparam(GwObex *ctx, const char *name, const
> ? ? return ret ? ctx->xfer : NULL;
> ?}
>
> +GwObexXfer *gw_obex_get_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
> + ? ? ? ? ? ? ? const guint8 *apparam, gint apparam_size,
> + ? ? ? ?const GSList *aheaders, gint *error) {
> + ? ?gboolean ret;
> + ? ?GW_OBEX_LOCK(ctx);
> + ? ?CHECK_DISCONNECT(NULL, error, ctx);
> + ? ?ret = gw_obex_get_with_aheaders(ctx, NULL, name, type, apparam, apparam_size, aheaders, NULL, NULL, -1, TRUE);
This too,
> + ? ?if (ret == FALSE)
> + ? ? ? ?gw_obex_get_error(ctx, error);
> + ? ?GW_OBEX_UNLOCK(ctx);
> + ? ?return ret ? ctx->xfer : NULL;
> +}
> +
> ?static gboolean gw_obex_put_idle(GwObexXfer *xfer) {
> ? ? struct gw_obex *ctx = xfer->ctx;
>
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>
--
Luiz Augusto von Dentz
Hi Jakub,
On Sun, Jun 19, 2011 at 3:59 AM, Jakub Adamek <[email protected]> wrote:
> ---
> ?gwobex/obex-priv.c | ? 22 ++++++++++++++++++++++
> ?1 files changed, 22 insertions(+), 0 deletions(-)
>
> diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
> index aba7dd7..b9216e5 100644
> --- a/gwobex/obex-priv.c
> +++ b/gwobex/obex-priv.c
> @@ -39,6 +39,7 @@
> ?#include <sys/socket.h>
>
> ?#include <openobex/obex.h>
> +#include <openobex/obex_const.h>
>
> ?#ifdef HAVE_CONFIG_H
> ?# include "config.h"
> @@ -335,6 +336,7 @@ static void get_non_body_headers(obex_t *handle, obex_object_t *object,
> ? ? obex_headerdata_t hv;
> ? ? uint8_t hi;
> ? ? unsigned int hlen;
> + ? ?struct a_header *ah;
>
> ? ? xfer->target_size = GW_OBEX_UNKNOWN_LENGTH;
> ? ? xfer->modtime = -1;
> @@ -358,6 +360,26 @@ static void get_non_body_headers(obex_t *handle, obex_object_t *object,
> ? ? ? ? ? ? ? ? ? ? xfer->apparam_size = 0;
> ? ? ? ? ? ? ? ? break;
> ? ? ? ? ? ? default:
> + ? ? ? ? ? ? ? ?ah = g_new0(struct a_header, 1);
> + ? ? ? ? ? ? ? ?ah->hi = hi;
> + ? ? ? ? ? ? ? ?ah->hv_size = hlen;
> + ? ? ? ? ? ? ? ?switch (hi & OBEX_HDR_TYPE_MASK) {
> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_UINT8:
> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_UINT32:
> + ? ? ? ? ? ? ? ? ? ? ? ?ah->hv = hv;
> + ? ? ? ? ? ? ? ? ? ? ? ?break;
> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_BYTES:
> + ? ? ? ? ? ? ? ? ? ?case OBEX_HDR_TYPE_UNICODE:
> + ? ? ? ? ? ? ? ? ? ? ? ?ah->hv.bs = g_try_malloc(hlen);
> + ? ? ? ? ? ? ? ? ? ? ? ?if (ah->hv.bs) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?memcpy((void *) ah->hv.bs, hv.bs, hlen);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?ah->hv_size = hlen;
> + ? ? ? ? ? ? ? ? ? ? ? ?} else {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ?ah->hv_size = hlen;
> + ? ? ? ? ? ? ? ? ? ? ? ?}
No need to add braces for single line statements.
> + ? ? ? ? ? ? ? ? ? ? ? ?break;
> + ? ? ? ? ? ? ? ?}
> + ? ? ? ? ? ? ? ?xfer->aheaders = g_slist_append(xfer->aheaders, ah);
I would suggest having this code separated in another function e.g.
get_aheader, it is easier to identify what the code is doing and
switch inside a switch is not very nice to read/understand IMO.
--
Luiz Augusto von Dentz
---
gwobex/obex-xfer.c | 10 ++++++++++
gwobex/obex-xfer.h | 2 ++
2 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/gwobex/obex-xfer.c b/gwobex/obex-xfer.c
index 20a3221..413fed9 100644
--- a/gwobex/obex-xfer.c
+++ b/gwobex/obex-xfer.c
@@ -472,6 +472,16 @@ void a_header_free(struct a_header *ah) {
g_free(ah);
}
+struct a_header *a_header_find(GSList *aheaders, uint8_t hi) {
+ while (aheaders) {
+ if (((struct a_header *)aheaders->data)->hi == hi) {
+ return aheaders->data;
+ }
+ aheaders = g_slist_next(aheaders);
+ }
+ return NULL;
+}
+
void _gw_obex_xfer_free(struct gw_obex_xfer *xfer) {
GSList *aheaders = xfer->aheaders;
while (aheaders) {
diff --git a/gwobex/obex-xfer.h b/gwobex/obex-xfer.h
index 61aa048..50dadad 100644
--- a/gwobex/obex-xfer.h
+++ b/gwobex/obex-xfer.h
@@ -95,6 +95,8 @@ void a_header_free(struct a_header *ah);
struct a_header *a_header_copy(struct a_header *ah);
+struct a_header *a_header_find(GSList *aheaders, uint8_t hi);
+
struct gw_obex_xfer *gw_obex_xfer_new(struct gw_obex *ctx, gboolean async, int stream_fd);
void _gw_obex_xfer_free(struct gw_obex_xfer *xfer);
--
1.7.0.4
These are to be used by client for performing async get or put
operations with sending additional headers.
---
gwobex/gw-obex.h | 32 ++++++++++++++++++++++++++++++++
gwobex/obex-xfer.c | 27 +++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/gwobex/gw-obex.h b/gwobex/gw-obex.h
index 0638f45..238d695 100644
--- a/gwobex/gw-obex.h
+++ b/gwobex/gw-obex.h
@@ -510,6 +510,24 @@ gboolean gw_obex_copy(GwObex *ctx, const gchar *src, const gchar *dst,
GwObexXfer *gw_obex_put_async(GwObex *ctx, const char *name, const char *type,
gint size, time_t time, gint *error);
+/** Start a PUT operation asynchronously with additional headers
+ *
+ * @param ctx Pointer returned by gw_obex_setup()
+ * @param name Name of the object (null terminated UTF-8)
+ * @param type Type of the object (null terminated UTF-8), or NULL
+ * @param apparam Application parameters of the object
+ * @param apparam_size Application paramters' size
+ * @param aheaders List of additional headers
+ * @param size Size of the object (GW_OBEX_UNKNOWN_LENGTH if not known)
+ * @param time Last modification time of the object (-1 if not known)
+ * @param error Place to store error code on failure (NULL if not interested)
+ *
+ * @returns a new GwObexXfer object on success, NULL on failure
+ */
+GwObexXfer *gw_obex_put_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders,
+ gint size, time_t time, gint *error);
/** Start a GET operation asynchronously
*
@@ -537,6 +555,20 @@ GwObexXfer *gw_obex_get_async(GwObex *ctx, const char *name, const char *type, g
GwObexXfer *gw_obex_get_async_with_apparam(GwObex *ctx, const char *name, const char *type,
const guint8 *apparam, gint apparam_size, gint *error);
+/** Start a GET operation asynchronously with additional headers
+ *
+ * @param ctx Pointer returned by gw_obex_setup()
+ * @param name Name of the object (null terminated UTF-8)
+ * @param type Type of the object (null terminated UTF-8), or NULL
+ * @param aheaders List of additional headers
+ * @param error Place to store error code on failure (NULL if not interested)
+ *
+ * @returns a new GwObexXfer object on success, NULL on failure
+ */
+
+GwObexXfer *gw_obex_get_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders, gint *error);
/** Set a callback function for a GwObexXfer object
* The callback function will be called in the following situations:
diff --git a/gwobex/obex-xfer.c b/gwobex/obex-xfer.c
index 1430f10..6d65197 100644
--- a/gwobex/obex-xfer.c
+++ b/gwobex/obex-xfer.c
@@ -124,6 +124,20 @@ GwObexXfer *gw_obex_put_async(GwObex *ctx, const char *name, const char *type,
return ret ? ctx->xfer : NULL;
}
+GwObexXfer *gw_obex_put_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders,
+ gint size, time_t time, gint *error) {
+ gboolean ret;
+ GW_OBEX_LOCK(ctx);
+ CHECK_DISCONNECT(NULL, error, ctx);
+ ret = gw_obex_put_with_aheaders(ctx, NULL, name, type, apparam, apparam_size, aheaders, NULL, size, time, -1, TRUE);
+ if (ret == FALSE)
+ gw_obex_get_error(ctx, error);
+ GW_OBEX_UNLOCK(ctx);
+ return ret ? ctx->xfer : NULL;
+}
+
GwObexXfer *gw_obex_get_async(GwObex *ctx, const char *name, const char *type, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
@@ -147,6 +161,19 @@ GwObexXfer *gw_obex_get_async_with_apparam(GwObex *ctx, const char *name, const
return ret ? ctx->xfer : NULL;
}
+GwObexXfer *gw_obex_get_async_with_aheaders(GwObex *ctx, const char *name, const char *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders, gint *error) {
+ gboolean ret;
+ GW_OBEX_LOCK(ctx);
+ CHECK_DISCONNECT(NULL, error, ctx);
+ ret = gw_obex_get_with_aheaders(ctx, NULL, name, type, apparam, apparam_size, aheaders, NULL, NULL, -1, TRUE);
+ if (ret == FALSE)
+ gw_obex_get_error(ctx, error);
+ GW_OBEX_UNLOCK(ctx);
+ return ret ? ctx->xfer : NULL;
+}
+
static gboolean gw_obex_put_idle(GwObexXfer *xfer) {
struct gw_obex *ctx = xfer->ctx;
--
1.7.0.4
---
gwobex/obex-xfer.c | 13 +++++++++++++
gwobex/obex-xfer.h | 2 ++
2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/gwobex/obex-xfer.c b/gwobex/obex-xfer.c
index 6d65197..20a3221 100644
--- a/gwobex/obex-xfer.c
+++ b/gwobex/obex-xfer.c
@@ -449,6 +449,19 @@ out:
return ret;
}
+struct a_header *a_header_copy(struct a_header *ah) {
+ struct a_header *res;
+ if(!ah) return NULL;
+ res = g_memdup(ah, sizeof(struct a_header));
+ switch (res->hi & OBEX_HDR_TYPE_MASK) {
+ case OBEX_HDR_TYPE_BYTES:
+ case OBEX_HDR_TYPE_UNICODE:
+ res->hv.bs = g_memdup(ah->hv.bs, ah->hv_size);
+ break;
+ }
+ return res;
+}
+
void a_header_free(struct a_header *ah) {
switch (ah->hi & OBEX_HDR_TYPE_MASK) {
case OBEX_HDR_TYPE_BYTES:
diff --git a/gwobex/obex-xfer.h b/gwobex/obex-xfer.h
index b1e2ff0..61aa048 100644
--- a/gwobex/obex-xfer.h
+++ b/gwobex/obex-xfer.h
@@ -93,6 +93,8 @@ struct a_header {
void a_header_free(struct a_header *ah);
+struct a_header *a_header_copy(struct a_header *ah);
+
struct gw_obex_xfer *gw_obex_xfer_new(struct gw_obex *ctx, gboolean async, int stream_fd);
void _gw_obex_xfer_free(struct gw_obex_xfer *xfer);
--
1.7.0.4
---
gwobex/obex-priv.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
index 5d3b458..c8043e1 100644
--- a/gwobex/obex-priv.c
+++ b/gwobex/obex-priv.c
@@ -362,7 +362,7 @@ static void obex_request_done(GwObex *ctx, obex_object_t *object,
ctx->obex_rsp = obex_rsp;
- if (obex_rsp != OBEX_RSP_SUCCESS) {
+ if (obex_rsp != OBEX_RSP_SUCCESS && obex_rsp != OBEX_RSP_PARTIAL_CONTENT) {
debug("%s command (0x%02x) failed: %s (0x%02x)\n",
optostr((uint8_t)obex_cmd), (uint8_t)obex_cmd,
OBEX_ResponseToString(obex_rsp), (uint8_t)obex_rsp);
--
1.7.0.4
---
gwobex/obex-priv.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
index c986744..5d3b458 100644
--- a/gwobex/obex-priv.c
+++ b/gwobex/obex-priv.c
@@ -898,11 +898,6 @@ gboolean gw_obex_get_with_aheaders(GwObex *ctx,
OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_CONNECTION, hv, 4, 0);
}
- if (apparam && apparam_size > 0) {
- hv.bs = (unsigned char *)apparam;
- OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_APPARAM, hv, apparam_size, 0);
- }
-
if (type) {
hv.bs = (unsigned char *)type;
OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_TYPE, hv, strlen(type) + 1, 0);
@@ -939,6 +934,11 @@ gboolean gw_obex_get_with_aheaders(GwObex *ctx,
}
}
+ if (apparam && apparam_size > 0) {
+ hv.bs = (unsigned char *)apparam;
+ OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_APPARAM, hv, apparam_size, 0);
+ }
+
if (aheaders) {
const GSList *hlist = aheaders;
struct a_header *ah;
@@ -1073,6 +1073,11 @@ gboolean gw_obex_put_with_aheaders(GwObex *ctx,
OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_CONNECTION, hv, 4, 0);
}
+ if (type) {
+ hv.bs = (unsigned char *)type;
+ OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_TYPE, hv, strlen(type) + 1, 0);
+ }
+
if (uname) {
hv.bs = (unsigned char *)uname;
OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_NAME, hv, uname_len, 0);
@@ -1080,11 +1085,6 @@ gboolean gw_obex_put_with_aheaders(GwObex *ctx,
uname = NULL;
}
- if (type) {
- hv.bs = (unsigned char *)type;
- OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_TYPE, hv, strlen(type) + 1, 0);
- }
-
if (apparam && apparam_size > 0) {
hv.bs = (unsigned char *)apparam;
OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_APPARAM, hv, apparam_size, 0);
--
1.7.0.4
These are for internal use by gwobex.
---
gwobex/obex-priv.c | 42 +++++++++++++++++++++++++++++++++++++++++-
gwobex/obex-priv.h | 29 +++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 1 deletions(-)
diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
index b9216e5..93a310b 100644
--- a/gwobex/obex-priv.c
+++ b/gwobex/obex-priv.c
@@ -863,6 +863,15 @@ gboolean gw_obex_get(GwObex *ctx,
const guint8 *apparam, gint apparam_size,
gchar **buf, gint *buf_size, int stream_fd,
gboolean async) {
+ return gw_obex_get_with_aheaders(ctx, local, remote, type, apparam, apparam_size,
+ NULL, buf, buf_size, stream_fd, async);
+}
+
+gboolean gw_obex_get_with_aheaders(GwObex *ctx,
+ const gchar *local, const gchar *remote, const gchar *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders, gchar **buf, gint *buf_size, int stream_fd,
+ gboolean async) {
gboolean ret = FALSE;
obex_headerdata_t hv;
obex_object_t *object;
@@ -927,6 +936,17 @@ gboolean gw_obex_get(GwObex *ctx,
}
}
+ if (aheaders) {
+ const GSList *hlist = aheaders;
+ struct a_header *ah;
+ while (hlist) {
+ ah = hlist->data;
+ hv = ah->hv;
+ OBEX_ObjectAddHeader(ctx->handle, object, ah->hi, hv, ah->hv_size, 0);
+ hlist = g_slist_next(hlist);
+ }
+ }
+
OBEX_ObjectReadStream(ctx->handle, object, NULL);
if (async) {
@@ -980,6 +1000,15 @@ gboolean gw_obex_put(GwObex *ctx,
const guint8 *apparam, gint apparam_size,
const gchar *buf, gint object_size, time_t object_time,
int stream_fd, gboolean async) {
+ return gw_obex_put_with_aheaders(ctx, local, remote, type, apparam, apparam_size,
+ NULL, buf, object_size, object_time, stream_fd, async);
+}
+
+gboolean gw_obex_put_with_aheaders(GwObex *ctx,
+ const gchar *local, const gchar *remote, const gchar *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders, const gchar *buf, gint object_size, time_t object_time,
+ int stream_fd, gboolean async) {
gboolean ret = FALSE;
obex_headerdata_t hv;
obex_object_t *object;
@@ -1052,12 +1081,23 @@ gboolean gw_obex_put(GwObex *ctx,
hv.bs = (unsigned char *)type;
OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_TYPE, hv, strlen(type) + 1, 0);
}
-
+
if (apparam && apparam_size > 0) {
hv.bs = (unsigned char *)apparam;
OBEX_ObjectAddHeader(ctx->handle, object, OBEX_HDR_APPARAM, hv, apparam_size, 0);
}
+ if (aheaders) {
+ const GSList *hlist = aheaders;
+ struct a_header *ah;
+ while (hlist) {
+ ah = hlist->data;
+ hv = ah->hv;
+ OBEX_ObjectAddHeader(ctx->handle, object, ah->hi, hv, ah->hv_size, 0);
+ hlist = g_slist_next(hlist);
+ }
+ }
+
/* Try to figure out modification time if none was given */
if (ctx->xfer->stream_fd >= 0) {
struct stat stats;
diff --git a/gwobex/obex-priv.h b/gwobex/obex-priv.h
index f4e3e5b..c0548b0 100644
--- a/gwobex/obex-priv.h
+++ b/gwobex/obex-priv.h
@@ -214,4 +214,33 @@ gboolean gw_obex_put(GwObex *ctx,
const gchar *buf, gint buf_size, time_t object_time,
int stream_fd, gboolean async);
+
+/** Get an object from the server, specifying additional headers
+ * @param ctx Pointer returned by gw_obex_setup()
+ * @param local Local filename which contains the object
+ * @param remote Remote filename to store the object in
+ * @param type MIME-type of the object (NULL if not known)
+ * @param aheaders list of additional headers (NULL if empty)
+ * @returns TRUE on success, FALSE on failure
+ */
+gboolean gw_obex_get_with_aheaders(GwObex *ctx,
+ const gchar *local, const gchar *remote, const gchar *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders, gchar **buf, gint *buf_size, int stream_fd,
+ gboolean async);
+
+/** Send an object to the server
+ * @param ctx Pointer returned by gw_obex_setup()
+ * @param local Local filename to store the objec in
+ * @param remote Remote filename which contains the object
+ * @param type MIME-type of the object (NULL if not known)
+ * @param aheaders list of additional headers (NULL if empty)
+ * @returns TRUE on success, FALSE on failure
+ */
+gboolean gw_obex_put_with_aheaders(GwObex *ctx,
+ const gchar *local, const gchar *remote, const gchar *type,
+ const guint8 *apparam, gint apparam_size,
+ const GSList *aheaders, const gchar *buf, gint buf_size, time_t object_time,
+ int stream_fd, gboolean async);
+
#endif /* _OBEX_PRIV_H_ */
--
1.7.0.4
---
gwobex/obex-priv.c | 69 +++++++++++++++++++++++++++-------------------------
1 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
index 93a310b..c986744 100644
--- a/gwobex/obex-priv.c
+++ b/gwobex/obex-priv.c
@@ -298,39 +298,6 @@ static void obex_abort_done(GwObex *ctx, obex_object_t *object,
optostr((uint8_t)obex_cmd), (uint8_t)obex_cmd);
}
-static void obex_request_done(GwObex *ctx, obex_object_t *object,
- int obex_cmd, int obex_rsp) {
- ctx->done = TRUE;
- if (ctx->xfer)
- ctx->xfer->do_cb = TRUE;
-
- ctx->obex_rsp = obex_rsp;
-
- if (obex_rsp != OBEX_RSP_SUCCESS) {
- debug("%s command (0x%02x) failed: %s (0x%02x)\n",
- optostr((uint8_t)obex_cmd), (uint8_t)obex_cmd,
- OBEX_ResponseToString(obex_rsp), (uint8_t)obex_rsp);
-#ifdef DEBUG
- if (obex_rsp == OBEX_RSP_UNAUTHORIZED) {
- debug("Showing headers..\n");
- show_headers(ctx->handle, object);
- }
-#endif
- return;
- }
-
- debug("%s command (0x%02x) succeeded.\n", optostr((uint8_t)obex_cmd),
- (uint8_t)obex_cmd);
-
- switch (obex_cmd) {
- case OBEX_CMD_CONNECT:
- obex_connect_done(ctx, object, obex_rsp);
- break;
- default:
- break;
- }
-}
-
static void get_non_body_headers(obex_t *handle, obex_object_t *object,
struct gw_obex_xfer *xfer) {
obex_headerdata_t hv;
@@ -387,6 +354,42 @@ static void get_non_body_headers(obex_t *handle, obex_object_t *object,
OBEX_ObjectReParseHeaders(handle, object);
}
+static void obex_request_done(GwObex *ctx, obex_object_t *object,
+ int obex_cmd, int obex_rsp) {
+ ctx->done = TRUE;
+ if (ctx->xfer)
+ ctx->xfer->do_cb = TRUE;
+
+ ctx->obex_rsp = obex_rsp;
+
+ if (obex_rsp != OBEX_RSP_SUCCESS) {
+ debug("%s command (0x%02x) failed: %s (0x%02x)\n",
+ optostr((uint8_t)obex_cmd), (uint8_t)obex_cmd,
+ OBEX_ResponseToString(obex_rsp), (uint8_t)obex_rsp);
+#ifdef DEBUG
+ if (obex_rsp == OBEX_RSP_UNAUTHORIZED) {
+ debug("Showing headers..\n");
+ show_headers(ctx->handle, object);
+ }
+#endif
+ return;
+ }
+
+ if (ctx->xfer)
+ get_non_body_headers(ctx->handle, object, ctx->xfer);
+
+ debug("%s command (0x%02x) succeeded.\n", optostr((uint8_t)obex_cmd),
+ (uint8_t)obex_cmd);
+
+ switch (obex_cmd) {
+ case OBEX_CMD_CONNECT:
+ obex_connect_done(ctx, object, obex_rsp);
+ break;
+ default:
+ break;
+ }
+}
+
static void obex_readstream(GwObex *ctx, obex_object_t *object) {
struct gw_obex_xfer *xfer = ctx->xfer;
const uint8_t *buf;
--
1.7.0.4
---
gwobex/obex-priv.c | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
index aba7dd7..b9216e5 100644
--- a/gwobex/obex-priv.c
+++ b/gwobex/obex-priv.c
@@ -39,6 +39,7 @@
#include <sys/socket.h>
#include <openobex/obex.h>
+#include <openobex/obex_const.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -335,6 +336,7 @@ static void get_non_body_headers(obex_t *handle, obex_object_t *object,
obex_headerdata_t hv;
uint8_t hi;
unsigned int hlen;
+ struct a_header *ah;
xfer->target_size = GW_OBEX_UNKNOWN_LENGTH;
xfer->modtime = -1;
@@ -358,6 +360,26 @@ static void get_non_body_headers(obex_t *handle, obex_object_t *object,
xfer->apparam_size = 0;
break;
default:
+ ah = g_new0(struct a_header, 1);
+ ah->hi = hi;
+ ah->hv_size = hlen;
+ switch (hi & OBEX_HDR_TYPE_MASK) {
+ case OBEX_HDR_TYPE_UINT8:
+ case OBEX_HDR_TYPE_UINT32:
+ ah->hv = hv;
+ break;
+ case OBEX_HDR_TYPE_BYTES:
+ case OBEX_HDR_TYPE_UNICODE:
+ ah->hv.bs = g_try_malloc(hlen);
+ if (ah->hv.bs) {
+ memcpy((void *) ah->hv.bs, hv.bs, hlen);
+ ah->hv_size = hlen;
+ } else {
+ ah->hv_size = hlen;
+ }
+ break;
+ }
+ xfer->aheaders = g_slist_append(xfer->aheaders, ah);
break;
}
}
--
1.7.0.4
The list is a GSList of a_header structs added to gw_obex_xfer for
storing received a_header objects.
---
gwobex/gw-obex.h | 7 +++++++
gwobex/obex-xfer.c | 20 ++++++++++++++++++++
gwobex/obex-xfer.h | 5 +++++
3 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/gwobex/gw-obex.h b/gwobex/gw-obex.h
index c858341..0638f45 100644
--- a/gwobex/gw-obex.h
+++ b/gwobex/gw-obex.h
@@ -583,6 +583,13 @@ gint gw_obex_xfer_object_size(GwObexXfer *xfer);
*/
unsigned char *gw_obex_xfer_object_apparam(GwObexXfer *xfer, size_t *apparam_size);
+/** Get the additional header list
+ *
+ * @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
+ *
+ * @returns The pointer to the GSList that contains the headers
+ */
+GSList *gw_obex_xfer_object_aheaders(GwObexXfer *xfer);
/** Returns if a transfer is already done
*
diff --git a/gwobex/obex-xfer.c b/gwobex/obex-xfer.c
index 4013687..1430f10 100644
--- a/gwobex/obex-xfer.c
+++ b/gwobex/obex-xfer.c
@@ -202,6 +202,10 @@ unsigned char *gw_obex_xfer_object_apparam(GwObexXfer *xfer, size_t *apparam_siz
return xfer->apparam_buf;
}
+GSList *gw_obex_xfer_object_aheaders(GwObexXfer *xfer) {
+ return xfer->aheaders;
+}
+
gboolean gw_obex_xfer_object_done(GwObexXfer *xfer) {
return xfer->ctx->done;
}
@@ -418,7 +422,23 @@ out:
return ret;
}
+void a_header_free(struct a_header *ah) {
+ switch (ah->hi & OBEX_HDR_TYPE_MASK) {
+ case OBEX_HDR_TYPE_BYTES:
+ case OBEX_HDR_TYPE_UNICODE:
+ g_free((gpointer) ah->hv.bs);
+ break;
+ }
+ g_free(ah);
+}
+
void _gw_obex_xfer_free(struct gw_obex_xfer *xfer) {
+ GSList *aheaders = xfer->aheaders;
+ while (aheaders) {
+ a_header_free(aheaders->data);
+ aheaders = g_slist_next(aheaders);
+ }
+ g_slist_free(xfer->aheaders);
g_free(xfer->buf);
g_free(xfer->apparam_buf);
g_free(xfer);
diff --git a/gwobex/obex-xfer.h b/gwobex/obex-xfer.h
index 9bc832d..b1e2ff0 100644
--- a/gwobex/obex-xfer.h
+++ b/gwobex/obex-xfer.h
@@ -62,6 +62,9 @@ struct gw_obex_xfer {
unsigned char *apparam_buf;
size_t apparam_size;
+ /* Additional headers, in the order they were received */
+ GSList *aheaders;
+
/* These two elements are only used for async transfers */
size_t data_start;
size_t data_length;
@@ -88,6 +91,8 @@ struct a_header {
uint32_t hv_size;
};
+void a_header_free(struct a_header *ah);
+
struct gw_obex_xfer *gw_obex_xfer_new(struct gw_obex *ctx, gboolean async, int stream_fd);
void _gw_obex_xfer_free(struct gw_obex_xfer *xfer);
--
1.7.0.4
---
gwobex/obex-xfer.h | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/gwobex/obex-xfer.h b/gwobex/obex-xfer.h
index 5a88b13..9bc832d 100644
--- a/gwobex/obex-xfer.h
+++ b/gwobex/obex-xfer.h
@@ -82,6 +82,12 @@ struct gw_obex_xfer {
GSource *idle_source;
};
+struct a_header {
+ uint8_t hi;
+ obex_headerdata_t hv;
+ uint32_t hv_size;
+};
+
struct gw_obex_xfer *gw_obex_xfer_new(struct gw_obex *ctx, gboolean async, int stream_fd);
void _gw_obex_xfer_free(struct gw_obex_xfer *xfer);
--
1.7.0.4