obexd: Remove gwobex

Not needed anymore since obex-client now uses gobex.
This commit is contained in:
Johan Hedberg 2011-09-01 15:24:28 +03:00 committed by Marcel Holtmann
parent 0e31d0f56b
commit 15f6d2e1f8
9 changed files with 0 additions and 3307 deletions

View File

@ -1,404 +0,0 @@
/**
@file gw-obex.c
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <glib.h>
#include "log.h"
#include "gw-obex.h"
#include "utils.h"
#include "obex-xfer.h"
#include "obex-priv.h"
gboolean gw_obex_get_file(GwObex *ctx,
const gchar *local,
const gchar *remote,
const gchar *type,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_get(ctx, local, remote, type, NULL, 0, NULL, NULL, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_get_fd(GwObex *ctx,
gint fd,
const gchar *remote,
const gchar *type,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_get(ctx, NULL, remote, type, NULL, 0, NULL, NULL, fd, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_put_fd(GwObex *ctx,
gint fd,
const gchar *remote,
const gchar *type,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_put(ctx, NULL, remote, type, NULL, 0, NULL, 0, -1, fd, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_put_file(GwObex *ctx,
const gchar *local,
const gchar *remote,
const gchar *type,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_put(ctx, local, remote, type, NULL, 0, NULL, 0, -1, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_get_buf(GwObex *ctx,
const gchar *remote,
const gchar *type,
gchar **buf,
gint *buf_size,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_get(ctx, NULL, remote, type, NULL, 0, buf, buf_size, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_put_buf(GwObex *ctx,
const gchar *remote,
const gchar *type,
const gchar *buf,
gint buf_size,
gint time,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_put(ctx, NULL, remote, type, NULL, 0, buf, buf_size, time, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_get_buf_with_apparam(GwObex *ctx,
const gchar *remote,
const gchar *type,
const guint8 *apparam,
gint apparam_size,
gchar **buf,
gint *buf_size,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_get(ctx, NULL, remote, type, apparam, apparam_size, buf, buf_size, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_put_buf_with_apparam(GwObex *ctx,
const gchar *remote,
const gchar *type,
const guint8 *apparam,
gint apparam_size,
const gchar *buf,
gint buf_size,
gint time,
gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_put(ctx, NULL, remote, type, apparam, apparam_size, buf, buf_size, time, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_chdir(GwObex *ctx, const gchar *dir, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_setpath(ctx, dir ? dir : "", 0);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_mkdir(GwObex *ctx, const gchar *dir, gint *error) {
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
if (!gw_obex_setpath(ctx, dir ? dir : "", SETPATH_CREATE)) {
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return FALSE;
}
(void) gw_obex_setpath(ctx, "..", 0);
GW_OBEX_UNLOCK(ctx);
return TRUE;
}
gboolean gw_obex_read_dir(GwObex *ctx, const gchar *dir,
gchar **buf, gint *buf_size, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_get(ctx, NULL, dir ? dir : "", LST_TYPE, NULL, 0, buf, buf_size, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
else if (*buf_size > 0) {
/* Hack for some OBEX implementations which send nul's
* at the end of the listing */
int i;
for (i = *buf_size - 1; i > 0; i--) {
if ((*buf)[i] == '\0')
(*buf_size)--;
else
break;
}
}
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_delete(GwObex *ctx, const gchar *name, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_put(ctx, NULL, name, NULL, NULL, 0, NULL, 0, -1, -1, FALSE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_move(GwObex *ctx, const gchar *src, const gchar *dst, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_action_op(ctx, src, dst, OBEX_ACTION_MOVE);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_copy(GwObex *ctx, const gchar *src, const gchar *dst, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_action_op(ctx, src, dst, OBEX_ACTION_COPY);
if (ret == FALSE)
gw_obex_get_error(ctx, error);
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_get_capability(GwObex *ctx, gchar **cap, gint *cap_len, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(FALSE, error, ctx);
ret = gw_obex_get(ctx, NULL, NULL, CAP_TYPE, NULL, 0, cap, cap_len, -1, FALSE);
if (ret == FALSE) {
*cap = NULL;
*cap_len = 0;
gw_obex_get_error(ctx, error);
}
GW_OBEX_UNLOCK(ctx);
return ret;
}
void gw_obex_set_disconnect_callback(GwObex *ctx, gw_obex_disconnect_cb_t callback, gpointer data) {
GW_OBEX_LOCK(ctx);
ctx->dc_cb = callback;
ctx->dc_data = data;
GW_OBEX_UNLOCK(ctx);
}
void gw_obex_set_progress_callback(GwObex *ctx, gw_obex_progress_cb_t callback, gpointer data) {
GW_OBEX_LOCK(ctx);
ctx->pr_cb = callback;
ctx->pr_data = data;
GW_OBEX_UNLOCK(ctx);
}
void gw_obex_set_cancel_callback(GwObex *ctx, gw_obex_cancel_cb_t callback, gpointer data) {
GW_OBEX_LOCK(ctx);
ctx->cancel_cb = callback;
ctx->cancel_data = data;
GW_OBEX_UNLOCK(ctx);
}
void gw_obex_close(GwObex *ctx) {
GW_OBEX_LOCK(ctx);
if (ctx->xfer) {
GwObexXfer *xfer = ctx->xfer;
GW_OBEX_UNLOCK(ctx);
gw_obex_xfer_close(ctx->xfer, NULL);
GW_OBEX_LOCK(ctx);
/* In the async case the caller of put/get_async owns the xfer object */
if (!xfer->async)
_gw_obex_xfer_free(xfer);
ctx->xfer = NULL;
}
if (ctx->conn_fd >= 0) {
if (!gw_obex_disconnect(ctx))
debug("OBEX Disconnect command failed\n");
OBEX_TransportDisconnect(ctx->handle);
close(ctx->conn_fd);
ctx->conn_fd = -1;
}
if (ctx->handle) {
OBEX_Cleanup(ctx->handle);
ctx->handle = NULL;
}
if (ctx->gio) {
g_io_channel_unref(ctx->gio);
ctx->gio = NULL;
}
if (ctx->gio_source) {
g_source_destroy(ctx->gio_source);
ctx->gio_source = NULL;
}
GW_OBEX_UNLOCK(ctx);
#ifdef GW_OBEX_THREADS_ENABLED
g_mutex_free(ctx->mutex);
ctx->mutex = NULL;
#endif
g_free(ctx);
}
GwObex *gw_obex_setup_fd(int fd, const gchar *uuid, gint uuid_len,
GMainContext *context, gint *error) {
obex_t *handle;
GwObex *ctx;
if (!gw_obex_transport_setup(fd, &handle)) {
debug("gw_obex_open() failed\n");
if (error)
*error = GW_OBEX_ERROR_CONNECT_FAILED;
return NULL;
}
debug("Transport connection opened.\n");
ctx = make_context(handle);
#ifdef GW_OBEX_THREADS_ENABLED
if (!g_thread_supported())
g_thread_init(NULL);
ctx->mutex = g_mutex_new();
#endif
OBEX_SetUserData(handle, ctx);
debug("Connecting to OBEX service\n");
if (!gw_obex_connect(ctx, uuid, uuid_len)) {
debug("Unable to connect to OBEX service\n");
#ifdef GW_OBEX_THREADS_ENABLED
g_mutex_free(ctx->mutex);
ctx->mutex = NULL;
#endif
g_free(ctx);
OBEX_Cleanup(handle);
if (error)
*error = GW_OBEX_ERROR_NO_SERVICE;
return NULL;
}
debug("Connected (Connection ID: %#x)\n", ctx->conid);
ctx->gio = g_io_channel_unix_new(ctx->conn_fd);
ctx->gio_source = g_io_create_watch (ctx->gio,
G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL);
g_source_set_callback(ctx->gio_source, (GSourceFunc)gw_obex_cb, ctx, NULL);
(void) g_source_attach(ctx->gio_source, context);
g_source_unref(ctx->gio_source);
ctx->main_ctx = context;
return ctx;
}
GwObex *gw_obex_setup_dev(const char *dev, const gchar *uuid, gint uuid_len,
GMainContext *context, gint *error) {
GwObex *ctx;
int fd;
fd = open(dev, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
debug("open(\"%s\"): %s\n", dev, strerror(errno));
if (error)
*error = GW_OBEX_ERROR_CONNECT_FAILED;
return NULL;
}
if (!fd_raw_mode(fd)) {
debug("setting raw mode failed\n");
close(fd);
if (error)
*error = GW_OBEX_ERROR_CONNECT_FAILED;
return NULL;
}
ctx = gw_obex_setup_fd(fd, uuid, uuid_len, context, error);
if (ctx == NULL) {
close(fd);
}
return ctx;
}

View File

@ -1,683 +0,0 @@
/**
@file gw-obex.h
OSSO GW OBEX Connectivity Library and API
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004-2005 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _GW_OBEX_H_
#define _GW_OBEX_H_
#include <glib.h>
#include <openobex/obex.h>
/**
* @name GW OBEX Error Codes
* The error codes returned by many of the functions refer either to an OBEX
* Protocol error or to a GW OBEX error. If the error code is less that 256, it
* refers to an OBEX error, othervice it refers to a GW_OBEX_ERROR_* error.
* @{
*/
/** Transport connection was disconnected */
#define GW_OBEX_ERROR_DISCONNECT 256
/** Operation was aborted */
#define GW_OBEX_ERROR_ABORT 257
/** GW OBEX internal error */
#define GW_OBEX_ERROR_INTERNAL 258
/** Unable to connecto to the specified service (UUID) */
#define GW_OBEX_ERROR_NO_SERVICE 259
/** Unable to create connection */
#define GW_OBEX_ERROR_CONNECT_FAILED 260
/** Timeout while waiting for data from the remote device */
#define GW_OBEX_ERROR_TIMEOUT 261
/** Remote device returned invalid/corrupted data */
#define GW_OBEX_ERROR_INVALID_DATA 262
/** Invalid parameters given to gwobex */
#define GW_OBEX_ERROR_INVALID_PARAMS 263
/** Local access error (e.g. read/write/open failed for local file) */
#define GW_OBEX_ERROR_LOCAL_ACCESS 264
/** Another operation is in progress */
#define GW_OBEX_ERROR_BUSY 265
/** No data currently available */
#define GW_OBEX_ERROR_NO_DATA 266
/** @} */
/** Value used if target length for put or get is not known */
#define GW_OBEX_UNKNOWN_LENGTH -1
/** Standard folder browsing service UUID (give this as a parameter to
* gw_obex_setup_* to connect to folder browsing service */
#define OBEX_FTP_UUID \
"\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
/** Length of OBEX_FTP_UUID */
#define OBEX_FTP_UUID_LEN 16
/** Phone Book Access Profile UUID */
#define OBEX_PBAP_UUID \
"\x79\x61\x35\xF0\xF0\xC5\x11\xD8\x09\x66\x08\x00\x20\x0C\x9A\x66"
/** Length of OBEX_PBAP_UUID */
#define OBEX_PBAP_UUID_LEN 16
/** IrMC Sync Profile UUID */
#define OBEX_SYNC_UUID \
"IRMC-SYNC"
/** Length of OBEX_SYNC_UUID */
#define OBEX_SYNC_UUID_LEN 9
/** Struct containing the context of a gwobex connection */
typedef struct gw_obex GwObex;
/** Objecct transfer handle */
typedef struct gw_obex_xfer GwObexXfer;
/** Callback type for ongoing transfers
* @param ctx GwObexXfer pointer for the transfer
* @param data Optional pointer to user data
*/
typedef void (*gw_obex_xfer_cb_t) (GwObexXfer *xfer,
gpointer data);
/** Callback type for transport connection loss
* @param ctx GwObex pointer for the connection
* @param data Optional pointer to user data
*/
typedef void (*gw_obex_disconnect_cb_t) (GwObex *ctx,
gpointer data);
/** Callback type for progress information
* Only used for the synchronous transfer functions.
* @param ctx GwObex pointer for the connection
* @param obex_cmd eg. OBEX_CMD_PUT
* @param current Bytes transfered
* @param target Total length (or GW_OBEX_UNKNOWN_LENGTH)
* @param data Optional pointer to user data
*/
typedef void (*gw_obex_progress_cb_t) (GwObex *ctx, gint obex_cmd,
gint current, gint target,
gpointer data);
/** Callback type for checking if the operation should be canceled.
* Only used for the synchronous functions.
* In the GNOME VFS case the callback function should be
* gnome_vfs_cancellation_check().
* @param data Optional pointer to user data
* @returns TRUE if the operation should be canceled, FALSE othervice
*/
typedef gboolean (*gw_obex_cancel_cb_t) (gpointer data);
/**
* @name Functions for connecting and disconnecting
* With these functions you can create and and disconnect connections. You can
* either connect using a filename (e.g. "/dev/rfcomm0") or using a file
* descriptor (e.g. a RFCOMM socket).
* @{
*/
/** Open connection using a local device node and setup parameters.
* This function should be called before calling any other functions. The
* pointer returned by this function should be passed to the other functions.
*
* @param device The local device which should be opened for the connection
* @param uuid UUID of service to connect to. NULL for the default service
* (INBOX).
* @param uuid_len Length (in bytes) of UUID
* @param context GMainContext to attach to (or NULL for the default one)
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns A pointer, NULL on failure
* This pointer should be passed to the other obex_* functions.
**/
GwObex *gw_obex_setup_dev(const gchar *device,
const gchar *uuid,
gint uuid_len,
GMainContext *context,
gint *error);
/** Setup OBEX connection using an opened file descriptor
* This function should be called before calling any other functions. The
* pointer returned by this function should be passed to the other functions.
*
* @param fd Opened file descriptor to use for the connection
* @param uuid UUID of service to connect to. NULL for the default service
* (INBOX).
* @param uuid_len Length (in bytes) of UUID
* @param context GMainContext to attach to (or NULL for the default one)
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns A pointer, NULL on failure
* This pointer should be passed to the other obex_* functions.
**/
GwObex *gw_obex_setup_fd(int fd,
const gchar *uuid,
gint uuid_len,
GMainContext *context,
gint *error);
/** Close GW OBEX connection and free all memory associated with it.
*
* @param ctx Pointer returned by gw_obex_setup().
* Cannot be used anymore after this calling this function.
*/
void gw_obex_close(GwObex *ctx);
/** @} */
/**
* @name Registering callback functions
* With these functions you can register your own callback functions
* to gwobex to receive indications about special events.
* @{
*/
/** Set function to be called when a disconnection happens.
* You may (and probably should) call gw_obex_close() if this function is
* called.
* @param ctx Pointer returned by gw_obex_setup()
* @param callback Function to call
* @param data Optional data to pass to the callback function
*/
void gw_obex_set_disconnect_callback(GwObex *ctx,
gw_obex_disconnect_cb_t callback,
gpointer data);
/** Set function to be called when progress for a put or get operation happens.
* Only used for the synchronous transfer functions.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param callback Function to call
* @param data Optional data to pass to the callback function
*/
void gw_obex_set_progress_callback(GwObex *ctx,
gw_obex_progress_cb_t callback,
gpointer data);
/** Set function to be called to check if the current operation should be
* canceled. In the GNOME VFS case the callback function should be
* gnome_vfs_cancellation_check(). The callback function should return TRUE if
* the operation should be canceled and FALSE othervice.
*
* Only used for the synchronous transfer functions.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param callback Function to call
* @param data Pointer to pass to the callback function
*/
void gw_obex_set_cancel_callback(GwObex *ctx,
gw_obex_cancel_cb_t callback,
gpointer data);
/** @} */
/**
* @name Functions for performing synchronous remote operations
* Once you have setup a connection using one of the gw_obex_setup_* functions,
* you can perform different remote transactions using these functions.
* @{
*/
/** Get the capability object from the connected remote device.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param cap Place to store the fetched object.
* g_free() when not needed anymore.
* @param cap_len Place to store the size of the fetched object
* @param error Place to store a possible error code
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_get_capability(GwObex *ctx,
gchar **cap,
gint *cap_len,
gint *error);
/** Get a file from the remote device.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param local Local filename (null terminated UTF-8)
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_get_file(GwObex *ctx,
const gchar *local,
const gchar *remote,
const gchar *type,
gint *error);
/** Send a file to the remote device.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param local Local filename (null terminated UTF-8)
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_put_file(GwObex *ctx,
const gchar *local,
const gchar *remote,
const gchar *type,
gint *error);
/** Get a file from the remote device and write it to a file descriptor
*
* @param ctx Pointer returned by gw_obex_setup()
* @param fd File descriptor to write the file into
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_get_fd(GwObex *ctx, gint fd,
const gchar *remote,
const gchar *type,
gint *error);
/** Read data from a file descriptor and send it to the remote device
*
* @param ctx Pointer returned by gw_obex_setup()
* @param fd File descriptor to read the data from
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_put_fd(GwObex *ctx, gint fd,
const gchar *remote,
const gchar *type,
gint *error);
/** Get an object from the remote device and store it in a memory buffer.
* Either remote filename or type must be supplied (or both).
*
* @param ctx Pointer returned by gw_obex_setup()
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param buf Buffer to store the object in.
* g_free() when not needed anymore.
* @param buf_size Place to store length of fetched object
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_get_buf(GwObex *ctx, const gchar *remote, const gchar *type,
gchar **buf, gint *buf_size, gint *error);
/** Send a object located in a memory buffer to the remote device.
* Either remote filename or type must be supplied (or both)
*
* @param ctx Pointer returned by gw_obex_setup()
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param buf Buffer containing the object
* @param buf_size Buffer (object) size
* @param time Last modification time of object (or -1 if not known)
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_put_buf(GwObex *ctx, const gchar *remote, const gchar *type,
const gchar *buf, gint buf_size, gint time, gint *error);
/** Get an object from the remote device and store it in a memory buffer.
* Either remote filename or type must be supplied (or both).
*
* @param ctx Pointer returned by gw_obex_setup()
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param apparam Application parameters of the object
* @param apparam_size Application parameters size
* @param buf Buffer to store the object in.
* g_free() when not needed anymore.
* @param buf_size Place to store length of fetched object
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_get_buf_with_apparam(GwObex *ctx, const gchar *remote, const gchar *type,
const guint8 *apparam, gint apparam_size,
gchar **buf, gint *buf_size, gint *error);
/** Send a object located in a memory buffer to the remote device.
* Either remote filename or type must be supplied (or both)
*
* @param ctx Pointer returned by gw_obex_setup()
* @param remote Remote filename (null terminated UTF-8)
* @param type MIME-type of the object
* @param apparam Application parameters of the object
* @param apparam_size Application parameters size
* @param buf Buffer containing the object
* @param buf_size Buffer (object) size
* @param time Last modification time of object (or -1 if not known)
* @param error Place to store error code on failure
* (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_put_buf_with_apparam(GwObex *ctx, const gchar *remote, const gchar *type,
const guint8 *apparam, gint apparam_size,
const gchar *buf, gint buf_size, gint time, gint *error);
/** Change directory (relative to the current one).
*
* @param ctx Pointer returned by gw_obex_setup()
* @param dir New directory to change to (null terminated UTF-8),
* ".." to go up, NULL to go to the root folder
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_chdir(GwObex *ctx, const gchar *dir, gint *error);
/** Create a new directory.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param dir Directory to create (null terminated UTF-8)
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_mkdir(GwObex *ctx, const gchar *dir, gint *error);
/** Get folder listing for the specified directory.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param dir Directory to list (null terminated UTF-8),
* NULL to list current directory
* @param buf Place to store the folder-listing object
* @param buf_size Place to store the size for the retrieved object
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_read_dir(GwObex *ctx, const gchar *dir,
gchar **buf, gint *buf_size, gint *error);
/** Remove a file from the remote device.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param name Filename to remove (null terminated UTF-8)
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_delete(GwObex *ctx, const gchar *name, gint *error);
/** Move/Rename a file on the remote device.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param src Source filename (null terminated UTF-8)
* @param dst Destination filename (null terminated UTF-8)
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_move(GwObex *ctx, const gchar *src, const gchar *dst,
gint *error);
/** Copy a file on the remote device.
*
* @param ctx Pointer returned by gw_obex_setup()
* @param src Source filename (null terminated UTF-8)
* @param dst Destination filename (null terminated UTF-8)
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_copy(GwObex *ctx, const gchar *src, const gchar *dst,
gint *error);
/** @} */
/**
* @name Functions for performing transfers in an asynchronous manner
* With these functions you can do transfers in smaller steps. The steps
* are split up in a open, read/write, close manner.
* @{
*/
/** Start a PUT operation asynchronously
*
* @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 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(GwObex *ctx, const char *name, const char *type,
gint size, time_t time, gint *error);
/** Start a GET operation asynchronously
*
* @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 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(GwObex *ctx, const char *name, const char *type, gint *error);
/** Start a GET operation asynchronously with application parameters
*
* @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 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_apparam(GwObex *ctx, const char *name, const char *type,
const guint8 *apparam, gint apparam_size, gint *error);
/** Set a callback function for a GwObexXfer object
* The callback function will be called in the following situations:
* <ul>
* <li>Data can be written (i.e. xfer_write will succeed)</li>
* <li>Data can be read (i.e. xfer_read will succees)</li>
* <li>An error ocured</li>
* <li>The transfer is finished</li>
* </ul>
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param cb Pointer to the callback function
* @param user_data Optional user data which will be passed to the callback function
*
* @returns a new GwObexXfer object on success, NULL on failure
*/
void gw_obex_xfer_set_callback(GwObexXfer *xfer, gw_obex_xfer_cb_t cb, gpointer user_data);
/** Get the last modification time of the object being transfered
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
*
* @returns The modification time or -1 if it is not known.
*/
time_t gw_obex_xfer_object_time(GwObexXfer *xfer);
/** Get the size of the object being transfered
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
*
* @returns The size or GW_OBEX_UNKNOWN_LENGTH if it is not known.
*/
gint gw_obex_xfer_object_size(GwObexXfer *xfer);
/** Get the contents of the application parameters header
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param apparam_size Return value for the size of the application parameters header.
*
* @returns The pointer to the buffer that hold the contents.
*/
unsigned char *gw_obex_xfer_object_apparam(GwObexXfer *xfer, size_t *apparam_size);
/** Returns if a transfer is already done
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
*
* @returns whether the current transfer is done
*/
gboolean gw_obex_xfer_object_done(GwObexXfer *xfer);
/** Supply more data to a transfer
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param buf Buffer containing the data
* @param buf_size Size of the buffer
* @param bytes_written Return value for the number of bytes that were written
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_xfer_write(GwObexXfer *xfer, const char *buf, gint buf_size,
gint *bytes_written, gint *error);
/** Read data from a transfer
*
* The function will report EOF by returning success with zero bytes read.
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param buf Buffer where the data should be stored
* @param buf_size Size of the buffer
* @param bytes_read Return value for the number of bytes that were read
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_xfer_read(GwObexXfer *xfer, char *buf, gint buf_size,
gint *bytes_read, gint *error);
/** Force all data remaining in buffers to be sent
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_xfer_flush(GwObexXfer *xfer, gint *error);
/** Close an ongoing transfer
*
* You still need to call gw_obex_xfer_free after this to free the actual
* memory allocated for the GwObexXfer object.
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_xfer_close(GwObexXfer *xfer, gint *error);
/** Abort an ongoing transfer
*
* You still need to call gw_obex_xfer_free after this to free the actual
* memory allocated for the GwObexXfer object. xfer_close and xfer_abort are
* mutually exclusive (only call one of them for a transfer).
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param error Place to store error code on failure (NULL if not interested)
*
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_xfer_abort(GwObexXfer *xfer, gint *error);
/** Free the data allocated for a GwObexXfer object
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
*/
void gw_obex_xfer_free(struct gw_obex_xfer *xfer);
/** Set blocking behaviour for a GwObexXfer object when calling xfer_read and xfer_write
*
* When blocking is enabled xfer_read will return only after it has been able
* to read some data (i.e. GW_OBEX_ERROR_NO_DATA will not be returned). For xfer_write
* blocking guarantees that *some* data will be written.
*
* @param xfer Pointer returned by gw_obex_put_async or gw_obex_get_async
* @param block TRUE to enable blocking behaviour
*/
void gw_obex_xfer_set_blocking(GwObexXfer *xfer, gboolean block);
/** @} */
#endif /* _GW_OBEX_H_ */

View File

@ -1,38 +0,0 @@
/**
@file log.h
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _LOG_H_
#define _LOG_H_
#ifdef DEBUG
# ifdef DEBUG_STDOUT
# include <glib.h>
# define debug(...) g_print(__VA_ARGS__)
# else
# include <syslog.h>
# define debug(fmt, arg...) syslog(LOG_DEBUG, "gwobex: " fmt, ## arg)
# endif
#else
# define debug(...) ((void)(0))
#endif
#endif /* _LOG_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,217 +0,0 @@
/**
@file obex-priv.h
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _OBEX_PRIV_H_
#define _OBEX_PRIV_H_
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <glib.h>
#include <openobex/obex.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "gw-obex.h"
#include "obex-xfer.h"
#define CHECK_DISCONNECT(ret, err, ctx) do { \
if ((ctx)->conn_fd < 0) { \
if (err) \
*(err) = GW_OBEX_ERROR_DISCONNECT; \
GW_OBEX_UNLOCK(ctx); \
return (ret); \
} \
} while (0)
#ifndef OBEX_CMD_ACTION
# define OBEX_CMD_ACTION 0x06
# define OBEX_HDR_ACTION_ID 0x94
# define OBEX_HDR_DESTNAME 0x15
# define OBEX_HDR_PERMISSIONS 0xD6
#endif /* OBEX_CMD_ACTION */
#define OBEX_ACTION_COPY 0x00
#define OBEX_ACTION_MOVE 0x01
#define OBEX_ACTION_SETPERM 0x02
#define CONID_INVALID 0xFFFFFFFF
#define OBEX_CMD_NONE 0x10
#define GW_OBEX_RX_MTU 4096
#define GW_OBEX_TX_MTU 32767
#define SETPATH_CREATE 0x0001
#define CAP_TYPE "x-obex/capability"
#define OBP_TYPE "x-obex/object-profile"
#define LST_TYPE "x-obex/folder-listing"
#ifdef GW_OBEX_THREADS_ENABLED
# ifdef DEBUG
# define GW_OBEX_LOCK(ctx) do { \
debug("Attempting GW_OBEX_LOCK at %s:%d (%s)...", __FILE__, __LINE__, __PRETTY_FUNCTION__); \
fflush(stdout); \
g_mutex_lock((ctx)->mutex); \
debug("got it!\n"); \
} while (0)
# define GW_OBEX_UNLOCK(ctx) do { \
debug("Unlocking GW_OBEX_LOCK at %s:%d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__); \
g_mutex_unlock((ctx)->mutex); \
} while (0)
# else
# define GW_OBEX_LOCK(ctx) g_mutex_lock((ctx)->mutex)
# define GW_OBEX_UNLOCK(ctx) g_mutex_unlock((ctx)->mutex)
# endif
#else
# define GW_OBEX_LOCK(ctx) ((void)(0))
# define GW_OBEX_UNLOCK(ctx) ((void)(0))
#endif
typedef struct obex_setpath_hdr {
uint8_t flags;
uint8_t constants;
} __attribute__ ((packed)) obex_setpath_hdr_t;
typedef struct obex_connect_hdr {
uint8_t version;
uint8_t flags;
uint16_t mtu;
} __attribute__ ((packed)) obex_connect_hdr_t;
struct gw_obex {
#ifdef GW_OBEX_THREADS_ENABLED
/* To get rid of race conditions in multithreaded apps */
GMutex *mutex;
#endif
/* Main OpenOBEX handle */
obex_t *handle;
/* Exception callback and associated data */
gw_obex_disconnect_cb_t dc_cb;
gpointer dc_data;
/* Progress callback and associated data */
gw_obex_progress_cb_t pr_cb;
gpointer pr_data;
/* Whether calling pr_cb is necessary or not */
gboolean report_progress;
/* Cancel callback and associated data */
gw_obex_cancel_cb_t cancel_cb;
gpointer cancel_data;
/* For checking if the current operation is finished */
gboolean done;
/* TRUE if a link error has hapened */
gboolean link_err;
/* FD for the transport connection */
int conn_fd;
GMainContext *main_ctx;
/* The transport connection's GIOChannel */
GIOChannel *gio;
/* The transport connection's GSource */
GSource *gio_source;
/* OBEX Connection ID */
uint32_t conid;
/* The last OBEX response code */
uint8_t obex_rsp;
/* The current OBEX operation */
uint8_t obex_op;
/* This is set if some operation fails */
gint error;
/* Bytes to read at a time when doing a put */
uint16_t tx_max;
/* How many bytes to allocate for incomming object data */
uint16_t rx_max;
/* Current object transfer handle */
struct gw_obex_xfer *xfer;
};
GwObex *make_context(obex_t *handle);
gboolean gw_obex_set_error(GwObex *ctx);
void gw_obex_get_error(GwObex *ctx, gint *error);
void obex_link_error(GwObex *ctx);
gboolean gw_obex_cb(GIOChannel *chan, GIOCondition cond, gpointer data);
gboolean gw_obex_connect(GwObex *ctx, const char *target, size_t target_len);
gboolean gw_obex_disconnect(GwObex *ctx);
gboolean gw_obex_transport_setup(int fd, obex_t **handle);
gboolean gw_obex_action_op(GwObex *ctx, const gchar *src, const gchar *dst,
uint8_t action);
gboolean gw_obex_setpath(GwObex *ctx, const gchar *path, int flags);
/** Get an object from the server
* @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)
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_get(GwObex *ctx,
const gchar *local, const gchar *remote, const gchar *type,
const guint8 *apparam, gint apparam_size,
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)
* @returns TRUE on success, FALSE on failure
*/
gboolean gw_obex_put(GwObex *ctx,
const gchar *local, const gchar *remote, const gchar *type,
const guint8 *apparam, gint apparam_size,
const gchar *buf, gint buf_size, time_t object_time,
int stream_fd, gboolean async);
#endif /* _OBEX_PRIV_H_ */

View File

@ -1,524 +0,0 @@
/**
@file obex-xfer.c
Object transfer related functions for the GW OBEX Library
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <openobex/obex.h>
#include "obex-priv.h"
#include "obex-xfer.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "log.h"
#include "obex-priv.h"
#include "obex-xfer.h"
#include "gw-obex.h"
static gboolean handle_input(GwObex *ctx, gint *err) {
gboolean ret = TRUE;
int r;
r = OBEX_HandleInput(ctx->handle, 10);
if (r < 0) {
debug("OBEX_HandleInput() failed\n");
obex_link_error(ctx);
if (err)
*err = GW_OBEX_ERROR_INTERNAL;
ret = FALSE;
}
else if (r == 0) { /* Timeout */
debug("OBEX_HandleInput(): timeout\n");
if (err)
*err = GW_OBEX_ERROR_TIMEOUT;
ret = FALSE;
}
return ret;
}
struct gw_obex_xfer *gw_obex_xfer_new(struct gw_obex *ctx, gboolean async, int stream_fd) {
struct gw_obex_xfer *xfer;
size_t buf_size = (ctx->obex_op == OBEX_CMD_GET) ? ctx->rx_max : ctx->tx_max;
xfer = g_new0(struct gw_obex_xfer, 1);
xfer->ctx = ctx;
xfer->async = async;
xfer->stream_fd = stream_fd;
xfer->target_size = GW_OBEX_UNKNOWN_LENGTH;
xfer->modtime = -1;
if (async || (stream_fd >= 0 && ctx->obex_op == OBEX_CMD_PUT)) {
xfer->buf = g_malloc(buf_size);
xfer->buf_size = buf_size;
}
if (async && ctx->obex_op == OBEX_CMD_PUT)
xfer->do_cb = TRUE;
return xfer;
}
gboolean gw_obex_xfer_do_abort(struct gw_obex_xfer *xfer) {
debug("gw_obex_xfer_do_abort()\n");
if (xfer->ctx->conn_fd < 0 || xfer->ctx->xfer == NULL || xfer->ctx->done)
return FALSE;
if (xfer->abort)
return TRUE;
xfer->abort = TRUE;
debug("Performing nice abort\n");
if (OBEX_CancelRequest(xfer->ctx->handle, TRUE) != 0)
return FALSE;
return TRUE;
}
GwObexXfer *gw_obex_put_async(GwObex *ctx, const char *name, const char *type,
gint size, time_t time, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(NULL, error, ctx);
ret = gw_obex_put(ctx, NULL, name, type, NULL, 0, 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);
CHECK_DISCONNECT(NULL, error, ctx);
ret = gw_obex_get(ctx, NULL, name, type, NULL, 0, NULL, NULL, -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_with_apparam(GwObex *ctx, const char *name, const char *type,
const guint8 *apparam, gint apparam_size, gint *error) {
gboolean ret;
GW_OBEX_LOCK(ctx);
CHECK_DISCONNECT(NULL, error, ctx);
ret = gw_obex_get(ctx, NULL, name, type, apparam, apparam_size, 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;
g_source_destroy(xfer->idle_source);
xfer->idle_source = NULL;
if (!ctx)
return FALSE;
GW_OBEX_LOCK(ctx);
if (xfer->cb && xfer->do_cb) {
xfer->do_cb = FALSE;
GW_OBEX_UNLOCK(ctx);
xfer->cb(xfer, xfer->cb_data);
GW_OBEX_LOCK(ctx);
}
GW_OBEX_UNLOCK(ctx);
return FALSE;
}
void gw_obex_xfer_set_callback(GwObexXfer *xfer, gw_obex_xfer_cb_t cb, gpointer user_data) {
GwObex *ctx = xfer->ctx;
GW_OBEX_LOCK(ctx);
xfer->cb = cb;
xfer->cb_data = user_data;
if (xfer->do_cb && xfer->idle_source == NULL) {
xfer->idle_source = g_idle_source_new();
g_source_set_callback(xfer->idle_source, (GSourceFunc)gw_obex_put_idle, xfer, NULL);
(void) g_source_attach(xfer->idle_source, ctx->main_ctx);
g_source_unref(xfer->idle_source);
}
GW_OBEX_UNLOCK(ctx);
}
time_t gw_obex_xfer_object_time(GwObexXfer *xfer) {
return xfer->modtime;
}
gint gw_obex_xfer_object_size(GwObexXfer *xfer) {
return xfer->target_size;
}
unsigned char *gw_obex_xfer_object_apparam(GwObexXfer *xfer, size_t *apparam_size) {
if (apparam_size)
*apparam_size = xfer->apparam_size;
return xfer->apparam_buf;
}
gboolean gw_obex_xfer_object_done(GwObexXfer *xfer) {
return xfer->ctx->done;
}
gboolean gw_obex_xfer_write(GwObexXfer *xfer, const char *buf, gint buf_size,
gint *bytes_written, gint *err) {
GwObex *ctx = xfer->ctx;
gboolean ret = TRUE;
gint free_space;
debug("gw_obex_xfer_write(buf_size=%d): entered\n", buf_size);
if (!ctx) {
if (err)
*err = GW_OBEX_ERROR_INVALID_PARAMS;
return FALSE;
}
GW_OBEX_LOCK(ctx);
if (ctx->obex_op != OBEX_CMD_PUT) {
ret = FALSE;
if (err)
*err = GW_OBEX_ERROR_INVALID_PARAMS;
goto out;
}
if (gw_obex_set_error(ctx)) {
gw_obex_get_error(ctx, err);
ret = FALSE;
goto out;
}
free_space = xfer->buf_size - (xfer->data_start + xfer->data_length);
*bytes_written = buf_size > free_space ? free_space : buf_size;
memcpy(&xfer->buf[xfer->data_start + xfer->data_length], buf, *bytes_written);
xfer->data_length += *bytes_written;
free_space -= *bytes_written;
if (xfer->object) {
if (OBEX_Request(ctx->handle, xfer->object) < 0) {
debug("OBEX_Request() failed\n");
xfer->data_length -= *bytes_written;
ret = FALSE;
goto out;
}
xfer->object = NULL;
/* Recalculate free space */
free_space = xfer->buf_size - (xfer->data_start + xfer->data_length);
}
if (xfer->data_length >= ctx->tx_max || !free_space) {
guint old_length = xfer->data_length;
debug("OBEX_ResumeRequest at %s:%d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
OBEX_ResumeRequest(ctx->handle);
if (!xfer->block)
goto out;
/* Call OBEX_HandleInput if the xfer is blocking and no data could be sent */
while (old_length == xfer->data_length) {
if (gw_obex_set_error(ctx)) {
gw_obex_get_error(ctx, err);
ret = FALSE;
goto out;
}
if (!handle_input(ctx, err)) {
ret = FALSE;
goto out;
}
}
}
out:
if (xfer->cb && xfer->do_cb && xfer->idle_source == NULL) {
xfer->idle_source = g_idle_source_new();
g_source_set_callback(xfer->idle_source, (GSourceFunc)gw_obex_put_idle, xfer, NULL);
(void) g_source_attach(xfer->idle_source, ctx->main_ctx);
g_source_unref(xfer->idle_source);
}
GW_OBEX_UNLOCK(ctx);
if (ret)
debug("gw_obex_xfer_write(): returning, %d bytes written\n", *bytes_written);
else
debug("gw_obex_xfer_write(): returning, failed (%d)\n", err ? *err : 0);
return ret;
}
gboolean gw_obex_xfer_read(GwObexXfer *xfer, char *buf, gint buf_size,
gint *bytes_read, gint *err) {
GwObex *ctx = xfer->ctx;
gint data_length;
gboolean ret = TRUE;
debug("gw_obex_xfer_read(buf_size=%d): entered\n", buf_size);
if (!ctx) {
if (err)
*err = GW_OBEX_ERROR_INVALID_PARAMS;
return FALSE;
}
GW_OBEX_LOCK(ctx);
if (ctx->obex_op != OBEX_CMD_GET) {
ret = FALSE;
if (err)
*err = GW_OBEX_ERROR_INVALID_PARAMS;
goto out;
}
while (TRUE) {
if (gw_obex_set_error(ctx)) {
gw_obex_get_error(ctx, err);
ret = FALSE;
goto out;
}
if (xfer->data_length)
break;
if (ctx->done) {
*bytes_read = 0;
goto out;
}
if (xfer->block) {
if (!handle_input(ctx, err)) {
ret = FALSE;
goto out;
}
}
else {
ret = FALSE;
if (err)
*err = GW_OBEX_ERROR_NO_DATA;
goto out;
}
}
data_length = xfer->data_length;
*bytes_read = buf_size < data_length ? buf_size : data_length;
memcpy(buf, &xfer->buf[xfer->data_start], *bytes_read);
xfer->data_length -= *bytes_read;
if (xfer->data_length)
xfer->data_start += *bytes_read;
else {
xfer->data_start = 0;
debug("OBEX_ResumeRequest at %s:%d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
OBEX_ResumeRequest(ctx->handle);
}
out:
GW_OBEX_UNLOCK(ctx);
if (ret)
debug("gw_obex_xfer_read(): returning, %d bytes read\n", *bytes_read);
else
debug("gw_obex_xfer_read(): returning, failed (%d)\n", err ? *err : 0);
return ret;
}
gboolean gw_obex_xfer_flush(GwObexXfer *xfer, gint *err) {
gboolean ret = TRUE;
struct gw_obex *ctx = xfer->ctx;
if (!ctx) {
if (err)
*err = GW_OBEX_ERROR_INVALID_PARAMS;
return FALSE;
}
GW_OBEX_LOCK(ctx);
if (ctx->obex_op != OBEX_CMD_PUT)
goto out;
if (gw_obex_set_error(ctx)) {
gw_obex_get_error(ctx, err);
ret = FALSE;
goto out;
}
while (xfer->data_length) {
debug("OBEX_ResumeRequest at %s:%d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
OBEX_ResumeRequest(ctx->handle);
if (gw_obex_set_error(ctx)) {
gw_obex_get_error(ctx, err);
ret = FALSE;
goto out;
}
if (xfer->data_length) {
if (!handle_input(ctx, err)) {
ret = FALSE;
goto out;
}
}
}
out:
GW_OBEX_UNLOCK(ctx);
return ret;
}
void _gw_obex_xfer_free(struct gw_obex_xfer *xfer) {
g_free(xfer->buf);
g_free(xfer->apparam_buf);
g_free(xfer);
}
void gw_obex_xfer_free(struct gw_obex_xfer *xfer) {
if (xfer->ctx)
gw_obex_xfer_close(xfer, NULL);
_gw_obex_xfer_free(xfer);
}
gboolean gw_obex_xfer_close(GwObexXfer *xfer, gint *err) {
gboolean ret = TRUE;
struct gw_obex *ctx = xfer->ctx;
/* If previous close() failed, just signal success so caller can continue */
if (!ctx)
return TRUE;
GW_OBEX_LOCK(ctx);
xfer->close = TRUE;
if (ctx->obex_op == OBEX_CMD_GET && !ctx->done)
gw_obex_xfer_do_abort(xfer);
if (ctx->obex_op == OBEX_CMD_PUT) {
if (xfer->object) {
if (OBEX_Request(ctx->handle, xfer->object) < 0) {
debug("OBEX_Request() failed\n");
ctx->done = TRUE;
}
xfer->object = NULL;
}
else {
debug("OBEX_ResumeRequest at %s:%d (%s)\n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
OBEX_ResumeRequest(ctx->handle);
}
}
while (!ctx->done) {
if (!handle_input(ctx, err)) {
ret = FALSE;
break;
}
}
/* Check for error but ignore ERROR_ABORT since we can still do a proper
* xfer_close() in that case */
if (gw_obex_set_error(ctx) && ctx->error != GW_OBEX_ERROR_ABORT) {
gw_obex_get_error(ctx, err);
ret = FALSE;
}
/* Remove the idle function related to this transfer (if there is one) */
if (xfer->idle_source) {
g_source_destroy(xfer->idle_source);
xfer->idle_source = NULL;
}
/* Disassociate from the GwObex object */
ctx->xfer = NULL;
xfer->ctx = NULL;
GW_OBEX_UNLOCK(ctx);
return ret;
}
gboolean gw_obex_xfer_abort(GwObexXfer *xfer, gint *err) {
GwObex *ctx = xfer->ctx;
gboolean ret = TRUE;
/* If previous call failed just signal success so caller can continue */
if (!ctx)
return TRUE;
GW_OBEX_LOCK(ctx);
/* Return if abort has already been sent */
if (xfer->abort)
goto out;
/* Return if actual request hasn't been sent */
if (xfer->object) {
OBEX_ObjectDelete(ctx->handle, xfer->object);
xfer->object = NULL;
ctx->done = TRUE;
goto out;
}
if (!gw_obex_xfer_do_abort(xfer)) {
ret = FALSE;
if (err)
*err = GW_OBEX_ERROR_INTERNAL;
goto out;
}
out:
GW_OBEX_UNLOCK(ctx);
gw_obex_xfer_close(xfer, err);
return ret;
}
void gw_obex_xfer_set_blocking(GwObexXfer *xfer, gboolean block) {
GW_OBEX_LOCK(xfer->ctx);
xfer->block = block;
GW_OBEX_UNLOCK(xfer->ctx);
}

View File

@ -1,91 +0,0 @@
/**
@file obex-xfer.h
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _OBEX_XFER_H_
#define _OBEX_XFER_H_
#include <stdint.h>
#include <time.h>
#include <glib.h>
#include <openobex/obex.h>
#include "gw-obex.h"
#include "obex-priv.h"
struct gw_obex_xfer {
/* Pointer to parent gw_obex struct */
struct gw_obex *ctx;
/* Used only for async PUT transfers */
obex_object_t *object;
/* Sync or async transfer */
gboolean async;
/* If read and write operations should block for an async transfer */
gboolean block;
/* When doing a get or put for a local file */
int stream_fd;
/* TRUE if the current operation was aborted */
gboolean abort;
/* Transfer should be closed when no more data to send */
gboolean close;
/* Temporary buffer when doing a put or get */
unsigned char *buf;
size_t buf_size;
/* Buffer and size for Application parameters */
unsigned char *apparam_buf;
size_t apparam_size;
/* These two elements are only used for async transfers */
size_t data_start;
size_t data_length;
/* Bytes read or written for the current get/put operation */
size_t counter;
/* Target length of the current get/put operation */
gint target_size;
/* Modification time of last file transfered */
time_t modtime;
gboolean do_cb;
gw_obex_xfer_cb_t cb;
gpointer cb_data;
GSource *idle_source;
};
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);
gboolean gw_obex_xfer_do_abort(struct gw_obex_xfer *xfer);
#endif /* _OBEX_XFER_H_ */

View File

@ -1,185 +0,0 @@
/**
@file utils.c
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <glib.h>
#include <termios.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "log.h"
#include "utils.h"
#ifdef DEBUG
char *bytestr(const uint8_t *uuid, int len) {
int i;
char *str = g_malloc((len << 1) + 1);
for (i = 0; i < len; i++)
sprintf(str + (2*i), "%02X", uuid[i]);
return str;
}
#endif
gboolean fd_raw_mode(int fd) {
struct termios mode;
memset(&mode, 0, sizeof(mode));
if (tcgetattr(fd, &mode) < 0) {
debug("tcgetattr(%d, &mode): %s", fd, strerror(errno));
return FALSE;
}
mode.c_iflag = 0;
mode.c_oflag &= ~OPOST;
mode.c_lflag &= ~(ISIG | ICANON | ECHO
#ifdef XCASE
| XCASE
#endif
);
mode.c_cc[VMIN] = 1;
mode.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSADRAIN, &mode) < 0) {
debug("tcsetattr(%d, TCSADRAIN, &mode): %s", fd, strerror(errno));
return FALSE;
}
return TRUE;
}
glong get_uname(gunichar2 **uname, const gchar *name) {
glong uname_len;
if (*name == '\0') {
*uname = NULL;
return 0;
}
*uname = g_utf8_to_utf16(name, -1, NULL, &uname_len, NULL);
if (*uname == NULL)
uname_len = -1;
else {
int i;
/* g_utf8_to_utf16 produces host-byteorder UTF-16,
* but OBEX requires network byteorder (big endian) */
for (i = 0; i < uname_len; i++)
(*uname)[i] = g_htons((*uname)[i]);
uname_len = (uname_len + 1) << 1;
}
return uname_len;
}
int make_iso8601(time_t time, char *str, int len) {
struct tm tm;
#if defined(HAVE_TIMEZONE) && defined(USE_LOCALTIME)
time_t tz_offset = 0;
tz_offset = -timezone;
if (daylight > 0)
tz_offset += 3600;
time += tz_offset;
#endif
if (gmtime_r(&time, &tm) == NULL)
return -1;
tm.tm_year += 1900;
tm.tm_mon++;
return snprintf(str, len,
#ifdef USE_LOCALTIME
"%04u%02u%02uT%02u%02u%02u",
#else
"%04u%02u%02uT%02u%02u%02uZ",
#endif
tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
/* From Imendio's GnomeVFS OBEX module (om-utils.c) */
time_t parse_iso8601(const gchar *str, int len) {
gchar *tstr;
struct tm tm;
gint nr;
gchar tz;
time_t time;
time_t tz_offset = 0;
memset(&tm, 0, sizeof(struct tm));
/* According to spec the time doesn't have to be null terminated */
if (str[len - 1] != '\0') {
tstr = g_malloc(len + 1);
strncpy(tstr, str, len);
tstr[len] = '\0';
}
else
tstr = g_strdup(str);
nr = sscanf(tstr, "%04u%02u%02uT%02u%02u%02u%c",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec,
&tz);
g_free(tstr);
/* Fixup the tm values */
tm.tm_year -= 1900; /* Year since 1900 */
tm.tm_mon--; /* Months since January, values 0-11 */
tm.tm_isdst = -1; /* Daylight savings information not avail */
if (nr < 6) {
/* Invalid time format */
return -1;
}
time = mktime(&tm);
#if defined(HAVE_TM_GMTOFF)
tz_offset = tm.tm_gmtoff;
#elif defined(HAVE_TIMEZONE)
tz_offset = -timezone;
if (tm.tm_isdst > 0) {
tz_offset += 3600;
}
#endif
if (nr == 7) { /* Date/Time was in localtime (to remote device)
* already. Since we don't know anything about the
* timezone on that one we won't try to apply UTC offset
*/
time += tz_offset;
}
return time;
}

View File

@ -1,60 +0,0 @@
/**
@file utils.h
@author Johan Hedberg <johan.hedberg@nokia.com>
Copyright (C) 2004-2006 Nokia Corporation. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License, version 2.1, as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef _UTILS_H_
#define _UTILS_H_
#include <sys/types.h>
#include <sys/stat.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
/** Create ISO8601 time format string from time_t
* @param time Time to convert
* @param str Pointer where result is stored
* @param len Maximum amount of chars written
* @returns length of created string.
*/
int make_iso8601(time_t time, char *str, int len);
/** Convert a time string in ISO8601 format to time_t
* @param str Time string in ISO8601 format
* @param len Length of string
* @returns time as time_t format
*/
time_t parse_iso8601(const gchar *str, int len);
#ifdef DEBUG
char *bytestr(const uint8_t *uuid, int len);
#endif
/** Convert an UTF-8 string to UTF-16 (Network byte order)
* @param uname, Place to store the new UTF-16 string
* @param name, Original UTF-8 string
* @returns Size in bytes allocated for the UTF-16 string (uname)
*/
glong get_uname(gunichar2 **uname, const gchar *name);
gboolean fd_raw_mode(int fd);
#endif /* _UTILS_H */