diff options
Diffstat (limited to 'daemon/echo.c')
-rw-r--r-- | daemon/echo.c | 448 |
1 files changed, 0 insertions, 448 deletions
diff --git a/daemon/echo.c b/daemon/echo.c deleted file mode 100644 index 09ceef31..00000000 --- a/daemon/echo.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * - * BlueZ - Bluetooth protocol stack for Linux - * - * Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org> - * - * - * 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 <config.h> -#endif - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <sys/socket.h> - -#include <bluetooth/bluetooth.h> -#include <bluetooth/rfcomm.h> -#include <bluetooth/sdp.h> -#include <bluetooth/sdp_lib.h> - -#include <glib.h> - -#include <dbus/dbus.h> - -#include "dbus.h" -#include "logging.h" - -struct auth_data { - DBusConnection *conn; - GIOChannel *io; - char *address; -}; - -static gboolean session_event(GIOChannel *chan, - GIOCondition cond, gpointer data) -{ - unsigned char buf[672]; - gsize len, written; - GIOError err; - - if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) - return FALSE; - - err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); - if (err == G_IO_ERROR_AGAIN) - return TRUE; - - g_io_channel_write(chan, (const gchar *) buf, len, &written); - - return TRUE; -} - -static void cancel_authorization(DBusConnection *conn, const char *address) -{ - DBusMessage *msg; - const char *string = ""; - - info("Canceling authorization for %s", address); - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "CancelAuthorizationRequest"); - if (!msg) { - error("Allocation of method message failed"); - return; - } - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID); - - dbus_connection_send(conn, msg, NULL); - - dbus_message_unref(msg); -} - -static void authorization_callback(DBusPendingCall *call, void *data) -{ - DBusMessage *reply = dbus_pending_call_steal_reply(call); - struct auth_data *auth = data; - DBusError err; - - dbus_error_init(&err); - - if (dbus_set_error_from_message(&err, reply)) { - error("Access denied: %s", err.message); - if (dbus_error_has_name(&err, DBUS_ERROR_NO_REPLY)) - cancel_authorization(auth->conn, auth->address); - dbus_error_free(&err); - } else { - info("Accepting incoming connection"); - g_io_add_watch(auth->io, - G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, - session_event, NULL); - } - - g_io_channel_unref(auth->io); - - dbus_message_unref(reply); -} - -static void authorization_free(void *data) -{ - struct auth_data *auth = data; - - g_free(auth->address); - g_free(auth); -} - -static int request_authorization(DBusConnection *conn, - GIOChannel *io, const char *address) -{ - DBusMessage *msg; - DBusPendingCall *pending; - struct auth_data *auth; - const char *string = ""; - - info("Requesting authorization for %s", address); - - auth = g_try_malloc0(sizeof(*auth)); - if (!auth) { - error("Allocation of auth object failed"); - return -1; - } - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "RequestAuthorization"); - if (!msg) { - error("Allocation of method message failed"); - g_free(auth); - return -1; - } - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &address, - DBUS_TYPE_STRING, &string, DBUS_TYPE_INVALID); - - if (dbus_connection_send_with_reply(conn, msg, &pending, -1) == FALSE) { - error("Sending of authorization request failed"); - dbus_message_unref(msg); - g_free(auth); - return -1; - } - - auth->conn = conn; - auth->io = io; - auth->address = g_strdup(address); - - dbus_pending_call_set_notify(pending, authorization_callback, - auth, authorization_free); - - dbus_pending_call_unref(pending); - - dbus_message_unref(msg); - - return 0; -} - -static gboolean connect_event(GIOChannel *chan, - GIOCondition cond, gpointer data) -{ - DBusConnection *conn = data; - GIOChannel *io; - struct sockaddr_rc addr; - socklen_t optlen; - char address[18]; - int sk, nsk; - - sk = g_io_channel_unix_get_fd(chan); - - memset(&addr, 0, sizeof(addr)); - optlen = sizeof(addr); - - nsk = accept(sk, (struct sockaddr *) &addr, &optlen); - if (nsk < 0) - return TRUE; - - io = g_io_channel_unix_new(nsk); - g_io_channel_set_close_on_unref(io, TRUE); - - ba2str(&addr.rc_bdaddr, address); - - if (request_authorization(conn, io, address) < 0) { - close(nsk); - return TRUE; - } - - return TRUE; -} - -static GIOChannel *setup_rfcomm(DBusConnection *conn, uint8_t channel) -{ - GIOChannel *io; - struct sockaddr_rc addr; - int sk; - - sk = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (sk < 0) - return NULL; - - memset(&addr, 0, sizeof(addr)); - addr.rc_family = AF_BLUETOOTH; - bacpy(&addr.rc_bdaddr, BDADDR_ANY); - addr.rc_channel = channel; - - if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - close(sk); - return NULL; - } - - if (listen(sk, 10) < 0) { - close(sk); - return NULL; - } - - io = g_io_channel_unix_new(sk); - g_io_channel_set_close_on_unref(io, TRUE); - - g_io_add_watch(io, G_IO_IN, connect_event, conn); - - return io; -} - -static int setup_sdp(DBusConnection *conn, uint8_t channel) -{ - DBusMessage *msg, *reply; - DBusError err; - sdp_record_t *record; - sdp_buf_t buf; - sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto; - uuid_t root_uuid, l2cap, rfcomm, spp; - sdp_profile_desc_t profile[1]; - sdp_list_t *proto[2]; - sdp_data_t *chan; - - record = sdp_record_alloc(); - if (!record) { - error("Allocation of service record failed"); - return -1; - } - - sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); - root = sdp_list_append(NULL, &root_uuid); - sdp_set_browse_groups(record, root); - - sdp_uuid16_create(&l2cap, L2CAP_UUID); - proto[0] = sdp_list_append(NULL, &l2cap); - apseq = sdp_list_append(NULL, proto[0]); - - chan = sdp_data_alloc(SDP_UINT8, &channel); - sdp_uuid16_create(&rfcomm, RFCOMM_UUID); - proto[1] = sdp_list_append(NULL, &rfcomm); - proto[1] = sdp_list_append(proto[1], chan); - apseq = sdp_list_append(apseq, proto[1]); - - aproto = sdp_list_append(NULL, apseq); - sdp_set_access_protos(record, aproto); - - sdp_uuid16_create(&spp, SERIAL_PORT_SVCLASS_ID); - svclass = sdp_list_append(NULL, &spp); - sdp_set_service_classes(record, svclass); - - sdp_uuid16_create(&profile[0].uuid, SERIAL_PORT_PROFILE_ID); - profile[0].version = 0x0100; - pfseq = sdp_list_append(NULL, &profile[0]); - sdp_set_profile_descs(record, pfseq); - - sdp_set_info_attr(record, "Echo service", NULL, NULL); - - if (sdp_gen_record_pdu(record, &buf) < 0) { - error("Generation of service record failed"); - sdp_record_free(record); - return -1; - } - - sdp_data_free(chan); - sdp_list_free(root, NULL); - sdp_list_free(apseq, NULL); - sdp_list_free(pfseq, NULL); - sdp_list_free(aproto, NULL); - sdp_list_free(svclass, NULL); - sdp_list_free(proto[0], NULL); - sdp_list_free(proto[1], NULL); - - sdp_record_free(record); - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "AddServiceRecord"); - if (!msg) { - error("Allocation of method message failed"); - return -1; - } - - dbus_message_append_args(msg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, - &buf.data, buf.data_size, DBUS_TYPE_INVALID); - - dbus_error_init(&err); - - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); - - dbus_message_unref(msg); - - free(buf.data); - - if (!reply) { - error("Registration of service record failed"); - error("%s", err.message); - dbus_error_free(&err); - return -1; - } - - dbus_message_unref(reply); - - dbus_connection_flush(conn); - - return 0; -} - -static int register_standalone(DBusConnection *conn) -{ - DBusMessage *msg, *reply; - DBusError err; - const char *ident = "echo", *name = "Echo service", *desc = ""; - - info("Registering service"); - - msg = dbus_message_new_method_call("org.bluez", "/org/bluez", - "org.bluez.Database", "RegisterService"); - if (!msg) { - error("Allocation of method message failed"); - return -1; - } - - dbus_message_append_args(msg, DBUS_TYPE_STRING, &ident, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &desc, DBUS_TYPE_INVALID); - - dbus_error_init(&err); - - reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err); - - dbus_message_unref(msg); - - if (!reply) { - error("Registration of service failed"); - error("%s", err.message); - dbus_error_free(&err); - return -1; - } - - dbus_message_unref(reply); - - dbus_connection_flush(conn); - - return 0; -} - -static GMainLoop *main_loop = NULL; - -static void sig_term(int sig) -{ - g_main_loop_quit(main_loop); -} - -int main(int argc, char *argv[]) -{ - DBusConnection *conn; - GIOChannel *io; - struct sigaction sa; - char *addr; - - start_logging("echo", "Bluetooth echo service ver %s", VERSION); - - memset(&sa, 0, sizeof(sa)); - sa.sa_flags = SA_NOCLDSTOP; - sa.sa_handler = sig_term; - sigaction(SIGTERM, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - - sa.sa_handler = SIG_IGN; - sigaction(SIGCHLD, &sa, NULL); - sigaction(SIGPIPE, &sa, NULL); - - enable_debug(); - - addr = getenv("BLUETOOTHD_ADDRESS"); - if (!addr) { - error("No D-Bus server address available"); - exit(1); - } - - debug("Bluetooth daemon at %s", addr); - - main_loop = g_main_loop_new(NULL, FALSE); - - if (argc > 1 && !strcmp(argv[1], "-s")) - conn = init_dbus_direct(addr); - else - conn = init_dbus(NULL, NULL, NULL); - - if (!conn) { - error("Connection to bus failed"); - g_main_loop_unref(main_loop); - exit(1); - } - - io = setup_rfcomm(conn, 23); - if (!io) { - error("Creation of server channel failed"); - dbus_connection_unref(conn); - g_main_loop_unref(main_loop); - exit(1); - } - - setup_sdp(conn, 23); - - if (argc > 1 && !strcmp(argv[1], "-s")) - register_standalone(conn); - - g_main_loop_run(main_loop); - - g_io_channel_unref(io); - - dbus_connection_unref(conn); - - g_main_loop_unref(main_loop); - - info("Exit"); - - stop_logging(); - - return 0; -} |