From bac315ca0f4f63a591a324f455de657921ec9ebc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 19 Oct 2008 06:03:36 +0200 Subject: [PATCH] obexd: Add first attempt at PBAP server implementation --- obexd/src/bluetooth.c | 56 +++++++++++++++++++++++--- obexd/src/main.c | 57 ++++++++++----------------- obexd/src/obex.c | 39 +++++++++++------- obexd/src/obex.h | 16 +++++--- obexd/src/pbap.c | 92 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+), 62 deletions(-) create mode 100644 obexd/src/pbap.c diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c index d71de2439..a385087ed 100644 --- a/obexd/src/bluetooth.c +++ b/obexd/src/bluetooth.c @@ -133,6 +133,47 @@ const static gchar *ftp_record = " \ \ "; +const static gchar *pbap_record = " \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +"; + static uint32_t register_record(const gchar *name, guint16 service, guint8 channel) { @@ -140,12 +181,15 @@ static uint32_t register_record(const gchar *name, gint handle; switch (service) { - case OBEX_OPUSH: + case OBEX_OPP: record = g_markup_printf_escaped(opp_record, channel, name); break; case OBEX_FTP: record = g_markup_printf_escaped(ftp_record, channel, name); break; + case OBEX_PBAP: + record = g_markup_printf_escaped(pbap_record, channel, name); + break; default: return 0; } @@ -182,7 +226,7 @@ static gboolean connect_event(GIOChannel *io, GIOCondition cond, gpointer user_d info("New connection from: %s, channel %u, fd %d", address, raddr.rc_channel, nsk); - if (server->service == OBEX_OPUSH) { + if (server->service == OBEX_OPP) { if (obex_session_start(nsk, server) < 0) close(nsk); @@ -292,11 +336,11 @@ failed: } gint bluetooth_init(guint service, const gchar *name, const gchar *folder, - guint8 channel, gboolean secure, gboolean auto_accept, - const gchar *capability) + guint8 channel, gboolean secure, + gboolean auto_accept, const gchar *capability) { - return server_register(service, name, channel, - folder, secure, auto_accept, capability); + return server_register(service, name, channel, folder, + secure, auto_accept, capability); } void bluetooth_exit(void) diff --git a/obexd/src/main.c b/obexd/src/main.c index 3a7937c4d..09d214452 100644 --- a/obexd/src/main.c +++ b/obexd/src/main.c @@ -46,12 +46,12 @@ #include "logging.h" #include "bluetooth.h" -#include "phonebook.h" #include "obexd.h" #include "obex.h" -#define OPUSH_CHANNEL 9 +#define OPP_CHANNEL 9 #define FTP_CHANNEL 10 +#define PBAP_CHANNEL 15 #define DEFAULT_ROOT_PATH "/tmp" @@ -59,26 +59,8 @@ static GMainLoop *main_loop = NULL; -static void test_phonebook(void) -{ - struct phonebook_context *context; - struct phonebook_driver *driver; - - driver = phonebook_get_driver(NULL); - if (driver == NULL) - return; - - context = phonebook_create(driver); - if (context == NULL) - return; - - phonebook_pullphonebook(context); - - phonebook_unref(context); -} - -static void tty_init(int service, const gchar *root_path, const gchar *capability, - const gchar *devnode) +static void tty_init(int service, const gchar *root_path, + const gchar *capability, const gchar *devnode) { struct server *server; struct termios options; @@ -113,26 +95,29 @@ static void tty_init(int service, const gchar *root_path, const gchar *capabilit } static int server_start(int service, const char *root_path, - gboolean auto_accept, const gchar *capability, - const char *devnode) + gboolean auto_accept, const gchar *capability, + const char *devnode) { switch (service) { - case OBEX_OPUSH: - bluetooth_init(OBEX_OPUSH, "OBEX OPUSH server", - root_path, OPUSH_CHANNEL, FALSE, - auto_accept, capability); + case OBEX_OPP: + bluetooth_init(OBEX_OPP, "Object Push server", + root_path, OPP_CHANNEL, FALSE, + auto_accept, capability); if (devnode) - tty_init(OBEX_OPUSH, root_path, capability, - devnode); + tty_init(OBEX_OPP, root_path, capability, devnode); break; case OBEX_FTP: - bluetooth_init(OBEX_FTP, "OBEX FTP server", - root_path, FTP_CHANNEL, TRUE, - auto_accept, capability); - + bluetooth_init(OBEX_FTP, "File Transfer server", + root_path, FTP_CHANNEL, TRUE, + auto_accept, capability); if (devnode) tty_init(OBEX_FTP, root_path, capability, devnode); break; + case OBEX_PBAP: + bluetooth_init(OBEX_PBAP, "Phonebook Access server", + root_path, PBAP_CHANNEL, TRUE, + auto_accept, capability); + break; default: return -EINVAL; } @@ -257,7 +242,7 @@ int main(int argc, char *argv[]) option_capability = g_strdup(DEFAULT_CAP_FILE); if (option_opp == TRUE) - server_start(OBEX_OPUSH, option_root, option_autoaccept, + server_start(OBEX_OPP, option_root, option_autoaccept, NULL, option_devnode); if (option_ftp == TRUE) @@ -265,7 +250,7 @@ int main(int argc, char *argv[]) option_capability, option_devnode); if (option_pbap == TRUE) - test_phonebook(); + server_start(OBEX_PBAP, NULL, FALSE, NULL, NULL); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_term; diff --git a/obexd/src/obex.c b/obexd/src/obex.c index 2ccebd14d..de96c8a4f 100644 --- a/obexd/src/obex.c +++ b/obexd/src/obex.c @@ -52,33 +52,40 @@ #define RX_MTU 32767 #define TX_MTU 32767 -#define TARGET_SIZE 16 -static const guint8 FTP_TARGET[TARGET_SIZE] = { 0xF9, 0xEC, 0x7B, 0xC4, - 0x95, 0x3C, 0x11, 0xD2, - 0x98, 0x4E, 0x52, 0x54, - 0x00, 0xDC, 0x9E, 0x09 }; +#define TARGET_SIZE 16 + +static const guint8 FTP_TARGET[TARGET_SIZE] = { + 0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2, + 0x98, 0x4E, 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 }; + +static const guint8 PBAP_TARGET[TARGET_SIZE] = { + 0x79, 0x61, 0x35, 0xF0, 0xF0, 0xC5, 0x11, 0xD8, + 0x09, 0x66, 0x08, 0x00, 0x20, 0x0C, 0x9A, 0x66 }; /* Connection ID */ static guint32 cid = 0x0000; typedef struct { - guint8 version; - guint8 flags; - guint16 mtu; + guint8 version; + guint8 flags; + guint16 mtu; } __attribute__ ((packed)) obex_connect_hdr_t; struct obex_commands opp = { .get = opp_get, - .chkput = opp_chkput, .put = opp_put, - .setpath = NULL, + .chkput = opp_chkput, }; struct obex_commands ftp = { .get = ftp_get, .put = ftp_put, - .setpath = ftp_setpath, .chkput = ftp_chkput, + .setpath = ftp_setpath, +}; + +struct obex_commands pbap = { + .get = pbap_get, }; static void os_reset_session(struct obex_session *os) @@ -248,7 +255,7 @@ static gboolean chk_cid(obex_t *obex, obex_object_t *obj, guint32 cid) os = OBEX_GetUserData(obex); - /* OPUSH doesn't provide a connection id. */ + /* Object Push doesn't provide a connection id. */ if (os->target == NULL) return TRUE; @@ -728,7 +735,7 @@ static void obex_event(obex_t *obex, obex_object_t *obj, gint mode, switch (evt) { case OBEX_EV_PROGRESS: - /* Just emit progress for OPUSH */ + /* Just emit progress for Object Push */ if (os->target == NULL) emit_transfer_progress(os->cid, os->size, os->offset); break; @@ -890,7 +897,7 @@ gint obex_session_start(gint fd, struct server *server) os = g_new0(struct obex_session, 1); switch (server->service) { - case OBEX_OPUSH: + case OBEX_OPP: os->target = NULL; os->cmds = &opp; break; @@ -898,6 +905,10 @@ gint obex_session_start(gint fd, struct server *server) os->target = FTP_TARGET; os->cmds = &ftp; break; + case OBEX_PBAP: + os->target = PBAP_TARGET; + os->cmds = &pbap; + break; default: g_free(os); debug("Invalid OBEX server"); diff --git a/obexd/src/obex.h b/obexd/src/obex.h index fad8a2d69..e1889ec40 100644 --- a/obexd/src/obex.h +++ b/obexd/src/obex.h @@ -29,16 +29,18 @@ #include -#define OBEX_OPUSH 0x00 -#define OBEX_FTP 0x01 +#define OBEX_OPP 0x01 +#define OBEX_FTP 0x02 +#define OBEX_BIP 0x03 +#define OBEX_PBAP 0x04 #define OBJECT_SIZE_UNKNOWN -1 #define OBJECT_SIZE_DELETE -2 struct obex_commands { void (*get) (obex_t *obex, obex_object_t *obj); - gint (*chkput) (obex_t *obex, obex_object_t *obj); void (*put) (obex_t *obex, obex_object_t *obj); + gint (*chkput) (obex_t *obex, obex_object_t *obj); void (*setpath) (obex_t *obex, obex_object_t *obj); }; @@ -73,14 +75,16 @@ struct obex_session { gint obex_session_start(gint fd, struct server *server); gint obex_session_stop(); -gint opp_chkput(obex_t *obex, obex_object_t *obj); -void opp_put(obex_t *obex, obex_object_t *obj); void opp_get(obex_t *obex, obex_object_t *obj); +void opp_put(obex_t *obex, obex_object_t *obj); +gint opp_chkput(obex_t *obex, obex_object_t *obj); void ftp_get(obex_t *obex, obex_object_t *obj); void ftp_put(obex_t *obex, obex_object_t *obj); -void ftp_setpath(obex_t *obex, obex_object_t *obj); gint ftp_chkput(obex_t *obex, obex_object_t *obj); +void ftp_setpath(obex_t *obex, obex_object_t *obj); + +void pbap_get(obex_t *obex, obex_object_t *obj); gboolean os_prepare_get(struct obex_session *os, gchar *file, guint32 *size); gint os_prepare_put(struct obex_session *os); diff --git a/obexd/src/pbap.c b/obexd/src/pbap.c new file mode 100644 index 000000000..fa12f12b3 --- /dev/null +++ b/obexd/src/pbap.c @@ -0,0 +1,92 @@ +/* + * + * OBEX Server + * + * Copyright (C) 2007-2008 Marcel Holtmann + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include "phonebook.h" +#include "logging.h" +#include "obex.h" + +static void test_phonebook(void) +{ + struct phonebook_context *context; + struct phonebook_driver *driver; + + driver = phonebook_get_driver(NULL); + if (driver == NULL) + return; + + context = phonebook_create(driver); + if (context == NULL) + return; + + phonebook_pullphonebook(context); + + phonebook_unref(context); +} + +void pbap_get(obex_t *obex, obex_object_t *obj) +{ + struct obex_session *os; + obex_headerdata_t hv; + guint32 size; + + os = OBEX_GetUserData(obex); + if (os == NULL) + return; + + if (os->name) + goto fail; + + if (os->type == NULL) + goto fail; + + test_phonebook(); + size = 0; + + hv.bq4 = size; + OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_LENGTH, hv, 4, 0); + + /* Add body header */ + hv.bs = NULL; + if (size == 0) + OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, + hv, 0, OBEX_FL_FIT_ONE_PACKET); + else + OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, + hv, 0, OBEX_FL_STREAM_START); + + OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); + + return; + +fail: + OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); +} -- 2.47.3