From e114d23e570b8ce8a6d82dc899c6748efe03474a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 5 Nov 2008 16:49:26 +0200 Subject: [PATCH] obexd: Use the OBEX Connect command for server selection Instead of pre-assigning a specific application profiles(OPP, FTP, PBAP, etc) for each server, allow one server to have multiple application profiles and select the one to use with the help of the Connect commands target header. --- obexd/src/bluetooth.c | 10 +++--- obexd/src/main.c | 84 ++++++++++++++++--------------------------- obexd/src/manager.c | 4 +-- obexd/src/obex.c | 79 ++++++++++++++++++++++++---------------- obexd/src/obex.h | 10 +++--- 5 files changed, 90 insertions(+), 97 deletions(-) diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c index f0014bdd1..8c3f56401 100644 --- a/obexd/src/bluetooth.c +++ b/obexd/src/bluetooth.c @@ -85,17 +85,15 @@ 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_OPP) { - if (obex_session_start(nsk, server) < 0) + if (server->services != OBEX_OPP) { + if (request_service_authorization(server, nsk) < 0) close(nsk); return TRUE; } - if (request_service_authorization(server, nsk) < 0) { + if (obex_session_start(nsk, server) < 0) close(nsk); - return TRUE; - } return TRUE; } @@ -165,7 +163,7 @@ static gint server_register(guint16 service, const gchar *name, guint8 channel, } server = g_malloc0(sizeof(struct server)); - server->service = service; + server->services = service; server->name = g_strdup(name); server->folder = g_strdup(folder); server->auto_accept = auto_accept; diff --git a/obexd/src/main.c b/obexd/src/main.c index 24a002cae..4a3ac46e3 100644 --- a/obexd/src/main.c +++ b/obexd/src/main.c @@ -59,17 +59,17 @@ static GMainLoop *main_loop = NULL; -static void tty_init(int service, const gchar *root_path, - const gchar *capability, const gchar *devnode) +static int tty_init(int services, const gchar *root_path, + const gchar *capability, const gchar *devnode) { struct server *server; struct termios options; - gint fd; + int fd, ret; glong flags; fd = open(devnode, O_RDWR); if (fd < 0) - return; + return fd; flags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); @@ -79,52 +79,18 @@ static void tty_init(int service, const gchar *root_path, tcsetattr(fd, TCSANOW, &options); server = g_malloc0(sizeof(struct server)); - server->service = service; + server->services = services; server->folder = g_strdup(root_path); server->auto_accept = TRUE; server->capability = g_strdup(capability); - if (obex_session_start(fd, server) < 0) + ret = obex_session_start(fd, server); + if (ret < 0) { + server_free(server); close(fd); - - return; -} - -static int server_start(int service, const char *root_path, - gboolean auto_accept, const gchar *capability, - const char *devnode) -{ - switch (service) { - case OBEX_OPP: - bluetooth_init(OBEX_OPP, "Object Push server", - root_path, OPP_CHANNEL, FALSE, - auto_accept, capability); - if (devnode) - tty_init(OBEX_OPP, root_path, capability, devnode); - break; - case OBEX_FTP: - 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; } - return 0; -} - -static void server_stop() -{ - /* FIXME: If Bluetooth enabled */ - bluetooth_exit(); + return ret; } static void sig_term(int sig) @@ -172,7 +138,7 @@ int main(int argc, char *argv[]) GOptionContext *context; GError *err = NULL; struct sigaction sa; - int log_option = LOG_NDELAY | LOG_PID; + int log_option = LOG_NDELAY | LOG_PID, services; #ifdef NEED_THREADS if (g_thread_supported() == FALSE) @@ -237,16 +203,28 @@ int main(int argc, char *argv[]) if (option_capability == NULL) option_capability = g_strdup(DEFAULT_CAP_FILE); - if (option_opp == TRUE) - server_start(OBEX_OPP, option_root, option_autoaccept, - NULL, option_devnode); + if (option_opp == TRUE) { + services |= OBEX_OPP; + bluetooth_init(OBEX_OPP, "Object Push server", option_root, + OPP_CHANNEL, FALSE, option_autoaccept, NULL); + } - if (option_ftp == TRUE) - server_start(OBEX_FTP, option_root, option_autoaccept, - option_capability, option_devnode); + if (option_ftp == TRUE) { + services |= OBEX_FTP; + bluetooth_init(OBEX_FTP, "File Transfer server", option_root, + FTP_CHANNEL, TRUE, option_autoaccept, + option_capability); + } - if (option_pbap == TRUE) - server_start(OBEX_PBAP, NULL, FALSE, NULL, NULL); + if (option_pbap == TRUE) { + services |= OBEX_PBAP; + bluetooth_init(OBEX_PBAP, "Phonebook Access server", NULL, + PBAP_CHANNEL, TRUE, FALSE, NULL); + } + + if (option_devnode) + tty_init(services, option_root, option_capability, + option_devnode); memset(&sa, 0, sizeof(sa)); sa.sa_handler = sig_term; @@ -255,7 +233,7 @@ int main(int argc, char *argv[]) g_main_loop_run(main_loop); - server_stop(); + bluetooth_exit(); plugin_cleanup(); diff --git a/obexd/src/manager.c b/obexd/src/manager.c index d79c6d89b..c479fb32f 100644 --- a/obexd/src/manager.c +++ b/obexd/src/manager.c @@ -549,7 +549,7 @@ void register_record(gpointer data, gpointer user_data) return; } - xml = create_xml_record(server->name, server->service, server->channel); + xml = create_xml_record(server->name, server->services, server->channel); ret = add_record(any->path, xml, server); g_free(xml); } @@ -579,7 +579,7 @@ static void find_adapter_reply(DBusPendingCall *call, gpointer user_data) for (l = any->servers; l; l = l->next) { server = l->data; xml = create_xml_record(server->name, - server->service, server->channel); + server->services, server->channel); add_record(path, xml, server); g_free(xml); } diff --git a/obexd/src/obex.c b/obexd/src/obex.c index 403e6cc9d..4768cdf70 100644 --- a/obexd/src/obex.c +++ b/obexd/src/obex.c @@ -214,19 +214,39 @@ static void cmd_connect(struct obex_session *os, /* connection id will be used to track the sessions, even for OPP */ os->cid = ++cid; - if (os->target == NULL) { - register_transfer(os->cid, os); - /* OPP doesn't contains target or connection id. */ - OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); + while (OBEX_ObjectGetNextHeader(obex, obj, &hi, &hd, &hlen)) { + if (hi != OBEX_HDR_TARGET || hlen != TARGET_SIZE) + continue; + + if (memcmp(hd.bs, FTP_TARGET, TARGET_SIZE) == 0 && + os->server->services & OBEX_FTP) { + os->target = FTP_TARGET; + os->cmds = &ftp; + break; + } + + if (memcmp(hd.bs, PBAP_TARGET, TARGET_SIZE) == 0 && + os->server->services & OBEX_PBAP) { + os->target = PBAP_TARGET; + os->cmds = &pbap; + break; + } + + error("Connect attempt to a non-supported target"); + OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); return; } - hi = hlen = 0; - OBEX_ObjectGetNextHeader(obex, obj, &hi, &hd, &hlen); + if (os->target == NULL) { + if (os->server->services & OBEX_OPP) { + register_transfer(os->cid, os); + /* OPP doesn't contains target or connection id. */ + OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); + } else { + error("Object Push connect attempt to a non-OPP server"); + OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); + } - if (hi != OBEX_HDR_TARGET || hlen != TARGET_SIZE - || memcmp(os->target, hd.bs, TARGET_SIZE) != 0) { - OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); return; } @@ -234,6 +254,7 @@ static void cmd_connect(struct obex_session *os, emit_session_created(cid); /* Append received UUID in WHO header */ + hd.bs = os->target; OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_WHO, hd, TARGET_SIZE, OBEX_FL_FIT_ONE_PACKET); @@ -281,7 +302,10 @@ static void cmd_get(struct obex_session *os, obex_t *obex, obex_object_t *obj) guint hlen; guint8 hi; - if (!os->cmds->get) { + if (!os->cmds) { + OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); + return; + } else if (!os->cmds->get) { OBEX_ObjectSetRsp(obj, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); return; @@ -355,7 +379,10 @@ static void cmd_setpath(struct obex_session *os, guint32 hlen; guint8 hi; - if (!os->cmds->setpath) { + if (!os->cmds) { + OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); + return; + } else if (!os->cmds->setpath) { OBEX_ObjectSetRsp(obj, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); return; @@ -659,7 +686,7 @@ static gboolean check_put(obex_t *obex, obex_object_t *obj) return FALSE; } - if (!os->cmds->chkput) + if (!os->cmds || !os->cmds->chkput) goto done; ret = os->cmds->chkput(obex, obj); @@ -708,7 +735,10 @@ done: static void cmd_put(struct obex_session *os, obex_t *obex, obex_object_t *obj) { - if (!os->cmds->put) { + if (!os->cmds) { + OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN); + return; + } else if (!os->cmds->put) { OBEX_ObjectSetRsp(obj, OBEX_RSP_NOT_IMPLEMENTED, OBEX_RSP_NOT_IMPLEMENTED); return; @@ -784,7 +814,7 @@ static void obex_event(obex_t *obex, obex_object_t *obj, gint mode, case OBEX_EV_REQCHECK: switch (cmd) { case OBEX_CMD_PUT: - if (os->cmds->put) + if (os->cmds && os->cmds->put) check_put(obex, obj); break; default: @@ -904,24 +934,11 @@ gint obex_session_start(gint fd, struct server *server) gint ret; os = g_new0(struct obex_session, 1); - switch (server->service) { - case OBEX_OPP: - os->target = NULL; + + os->target = NULL; + + if (server->services & OBEX_OPP) os->cmds = &opp; - break; - case OBEX_FTP: - 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"); - return -EINVAL; - } os->current_folder = g_strdup(server->folder); os->server = server; diff --git a/obexd/src/obex.h b/obexd/src/obex.h index 01dacfdfb..6718942e5 100644 --- a/obexd/src/obex.h +++ b/obexd/src/obex.h @@ -29,10 +29,10 @@ #include -#define OBEX_OPP 0x01 -#define OBEX_FTP 0x02 -#define OBEX_BIP 0x03 -#define OBEX_PBAP 0x04 +#define OBEX_OPP (1 << 0) +#define OBEX_FTP (1 << 2) +#define OBEX_BIP (1 << 3) +#define OBEX_PBAP (1 << 4) #define OBJECT_SIZE_UNKNOWN -1 #define OBJECT_SIZE_DELETE -2 @@ -45,7 +45,7 @@ struct obex_commands { }; struct server { - guint16 service; + guint16 services; gboolean auto_accept; gchar *name; gchar *folder; -- 2.47.3