static void rfcomm_connect_cb(GIOChannel *chan, GError *conn_err, gpointer user_data) { struct serial_port *port = user_data; struct serial_device *device = port->device; struct rfcomm_dev_req req; int sk, fd; DBusMessage *reply; /* Owner exited? */ if (!port->listener_id) return; if (conn_err) { error("%s", conn_err->message); reply = btd_error_failed(port->msg, conn_err->message); goto fail; } sk = g_io_channel_unix_get_fd(chan); if (dbus_message_has_member(port->msg, "ConnectFD")) { reply = g_dbus_create_reply(port->msg, DBUS_TYPE_UNIX_FD, &sk, DBUS_TYPE_INVALID); g_dbus_send_message(device->conn, reply); close(sk); g_dbus_remove_watch(device->conn, port->listener_id); port->listener_id = 0; return; } memset(&req, 0, sizeof(req)); req.dev_id = -1; req.flags = (1 << RFCOMM_REUSE_DLC); bacpy(&req.src, &device->src); bacpy(&req.dst, &device->dst); req.channel = port->channel; g_io_channel_unref(port->io); port->io = NULL; port->id = ioctl(sk, RFCOMMCREATEDEV, &req); if (port->id < 0) { int err = -errno; error("ioctl(RFCOMMCREATEDEV): %s (%d)", strerror(-err), -err); reply = btd_error_failed(port->msg, strerror(-err)); g_io_channel_shutdown(chan, TRUE, NULL); goto fail; } port->dev = g_strdup_printf("/dev/rfcomm%d", port->id); DBG("Serial port %s created", port->dev); g_io_channel_shutdown(chan, TRUE, NULL); /* Addressing connect port */ fd = port_open(port); if (fd < 0) /* Open in progress: Wait the callback */ return; open_notify(fd, 0, port); return; fail: g_dbus_send_message(device->conn, reply); g_dbus_remove_watch(device->conn, port->listener_id); port->listener_id = 0; }
static gboolean io_glib_callback( GIOChannel *source, GIOCondition cond, gpointer data ) { struct io_glib_cbinfo *cbinfo = (struct io_glib_cbinfo *)data; return cbinfo->callback( g_io_channel_unix_get_fd(source), cbinfo->cbdata); }
static int hidp_add_connection(const struct input_device *idev, const struct input_conn *iconn) { struct hidp_connadd_req *req; struct fake_hid *fake_hid; struct fake_input *fake; sdp_record_t *rec; char src_addr[18], dst_addr[18]; int err; req = g_new0(struct hidp_connadd_req, 1); req->ctrl_sock = g_io_channel_unix_get_fd(iconn->ctrl_io); req->intr_sock = g_io_channel_unix_get_fd(iconn->intr_io); req->flags = 0; req->idle_to = iconn->timeout; ba2str(&idev->src, src_addr); ba2str(&idev->dst, dst_addr); rec = fetch_record(src_addr, dst_addr, idev->handle); if (!rec) { error("Rejected connection from unknown device %s", dst_addr); err = -EPERM; goto cleanup; } extract_hid_record(rec, req); sdp_record_free(rec); read_device_id(src_addr, dst_addr, NULL, &req->vendor, &req->product, &req->version); fake_hid = get_fake_hid(req->vendor, req->product); if (fake_hid) { err = 0; fake = g_new0(struct fake_input, 1); fake->connect = fake_hid_connect; fake->disconnect = fake_hid_disconnect; fake->priv = fake_hid; fake->idev = idev; fake = fake_hid_connadd(fake, iconn->intr_io, fake_hid); if (fake == NULL) err = -ENOMEM; else fake->flags |= FI_FLAG_CONNECTED; goto cleanup; } if (idev->name) strncpy(req->name, idev->name, sizeof(req->name) - 1); /* Encryption is mandatory for keyboards */ if (req->subclass & 0x40) { struct btd_adapter *adapter = device_get_adapter(idev->device); err = btd_adapter_encrypt_link(adapter, (bdaddr_t *) &idev->dst, encrypt_completed, req); if (err == 0) { /* Waiting async encryption */ return 0; } else if (err != -EALREADY) { error("encrypt_link: %s (%d)", strerror(-err), -err); goto cleanup; } } err = ioctl_connadd(req); cleanup: free(req->rd_data); g_free(req); return err; }
int sap_server_register(const char *path, bdaddr_t *src) { sdp_record_t *record = NULL; GError *gerr = NULL; GIOChannel *io; if (sap_init() < 0) { error("Sap driver initialization failed."); return -1; } server = g_try_new0(struct sap_server, 1); if (!server) { sap_exit(); return -ENOMEM; } server->path = g_strdup(path); record = create_sap_record(SAP_SERVER_CHANNEL); if (!record) { error("Creating SAP SDP record failed."); goto sdp_err; } if (add_record_to_server(src, record) < 0) { error("Adding SAP SDP record to the SDP server failed."); sdp_record_free(record); goto sdp_err; } server->record_id = record->handle; io = bt_io_listen(BT_IO_RFCOMM, NULL, connect_confirm_cb, server, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_CHANNEL, SAP_SERVER_CHANNEL, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_HIGH, BT_IO_OPT_MASTER, TRUE, BT_IO_OPT_INVALID); if (!io) { error("Can't listen at channel %d.", SAP_SERVER_CHANNEL); g_error_free(gerr); goto server_err; } DBG("Listen socket 0x%02x", g_io_channel_unix_get_fd(io)); server->listen_io = io; server->conn = NULL; if (!g_dbus_register_interface(connection, path, SAP_SERVER_INTERFACE, server_methods, server_signals, NULL, server, destroy_sap_interface)) { error("D-Bus failed to register %s interface", SAP_SERVER_INTERFACE); goto server_err; } return 0; server_err: remove_record_from_server(server->record_id); sdp_err: server_free(server); sap_exit(); return -1; }
static gboolean bnep_setup(GIOChannel *chan, GIOCondition cond, gpointer user_data) { const uint8_t bt_base[] = { 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; struct network_adapter *na = user_data; struct network_server *ns; uint8_t packet[BNEP_MTU]; struct bnep_setup_conn_req *req = (void *) packet; uint16_t dst_role = 0; uint32_t val; int n, sk; char *bridge = NULL; if (cond & G_IO_NVAL) return FALSE; if (cond & (G_IO_ERR | G_IO_HUP)) { error("Hangup or error on BNEP socket"); return FALSE; } sk = g_io_channel_unix_get_fd(chan); /* * BNEP_SETUP_CONNECTION_REQUEST_MSG should be read and left in case * of kernel setup connection msg handling. */ n = recv(sk, packet, sizeof(packet), MSG_PEEK); if (n < 0) { error("read(): %s(%d)", strerror(errno), errno); return FALSE; } /* * Initial received data packet is BNEP_SETUP_CONNECTION_REQUEST_MSG * minimal size of this frame is 3 octets: 1 byte of BNEP Type + * 1 byte of BNEP Control Type + 1 byte of BNEP services UUID size. */ if (n < 3) { error("To few setup connection request data received"); return FALSE; } switch (req->uuid_size) { case 2: dst_role = get_be16(req->service); break; case 16: if (memcmp(&req->service[4], bt_base, sizeof(bt_base)) != 0) break; /* Intentional no-brake */ case 4: val = get_be32(req->service); if (val > 0xffff) break; dst_role = val; break; default: break; } ns = find_server(na->servers, dst_role); if (!ns || !ns->record_id || !ns->bridge) error("Server error, bridge not initialized: (0x%x)", dst_role); else bridge = ns->bridge; strncpy(na->setup->dev, BNEP_INTERFACE, 16); na->setup->dev[15] = '\0'; if (bnep_server_add(sk, bridge, na->setup->dev, &na->setup->dst, packet, n) < 0) error("BNEP server cannot be added"); na->setup = NULL; return FALSE; }
static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct bnep *session = data; struct bnep_control_rsp *rsp; struct timeval timeo; char pkt[BNEP_MTU]; ssize_t r; int sk; if (cond & G_IO_NVAL) return FALSE; if (session->setup_to > 0) { g_source_remove(session->setup_to); session->setup_to = 0; } if (cond & (G_IO_HUP | G_IO_ERR)) { error("Hangup or error on l2cap server socket"); goto failed; } sk = g_io_channel_unix_get_fd(chan); memset(pkt, 0, BNEP_MTU); r = read(sk, pkt, sizeof(pkt) - 1); if (r < 0) { error("IO Channel read error"); goto failed; } if (r == 0) { error("No packet received on l2cap socket"); goto failed; } errno = EPROTO; if ((size_t) r < sizeof(*rsp)) { error("Packet received is not bnep type"); goto failed; } rsp = (void *) pkt; if (rsp->type != BNEP_CONTROL) { error("Packet received is not bnep type"); goto failed; } if (rsp->ctrl != BNEP_SETUP_CONN_RSP) return TRUE; r = ntohs(rsp->resp); if (r != BNEP_SUCCESS) { error("bnep failed"); goto failed; } memset(&timeo, 0, sizeof(timeo)); timeo.tv_sec = 0; setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); sk = g_io_channel_unix_get_fd(session->io); if (bnep_connadd(sk, session->src, session->iface)) { error("bnep conn could not be added"); goto failed; } if (bnep_if_up(session->iface)) { error("could not up %s", session->iface); bnep_conndel(&session->dst_addr); goto failed; } session->watch = g_io_add_watch(session->io, G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc) bnep_watchdog_cb, session); g_io_channel_unref(session->io); session->io = NULL; session->conn_cb(session->iface, 0, session->conn_data); return FALSE; failed: session->conn_cb(NULL, -EIO, session->conn_data); return FALSE; }
static gboolean io_invoke(GIOChannel *source, GIOCondition condition, gpointer data) { get_stdin_string(NULL, g_io_channel_unix_get_fd(source), 0); return(true); }
static void bt_hid_get_report(const void *buf, uint16_t len) { const struct hal_cmd_hidhost_get_report *cmd = buf; struct hid_device *dev; GSList *l; bdaddr_t dst; int fd; uint8_t *req; uint8_t req_size; uint8_t status; DBG(""); switch (cmd->type) { case HAL_HIDHOST_INPUT_REPORT: case HAL_HIDHOST_OUTPUT_REPORT: case HAL_HIDHOST_FEATURE_REPORT: break; default: status = HAL_STATUS_INVALID; goto failed; } android2bdaddr(&cmd->bdaddr, &dst); l = g_slist_find_custom(devices, &dst, device_cmp); if (!l) { status = HAL_STATUS_FAILED; goto failed; } dev = l->data; req_size = (cmd->buf_size > 0) ? 4 : 2; req = g_try_malloc0(req_size); if (!req) { status = HAL_STATUS_NOMEM; goto failed; } req[0] = HID_MSG_GET_REPORT | cmd->type; req[1] = cmd->id; if (cmd->buf_size > 0) { req[0] = req[0] | HID_GET_REPORT_SIZE_FIELD; put_le16(cmd->buf_size, &req[2]); } fd = g_io_channel_unix_get_fd(dev->ctrl_io); if (write(fd, req, req_size) < 0) { error("hidhost: error writing hid_get_report: %s (%d)", strerror(errno), errno); g_free(req); status = HAL_STATUS_FAILED; goto failed; } dev->last_hid_msg = HID_MSG_GET_REPORT; g_free(req); status = HAL_STATUS_SUCCESS; failed: ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT, status); }
static void bt_hid_send_data(const void *buf, uint16_t len) { const struct hal_cmd_hidhost_send_data *cmd = buf; struct hid_device *dev; GSList *l; bdaddr_t dst; int fd; uint8_t *req = NULL; uint8_t req_size; uint8_t status; DBG(""); if (len != sizeof(*cmd) + cmd->len) { error("Invalid hid send data size (%u bytes), terminating", len); raise(SIGTERM); return; } android2bdaddr(&cmd->bdaddr, &dst); l = g_slist_find_custom(devices, &dst, device_cmp); if (!l) { status = HAL_STATUS_FAILED; goto failed; } dev = l->data; if (!(dev->intr_io)) { status = HAL_STATUS_FAILED; goto failed; } req_size = 1 + (cmd->len / 2); req = g_try_malloc0(req_size); if (!req) { status = HAL_STATUS_NOMEM; goto failed; } req[0] = HID_MSG_DATA | HID_DATA_TYPE_OUTPUT; /* * Report data coming to HAL is in ascii format, HAL sends * data in hex to daemon, so convert to binary. */ if (!hex2buf(cmd->data, req + 1, req_size - 1)) { status = HAL_STATUS_INVALID; goto failed; } fd = g_io_channel_unix_get_fd(dev->intr_io); if (write(fd, req, req_size) < 0) { error("hidhost: error writing data to HID device: %s (%d)", strerror(errno), errno); status = HAL_STATUS_FAILED; goto failed; } status = HAL_STATUS_SUCCESS; failed: g_free(req); ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA, status); }
static void bt_hid_set_report(const void *buf, uint16_t len) { const struct hal_cmd_hidhost_set_report *cmd = buf; struct hid_device *dev; GSList *l; bdaddr_t dst; int i, fd; uint8_t *req; uint8_t req_size; uint8_t status; DBG(""); if (len != sizeof(*cmd) + cmd->len) { error("Invalid hid set report size (%u bytes), terminating", len); raise(SIGTERM); return; } switch (cmd->type) { case HAL_HIDHOST_INPUT_REPORT: case HAL_HIDHOST_OUTPUT_REPORT: case HAL_HIDHOST_FEATURE_REPORT: break; default: status = HAL_STATUS_INVALID; goto failed; } android2bdaddr(&cmd->bdaddr, &dst); l = g_slist_find_custom(devices, &dst, device_cmp); if (!l) { status = HAL_STATUS_FAILED; goto failed; } dev = l->data; if (!(dev->ctrl_io)) { status = HAL_STATUS_FAILED; goto failed; } req_size = 1 + (cmd->len / 2); req = g_try_malloc0(req_size); if (!req) { status = HAL_STATUS_NOMEM; goto failed; } req[0] = HID_MSG_SET_REPORT | cmd->type; /* Report data coming to HAL is in ascii format, HAL sends * data in hex to daemon, so convert to binary. */ for (i = 0; i < (req_size - 1); i++) sscanf((char *) &(cmd->data)[i * 2], "%hhx", &(req + 1)[i]); fd = g_io_channel_unix_get_fd(dev->ctrl_io); if (write(fd, req, req_size) < 0) { error("error writing hid_set_report: %s (%d)", strerror(errno), errno); g_free(req); status = HAL_STATUS_FAILED; goto failed; } dev->last_hid_msg = HID_MSG_SET_REPORT; g_free(req); status = HAL_STATUS_SUCCESS; failed: ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT, status); }
static gboolean uhid_event_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct hid_device *dev = user_data; struct uhid_event ev; ssize_t bread; int fd; DBG(""); if (cond & (G_IO_ERR | G_IO_NVAL)) goto failed; fd = g_io_channel_unix_get_fd(io); memset(&ev, 0, sizeof(ev)); bread = read(fd, &ev, sizeof(ev)); if (bread < 0) { DBG("read: %s (%d)", strerror(errno), errno); goto failed; } DBG("uHID event type %d received", ev.type); switch (ev.type) { case UHID_START: case UHID_STOP: /* These are called to start and stop the underlying hardware. * We open the channels before creating the device so the * hardware is always ready. No need to handle these. * The kernel never destroys a device itself! Only an explicit * UHID_DESTROY request can remove a device. */ break; case UHID_OPEN: case UHID_CLOSE: /* OPEN/CLOSE are sent whenever user-space opens any interface * provided by the kernel HID device. Whenever the open-count * is non-zero we must be ready for I/O. As long as it is zero, * we can decide to drop all I/O and put the device * asleep This is optional, though. */ break; case UHID_OUTPUT: handle_uhid_output(dev, &ev.u.output); break; case UHID_FEATURE: /* TODO */ break; case UHID_OUTPUT_EV: /* This is only sent by kernels prior to linux-3.11. It * requires us to parse HID-descriptors in user-space to * properly handle it. This is redundant as the kernel * does it already. That's why newer kernels assemble * the output-reports and send it to us via UHID_OUTPUT. */ DBG("UHID_OUTPUT_EV unsupported"); break; default: warn("unexpected uHID event"); } return TRUE; failed: dev->uhid_watch_id = 0; return FALSE; }
static gboolean mainloop_gio_callback(GIOChannel * gio, GIOCondition condition, gpointer data) { gboolean keep = TRUE; mainloop_io_t *client = data; CRM_ASSERT(client->fd == g_io_channel_unix_get_fd(gio)); if (condition & G_IO_IN) { if (client->ipc) { long rc = 0; int max = 10; do { rc = crm_ipc_read(client->ipc); if (rc <= 0) { crm_trace("Message acquisition from %s[%p] failed: %s (%ld)", client->name, client, pcmk_strerror(rc), rc); } else if (client->dispatch_fn_ipc) { const char *buffer = crm_ipc_buffer(client->ipc); crm_trace("New message from %s[%p] = %d", client->name, client, rc, condition); if (client->dispatch_fn_ipc(buffer, rc, client->userdata) < 0) { crm_trace("Connection to %s no longer required", client->name); keep = FALSE; } } } while (keep && rc > 0 && --max > 0); } else { crm_trace("New message from %s[%p] %u", client->name, client, condition); if (client->dispatch_fn_io) { if (client->dispatch_fn_io(client->userdata) < 0) { crm_trace("Connection to %s no longer required", client->name); keep = FALSE; } } } } if (client->ipc && crm_ipc_connected(client->ipc) == FALSE) { crm_err("Connection to %s[%p] closed (I/O condition=%d)", client->name, client, condition); keep = FALSE; } else if (condition & (G_IO_HUP | G_IO_NVAL | G_IO_ERR)) { crm_trace("The connection %s[%p] has been closed (I/O condition=%d)", client->name, client, condition); keep = FALSE; } else if ((condition & G_IO_IN) == 0) { /* #define GLIB_SYSDEF_POLLIN =1 #define GLIB_SYSDEF_POLLPRI =2 #define GLIB_SYSDEF_POLLOUT =4 #define GLIB_SYSDEF_POLLERR =8 #define GLIB_SYSDEF_POLLHUP =16 #define GLIB_SYSDEF_POLLNVAL =32 typedef enum { G_IO_IN GLIB_SYSDEF_POLLIN, G_IO_OUT GLIB_SYSDEF_POLLOUT, G_IO_PRI GLIB_SYSDEF_POLLPRI, G_IO_ERR GLIB_SYSDEF_POLLERR, G_IO_HUP GLIB_SYSDEF_POLLHUP, G_IO_NVAL GLIB_SYSDEF_POLLNVAL } GIOCondition; A bitwise combination representing a condition to watch for on an event source. G_IO_IN There is data to read. G_IO_OUT Data can be written (without blocking). G_IO_PRI There is urgent data to read. G_IO_ERR Error condition. G_IO_HUP Hung up (the connection has been broken, usually for pipes and sockets). G_IO_NVAL Invalid request. The file descriptor is not open. */ crm_err("Strange condition: %d", condition); } /* keep == FALSE results in mainloop_gio_destroy() being called * just before the source is removed from mainloop */ return keep; }
static void avctp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src, const bdaddr_t *dst, gpointer data) { socklen_t size; struct l2cap_options l2o; struct avctp *session; GIOCondition flags = G_IO_ERR | G_IO_HUP | G_IO_NVAL; struct audio_device *dev; char address[18]; if (err < 0) { error("AVCTP server socket: %s (%d)", strerror(-err), -err); return; } session = avctp_get(src, dst); if (!session) { error("Unable to create new AVCTP session"); goto drop; } if (session->sock >= 0) { error("Refusing unexpected connect from %s", address); goto drop; } dev = manager_find_device(&session->dst, AUDIO_CONTROL_INTERFACE, FALSE); if (!dev) { error("Unable to get audio device object for %s", address); goto drop; } if (!dev->control) dev->control = control_init(dev); device_remove_control_timer(dev); session->state = AVCTP_STATE_CONNECTING; session->sock = g_io_channel_unix_get_fd(chan); memset(&l2o, 0, sizeof(l2o)); size = sizeof(l2o); if (getsockopt(session->sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &size) < 0) { err = errno; error("getsockopt(L2CAP_OPTIONS): %s (%d)", strerror(err), err); avctp_unref(session); goto drop; } session->mtu = l2o.imtu; if (session->io) g_source_remove(session->io); session->io = g_io_add_watch(chan, flags, (GIOFunc) session_cb, session); g_io_channel_unref(chan); if (avdtp_is_connected(src, dst)) goto proceed; if (service_req_auth(src, dst, AVRCP_TARGET_UUID, auth_cb, session) < 0) goto drop; return; proceed: avctp_connect_session(session); return; drop: close(session->sock); }
static void connect_confirm_cb(GIOChannel *io, gpointer data) { struct sap_connection *conn = server->conn; GError *gerr = NULL; bdaddr_t src, dst; char srcaddr[18], dstaddr[18]; int err; DBG("io %p data %p ", io, data); if (!io) return; if (conn) { g_io_channel_shutdown(io, TRUE, NULL); return; } conn = g_try_new0(struct sap_connection, 1); if (!conn) { error("Can't allocate memory for incomming SAP connection."); g_io_channel_shutdown(io, TRUE, NULL); return; } g_io_channel_set_encoding(io, NULL, NULL); g_io_channel_set_buffered(io, FALSE); server->conn = conn; conn->io = g_io_channel_ref(io); conn->state = SAP_STATE_DISCONNECTED; bt_io_get(io, BT_IO_RFCOMM, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_INVALID); if (gerr) { error("%s", gerr->message); g_error_free(gerr); sap_conn_remove(conn); return; } //client_to_be_authorized = &dst; ba2str(&dst, dstaddr); ba2str(&src, srcaddr); if(sap_check_weak_linkkey(srcaddr, dstaddr) == TRUE) { DBG("SAP weak_key was detected."); sap_connect_rsp(conn, SAP_STATUS_CONNECTION_FAILED, SAP_BUF_SIZE); sap_conn_remove(conn); return; } err = btd_request_authorization(&src, &dst, SAP_UUID, connect_auth_cb, conn); if (err < 0) { DBG("Authorization denied: %d %s", err, strerror(err)); sap_conn_remove(conn); return; } DBG("SAP incoming connection (sock %d) authorization.", g_io_channel_unix_get_fd(io)); }
static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; int sk, new_sk; data->io_id = 0; sk = g_io_channel_unix_get_fd(io); new_sk = accept(sk, NULL, NULL); if (new_sk < 0) { tester_warn("accept failed: %s (%u)", strerror(errno), errno); tester_test_failed(); return FALSE; } if (!check_mtu(data, new_sk)) { tester_test_failed(); return FALSE; } if (l2data->read_data) { struct bthost *bthost; GIOChannel *new_io; new_io = g_io_channel_unix_new(new_sk); g_io_channel_set_close_on_unref(new_io, TRUE); bthost = hciemu_client_get_host(data->hciemu); g_io_add_watch(new_io, G_IO_IN, server_received_data, NULL); bthost_send_cid(bthost, data->handle, data->dcid, l2data->read_data, l2data->data_len); g_io_channel_unref(new_io); return FALSE; } else if (l2data->write_data) { struct bthost *bthost; ssize_t ret; bthost = hciemu_client_get_host(data->hciemu); bthost_add_cid_hook(bthost, data->handle, data->scid, server_bthost_received_data, NULL); ret = write(new_sk, l2data->write_data, l2data->data_len); close(new_sk); if (ret != l2data->data_len) { tester_warn("Unable to write all data"); tester_test_failed(); } return FALSE; } tester_print("Successfully connected"); close(new_sk); tester_test_passed(); return FALSE; }
static gboolean control_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct control *control = data; unsigned char buf[1024], *operands; struct avctp_header *avctp; struct avrcp_header *avrcp; int ret, packet_size, operand_count, sock; if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) goto failed; sock = g_io_channel_unix_get_fd(control->io); ret = read(sock, buf, sizeof(buf)); if (ret <= 0) goto failed; DBG("Got %d bytes of data for AVCTP session %p", ret, control); if ((unsigned int) ret < sizeof(struct avctp_header)) { error("Too small AVCTP packet"); goto failed; } packet_size = ret; avctp = (struct avctp_header *) buf; DBG("AVCTP transaction %u, packet type %u, C/R %u, IPID %u, " "PID 0x%04X", avctp->transaction, avctp->packet_type, avctp->cr, avctp->ipid, ntohs(avctp->pid)); ret -= sizeof(struct avctp_header); if ((unsigned int) ret < sizeof(struct avrcp_header)) { error("Too small AVRCP packet"); goto failed; } avrcp = (struct avrcp_header *) (buf + sizeof(struct avctp_header)); ret -= sizeof(struct avrcp_header); operands = buf + sizeof(struct avctp_header) + sizeof(struct avrcp_header); operand_count = ret; DBG("AVRCP %s 0x%01X, subunit_type 0x%02X, subunit_id 0x%01X, " "opcode 0x%02X, %d operands", avctp->cr ? "response" : "command", avrcp->code, avrcp->subunit_type, avrcp->subunit_id, avrcp->opcode, operand_count); if (avctp->packet_type != AVCTP_PACKET_SINGLE) { avctp->cr = AVCTP_RESPONSE; avrcp->code = CTYPE_NOT_IMPLEMENTED; } else if (avctp->pid != htons(AV_REMOTE_SVCLASS_ID)) { avctp->ipid = 1; avctp->cr = AVCTP_RESPONSE; avrcp->code = CTYPE_REJECTED; } else if (avctp->cr == AVCTP_COMMAND && avrcp->code == CTYPE_CONTROL && avrcp->subunit_type == SUBUNIT_PANEL && avrcp->opcode == OP_PASSTHROUGH) { handle_panel_passthrough(control, operands, operand_count); avctp->cr = AVCTP_RESPONSE; avrcp->code = CTYPE_ACCEPTED; } else if (avctp->cr == AVCTP_COMMAND && avrcp->code == CTYPE_STATUS && (avrcp->opcode == OP_UNITINFO || avrcp->opcode == OP_SUBUNITINFO)) { avctp->cr = AVCTP_RESPONSE; avrcp->code = CTYPE_STABLE; /* The first operand should be 0x07 for the UNITINFO response. * Neither AVRCP (section 22.1, page 117) nor AVC Digital * Interface Command Set (section 9.2.1, page 45) specs * explain this value but both use it */ if (operand_count >= 1 && avrcp->opcode == OP_UNITINFO) operands[0] = 0x07; if (operand_count >= 2) operands[1] = SUBUNIT_PANEL << 3; DBG("reply to %s", avrcp->opcode == OP_UNITINFO ? "OP_UNITINFO" : "OP_SUBUNITINFO"); } else { avctp->cr = AVCTP_RESPONSE; avrcp->code = CTYPE_REJECTED; } ret = write(sock, buf, packet_size); return TRUE; failed: DBG("AVCTP session %p got disconnected", control); avctp_set_state(control, AVCTP_STATE_DISCONNECTED); return FALSE; }
static gboolean l2cap_connect_cb(GIOChannel *io, GIOCondition cond, gpointer user_data) { struct test_data *data = tester_get_data(); const struct l2cap_data *l2data = data->test_data; int err, sk_err, sk; socklen_t len = sizeof(sk_err); data->io_id = 0; sk = g_io_channel_unix_get_fd(io); if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0) err = -errno; else err = -sk_err; if (err < 0) { tester_warn("Connect failed: %s (%d)", strerror(-err), -err); goto failed; } tester_print("Successfully connected"); if (!check_mtu(data, sk)) { tester_test_failed(); return FALSE; } if (l2data->read_data) { struct bthost *bthost; bthost = hciemu_client_get_host(data->hciemu); g_io_add_watch(io, G_IO_IN, client_received_data, NULL); bthost_send_cid(bthost, data->handle, data->dcid, l2data->read_data, l2data->data_len); return FALSE; } else if (l2data->write_data) { struct bthost *bthost; ssize_t ret; bthost = hciemu_client_get_host(data->hciemu); bthost_add_cid_hook(bthost, data->handle, data->dcid, bthost_received_data, NULL); ret = write(sk, l2data->write_data, l2data->data_len); if (ret != l2data->data_len) { tester_warn("Unable to write all data"); tester_test_failed(); } return FALSE; } failed: if (-err != l2data->expect_err) tester_test_failed(); else tester_test_passed(); return FALSE; }
/* * handle_new_connection */ static gboolean handle_new_connection ( GIOChannel *chan, GIOCondition cond, ajax_worker *aw ) { gint client_socket; struct sockaddr_un client_addr; socklen_t client_addr_len = sizeof ( struct sockaddr_un ); GIOChannel *client_chan; gchar *client_input; gsize client_input_len; gsize client_nbread; GError *error = NULL; guint i; gchar scgi_cmd[AJAX_REQUEST_SIZE]; gchar *scgi_prev_line, *scgi_request; FILE *client_chan_f; exchange *exch = EXCHANGES[0]; exchange *exch_list[EXCH_NB_MAX_MULTI] = { NULL, NULL, NULL, NULL }; gint nb_exch_multi = 0; view_length_id view_length = VIEW_LENGTH_8_H; view_mode_id view_mode = VIEW_MODE_SINGLE; gboolean sendBook = FALSE; gboolean sendFull = FALSE; gboolean sendList = FALSE; gboolean tickOnly = TRUE; gdouble toffset = -1; /* g_assert ( g_main_context_is_owner(aw->context) ); */ memset ( &client_addr, 0, sizeof(struct sockaddr_un) ); if ( (client_socket = accept(aw->server_socket, (struct sockaddr *) &client_addr, &client_addr_len)) < 0 ) { log_print ( "ajax-%u: unable to accept new connection: %s.\n", aw->uid, strerror(errno) ); return FALSE; } client_chan = g_io_channel_unix_new ( client_socket ); g_io_channel_read_line ( client_chan, &client_input, &client_nbread, NULL, &error ); if ( error != NULL ) { log_print ( "ajax-%u: chan reading said %s\n", aw->uid, error->message ); g_io_channel_shutdown ( client_chan, TRUE, NULL ); g_io_channel_unref ( client_chan ); return TRUE; } client_input_len = atoi(client_input) - 15; /* 15 = strlen("CONTENT_LENGTH\0") */ /*log_print ( "ajax-%u: scgi request has size: %lu\n", aw->uid, client_input_len );*/ if ( client_input_len > AJAX_REQUEST_SIZE ) { log_print ( "ajax-%u: scgi request is too big\n", aw->uid ); client_input_len = AJAX_REQUEST_SIZE - 1; scgi_cmd[AJAX_REQUEST_SIZE-1] = '\0'; } g_io_channel_read_chars ( client_chan, scgi_cmd, client_input_len, &client_nbread, &error ); if ( error != NULL ) { log_print ( "ajax-%u: chan reading said %s\n", aw->uid, error->message ); g_free ( client_input ); g_io_channel_shutdown ( client_chan, TRUE, NULL ); g_io_channel_unref ( client_chan ); return TRUE; } /* find the query string content */ scgi_prev_line = scgi_cmd; scgi_request = scgi_cmd; for ( i=0; i<client_input_len; ++i ) { if ( scgi_cmd[i] == '\0' ) { scgi_prev_line = scgi_request; scgi_request = scgi_cmd + i + 1; } if ( !strcmp("QUERY_STRING",scgi_prev_line) ) break; } /* if a query string was found, parse it */ if ( i<client_input_len ) { gchar *rq_end; gchar *rq_ptr; /*log_print ( "ajax-%u: scgi request is \'%s\'\n", aw->uid, scgi_request );*/ rq_end = index ( scgi_request, '\0' ); rq_ptr = scgi_request; while ( rq_ptr < rq_end ) { if ( ( rq_ptr[1] == '=' ) && ( (rq_end-rq_ptr) > 2 ) ) { switch ( rq_ptr[0] ) { case 'f': if ( rq_ptr[2] == '1' ) sendFull = TRUE; break; case 'l': if ( rq_ptr[2] == '1' ) sendList = TRUE; break; case 'e': exch = exchanges_lookup_by_uid ( rq_ptr+2 ); break; case 'E': nb_exch_multi = exchanges_lookup_multi_by_uid ( rq_ptr+2, &exch_list[0] ); break; case 'v': view_length = view_length_lookup ( rq_ptr+2 ); break; case 'm': view_mode = view_mode_lookup ( rq_ptr+2 ); break; case 'b': if ( rq_ptr[2] == '1' ) sendBook = TRUE; break; case 't': toffset = strtod ( rq_ptr+2, NULL ); break; case 'k': if ( rq_ptr[2] == '0' ) tickOnly = FALSE; break; default: break; } } rq_ptr = index ( rq_ptr, '&' ); if ( rq_ptr == NULL ) break; rq_ptr++; } } g_free ( client_input ); client_chan_f = fdopen ( dup(g_io_channel_unix_get_fd(client_chan)), "w" ); if ( client_chan_f == NULL ) { log_print ( "ajax-%u: unable to fdopen socket: %s.\n\n", aw->uid, strerror(errno) ); g_io_channel_shutdown ( client_chan, TRUE, NULL ); g_io_channel_unref ( client_chan ); return TRUE; } fputs ( "Status: 200 OK\nContent-Type: application/json\n\n", client_chan_f ); fputs ( COINREF_AJAX_HEAD, client_chan_f ); if ( exch == NULL ) exch = EXCHANGES[0]; if ( !tickOnly && !sendList ) { fputs ( COINREF_AJAX_DATA_HEAD, client_chan_f ); switch ( view_mode ) { case VIEW_MODE_MULTI: case VIEW_MODE_AVERAGE: { if ( nb_exch_multi == 0 ) exchange_write_json ( EXCHANGES[0], view_mode, view_length, sendFull, sendBook, toffset, client_chan_f ); else { for ( i=0; i<(nb_exch_multi-1); ++i ) { exchange_write_json ( exch_list[i], view_mode, view_length, sendFull, sendBook, toffset, client_chan_f ); fputc ( ',', client_chan_f ); } exchange_write_json ( exch_list[i], view_mode, view_length, sendFull, sendBook, toffset, client_chan_f ); } break; } case VIEW_MODE_SINGLE: default: { exchange_write_json ( exch, view_mode, view_length, sendFull, sendBook, toffset, client_chan_f ); break; } } if ( sendFull ) fputs ( COINREF_AJAX_DATA_FOOT COINREF_AJAX_FULL_OK, client_chan_f ); else fputs ( COINREF_AJAX_DATA_FOOT COINREF_AJAX_FULL_REJ, client_chan_f ); } if ( sendList ) exchanges_write_json_config ( client_chan_f ); else exchanges_write_json_ticker ( client_chan_f ); fputs ( COINREF_AJAX_FOOT, client_chan_f ); fclose ( client_chan_f ); g_io_channel_shutdown ( client_chan, TRUE, NULL ); g_io_channel_unref ( client_chan ); /*log_print ( "ajax-%u: handled a request\n", aw->uid );*/ aw->nb_requests++; return TRUE; }
/* Handle communications with the client. */ gboolean interface_client_event(GIOChannel* source, GIOCondition condition, gpointer data) { GString* buffer = NULL; GError* err = NULL; GIOStatus status; int client; command_result cr = CR_OK; client = g_io_channel_unix_get_fd(source); /* Ready for reading? */ if (condition & G_IO_IN) { buffer = g_string_sized_new(1024); if (!buffer) { g_warning("[ice:%d] Can't allocate buffer.", client); goto ice_client_clean; } /* Read exactly one command */ status = g_io_channel_read_line_string(source, buffer, NULL, &err); if (status == G_IO_STATUS_EOF) { g_debug("[ice:%d] Connection reset by peer.", client); goto ice_client_clean; } else if (status != G_IO_STATUS_NORMAL) { g_debug("[ice:%d] Can't read from IO channel: %s", client, err->message); goto ice_client_clean; } buffer->str[buffer->len-1] = '\0'; g_debug("[ice:%d] Received command: %s", client, buffer->str); buffer->str[buffer->len-1] = '\n'; /* Parse and run the command */ cr = interface_handle_command(source, buffer->str); g_string_free(buffer, TRUE); buffer = NULL; /* "idle" command? */ if (cr == CR_IDLE) { /* Add to list of idle channels */ g_idle_channels = g_list_prepend(g_idle_channels, source); } } /* Received hangup? */ if (condition & G_IO_HUP) { g_debug("[ice:%d] Connection hung up", client); goto ice_client_clean; } if (cr != CR_CLOSE) return TRUE; ice_client_clean: if (buffer) g_string_free(buffer, TRUE); g_idle_channels = g_list_remove(g_idle_channels, source); g_io_channel_shutdown(source, TRUE, NULL); g_io_channel_unref(source); g_info("[ice:%d] Connection closed.", client); return FALSE; }
static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct avctp *session = data; struct avctp_channel *browsing = session->browsing; uint8_t *buf = browsing->buffer; uint8_t *operands; struct avctp_header *avctp; int sock, ret, packet_size, operand_count; struct avctp_browsing_pdu_handler *handler; if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) goto failed; sock = g_io_channel_unix_get_fd(chan); ret = read(sock, buf, browsing->imtu); if (ret <= 0) goto failed; avctp = (struct avctp_header *) buf; if (avctp->packet_type != AVCTP_PACKET_SINGLE) goto failed; operands = buf + AVCTP_HEADER_LENGTH; ret -= AVCTP_HEADER_LENGTH; operand_count = ret; if (avctp->cr == AVCTP_RESPONSE) { browsing_response(browsing, avctp, operands, operand_count); return TRUE; } packet_size = AVCTP_HEADER_LENGTH; avctp->cr = AVCTP_RESPONSE; handler = g_slist_nth_data(browsing->handlers, 0); if (handler == NULL) { DBG("handler not found"); packet_size += avrcp_browsing_general_reject(operands); goto send; } packet_size += handler->cb(session, avctp->transaction, operands, operand_count, handler->user_data); send: if (packet_size != 0) { ret = write(sock, buf, packet_size); if (ret != packet_size) goto failed; } return TRUE; failed: DBG("AVCTP Browsing: disconnected"); avctp_set_state(session, AVCTP_STATE_CONNECTED); if (session->browsing) { avctp_channel_destroy(session->browsing); session->browsing = NULL; } return FALSE; }
static void sco_server_cb(GIOChannel *chan, GError *err, gpointer data) { int sk; struct audio_device *device; char addr[18]; bdaddr_t src, dst; if (err) { error("sco_server_cb: %s", err->message); return; } bt_io_get(chan, BT_IO_SCO, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID); if (err) { error("bt_io_get: %s", err->message); goto drop; } device = manager_find_device(NULL, &src, &dst, AUDIO_HEADSET_INTERFACE, FALSE); if (!device) device = manager_find_device(NULL, &src, &dst, AUDIO_GATEWAY_INTERFACE, FALSE); if (!device) goto drop; if (device->headset) { if (headset_get_state(device) < HEADSET_STATE_CONNECTED) { debug("Refusing SCO from non-connected headset"); goto drop; } if (!get_hfp_active(device)) { error("Refusing non-HFP SCO connect attempt from %s", addr); goto drop; } if (headset_connect_sco(device, chan) < 0) goto drop; headset_set_state(device, HEADSET_STATE_PLAYING); } else if (device->gateway) { if (!gateway_is_connected(device)) { debug("Refusing SCO from non-connected AG"); goto drop; } if (gateway_connect_sco(device, chan) < 0) goto drop; } else goto drop; sk = g_io_channel_unix_get_fd(chan); fcntl(sk, F_SETFL, 0); debug("Accepted SCO connection from %s", addr); return; drop: g_io_channel_shutdown(chan, TRUE, NULL); }
static gboolean session_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct avctp *session = data; struct avctp_channel *control = session->control; uint8_t *buf = control->buffer; uint8_t *operands, code, subunit; struct avctp_header *avctp; struct avc_header *avc; int ret, packet_size, operand_count, sock; struct avctp_pdu_handler *handler; if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) goto failed; sock = g_io_channel_unix_get_fd(chan); ret = read(sock, buf, control->imtu); if (ret <= 0) goto failed; if ((unsigned int) ret < sizeof(struct avctp_header)) { error("Too small AVCTP packet"); goto failed; } avctp = (struct avctp_header *) buf; ret -= sizeof(struct avctp_header); if ((unsigned int) ret < sizeof(struct avc_header)) { error("Too small AVCTP packet"); goto failed; } avc = (struct avc_header *) (buf + sizeof(struct avctp_header)); ret -= sizeof(struct avc_header); operands = buf + sizeof(struct avctp_header) + sizeof(struct avc_header); operand_count = ret; if (avctp->cr == AVCTP_RESPONSE) { control_response(control, avctp, avc, operands, operand_count); return TRUE; } packet_size = AVCTP_HEADER_LENGTH + AVC_HEADER_LENGTH; avctp->cr = AVCTP_RESPONSE; if (avctp->packet_type != AVCTP_PACKET_SINGLE) { avc->code = AVC_CTYPE_NOT_IMPLEMENTED; goto done; } if (avctp->pid != htons(AV_REMOTE_SVCLASS_ID)) { avctp->ipid = 1; packet_size = AVCTP_HEADER_LENGTH; goto done; } handler = find_handler(control->handlers, avc->opcode); if (!handler) { DBG("handler not found for 0x%02x", avc->opcode); packet_size += avrcp_handle_vendor_reject(&code, operands); avc->code = code; goto done; } code = avc->code; subunit = avc->subunit_type; packet_size += handler->cb(session, avctp->transaction, &code, &subunit, operands, operand_count, handler->user_data); avc->code = code; avc->subunit_type = subunit; done: ret = write(sock, buf, packet_size); if (ret != packet_size) goto failed; return TRUE; failed: DBG("AVCTP session %p got disconnected", session); avctp_set_state(session, AVCTP_STATE_DISCONNECTED); return FALSE; }
gboolean socket_lock_input_cb(GIOChannel *source, GIOCondition condition, gpointer data) { gint fd, sock; gchar buf[BUFFER_LENGTH]; struct sockaddr_in caddr; socklen_t caddr_len = sizeof(caddr); GtkWidget *window = data; gboolean popup = FALSE; fd = g_io_channel_unix_get_fd(source); sock = accept(fd, (struct sockaddr *)&caddr, &caddr_len); /* first get the command */ while (socket_fd_gets(sock, buf, sizeof(buf)) != -1) { if (strncmp(buf, "open", 4) == 0) { cl_options.readonly = strncmp(buf+4, "ro", 2) == 0; /* open in readonly? */ while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { gsize buf_len = strlen(buf); /* remove trailing newline */ if (buf_len > 0 && buf[buf_len - 1] == '\n') buf[buf_len - 1] = '\0'; handle_input_filename(buf); } popup = TRUE; } else if (strncmp(buf, "doclist", 7) == 0) { gchar *doc_list = build_document_list(); if (!EMPTY(doc_list)) socket_fd_write_all(sock, doc_list, strlen(doc_list)); /* send ETX (end-of-text) so reader knows to stop reading */ socket_fd_write_all(sock, "\3", 1); g_free(doc_list); } else if (strncmp(buf, "line", 4) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_line = atoi(buf); } } else if (strncmp(buf, "column", 6) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_column = atoi(buf); } } #ifdef G_OS_WIN32 else if (strncmp(buf, "window", 6) == 0) { # if GTK_CHECK_VERSION(3, 0, 0) HWND hwnd = (HWND) gdk_win32_window_get_handle(gtk_widget_get_window(window)); # else HWND hwnd = (HWND) gdk_win32_drawable_get_handle( GDK_DRAWABLE(gtk_widget_get_window(window))); # endif socket_fd_write(sock, (gchar *)&hwnd, sizeof(hwnd)); } #endif } if (popup) { #ifdef GDK_WINDOWING_X11 GdkWindow *x11_window = gtk_widget_get_window(window); /* Set the proper interaction time on the window. This seems necessary to make * gtk_window_present() really bring the main window into the foreground on some * window managers like Gnome's metacity. * Code taken from Gedit. */ # if GTK_CHECK_VERSION(3, 0, 0) if (GDK_IS_X11_WINDOW(x11_window)) # endif { gdk_x11_window_set_user_time(x11_window, gdk_x11_get_server_time(x11_window)); } #endif gtk_window_present(GTK_WINDOW(window)); #ifdef G_OS_WIN32 gdk_window_show(gtk_widget_get_window(window)); #endif } socket_fd_close(sock); return TRUE; }
static gboolean accept_handler(GIOChannel *channel, GIOCondition cond, gpointer user_data) { struct sockaddr_in addr; socklen_t addrlen; int fd, nfd; if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) return FALSE; fd = g_io_channel_unix_get_fd(channel); memset(&addr, 0, sizeof(addr)); addrlen = sizeof(addr); nfd = accept4(fd, (struct sockaddr *) &addr, &addrlen, SOCK_CLOEXEC); if (nfd < 0) return TRUE; if (device_watch > 0) { g_printerr("Closing previous descriptors\n"); g_source_remove(device_watch); device_watch = 0; if (client_watch > 0) { g_source_remove(client_watch); client_watch = 0; } } if (option_ifx == TRUE) { write_file(IFX_RESET_PATH, "1"); sleep(1); write_file(IFX_RESET_PATH, "0"); sleep(1); } device_fd = open_device(option_device); if (device_fd < 0) { close(nfd); return TRUE; } device_watch = create_watch(device_fd, device_handler); if (device_watch == 0) { close(nfd); return TRUE; } client_watch = create_watch(nfd, client_handler); if (client_watch == 0) { g_source_remove(device_watch); device_watch = 0; close(nfd); return TRUE; } client_fd = nfd; return TRUE; }
static gboolean bnep_setup(GIOChannel *chan, GIOCondition cond, gpointer user_data) { struct network_adapter *na = user_data; struct network_server *ns; uint8_t packet[BNEP_MTU]; struct bnep_setup_conn_req *req = (void *) packet; uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED; int n, sk; if (cond & G_IO_NVAL) return FALSE; if (cond & (G_IO_ERR | G_IO_HUP)) { error("Hangup or error on BNEP socket"); return FALSE; } sk = g_io_channel_unix_get_fd(chan); /* Reading BNEP_SETUP_CONNECTION_REQUEST_MSG */ n = read(sk, packet, sizeof(packet)); if (n < 0) { error("read(): %s(%d)", strerror(errno), errno); return FALSE; } /* Highest known Control command ID * is BNEP_FILTER_MULT_ADDR_RSP = 0x06 */ if (req->type == BNEP_CONTROL && req->ctrl > BNEP_FILTER_MULT_ADDR_RSP) { uint8_t pkt[3]; pkt[0] = BNEP_CONTROL; pkt[1] = BNEP_CMD_NOT_UNDERSTOOD; pkt[2] = req->ctrl; send(sk, pkt, sizeof(pkt), 0); return FALSE; } if (req->type != BNEP_CONTROL || req->ctrl != BNEP_SETUP_CONN_REQ) return FALSE; rsp = bnep_setup_decode(req, &dst_role, &src_role); if (rsp) goto reply; rsp = bnep_setup_chk(dst_role, src_role); if (rsp) goto reply; ns = find_server(na->servers, dst_role); if (!ns) { error("Server unavailable: (0x%x)", dst_role); goto reply; } if (!ns->record_id) { error("Service record not available"); goto reply; } if (!ns->bridge) { error("Bridge interface not configured"); goto reply; } if (server_connadd(ns, na->setup, dst_role) < 0) goto reply; na->setup = NULL; rsp = BNEP_SUCCESS; reply: send_bnep_ctrl_rsp(sk, rsp); return FALSE; }
static gboolean moloch_gio_invoke(GIOChannel *source, GIOCondition condition, gpointer data) { MolochWatchFd_t *watch = data; return watch->func(g_io_channel_unix_get_fd(source), condition, watch->data); }
static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data) { char buf[MGMT_BUF_SIZE]; struct mgmt_hdr *hdr = (void *) buf; int sk; ssize_t ret; uint16_t len, opcode; DBG("cond %d", cond); if (cond & G_IO_NVAL) return FALSE; sk = g_io_channel_unix_get_fd(io); if (cond & (G_IO_ERR | G_IO_HUP)) { error("Error on management socket"); return FALSE; } ret = read(sk, buf, sizeof(buf)); if (ret < 0) { error("Unable to read from management socket: %s (%d)", strerror(errno), errno); return TRUE; } DBG("Received %zd bytes from management socket", ret); if (ret < MGMT_HDR_SIZE) { error("Too small Management packet"); return TRUE; } opcode = btohs(bt_get_unaligned(&hdr->opcode)); len = btohs(bt_get_unaligned(&hdr->len)); if (ret != MGMT_HDR_SIZE + len) { error("Packet length mismatch. ret %zd len %u", ret, len); return TRUE; } switch (opcode) { case MGMT_EV_CMD_COMPLETE: mgmt_cmd_complete(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CMD_STATUS: mgmt_cmd_status(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONTROLLER_ERROR: mgmt_controller_error(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_INDEX_ADDED: mgmt_index_added(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_INDEX_REMOVED: mgmt_index_removed(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_POWERED: mgmt_powered(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DISCOVERABLE: mgmt_discoverable(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONNECTABLE: mgmt_connectable(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_PAIRABLE: mgmt_pairable(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_NEW_KEY: mgmt_new_key(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_CONNECTED: mgmt_device_connected(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_DISCONNECTED: mgmt_device_disconnected(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONNECT_FAILED: mgmt_connect_failed(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_PIN_CODE_REQUEST: mgmt_pin_code_request(sk, buf + MGMT_HDR_SIZE, len); break; default: error("Unknown Management opcode %u", opcode); break; } return TRUE; }
gboolean socket_lock_input_cb(GIOChannel *source, GIOCondition condition, gpointer data) { gint fd, sock; gchar buf[BUFFER_LENGTH]; struct sockaddr_in caddr; socklen_t caddr_len = sizeof(caddr); GtkWidget *window = data; gboolean popup = FALSE; fd = g_io_channel_unix_get_fd(source); sock = accept(fd, (struct sockaddr *)&caddr, &caddr_len); /* first get the command */ while (socket_fd_gets(sock, buf, sizeof(buf)) != -1) { if (strncmp(buf, "open", 4) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { handle_input_filename(g_strstrip(buf)); } popup = TRUE; } else if (strncmp(buf, "doclist", 7) == 0) { gchar *doc_list = build_document_list(); if (NZV(doc_list)) socket_fd_write_all(sock, doc_list, strlen(doc_list)); else /* send ETX (end-of-text) in case we have no open files, we must send anything * otherwise the client would hang on reading */ socket_fd_write_all(sock, "\3", 1); g_free(doc_list); } else if (strncmp(buf, "line", 4) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_line = atoi(buf); } } else if (strncmp(buf, "column", 6) == 0) { while (socket_fd_gets(sock, buf, sizeof(buf)) != -1 && *buf != '.') { g_strstrip(buf); /* remove \n char */ /* on any error we get 0 which should be safe enough as fallback */ cl_options.goto_column = atoi(buf); } } #ifdef G_OS_WIN32 else if (strncmp(buf, "window", 6) == 0) { HWND hwnd = (HWND) gdk_win32_drawable_get_handle(GDK_DRAWABLE(window->window)); socket_fd_write(sock, (gchar *)&hwnd, sizeof(hwnd)); } #endif } if (popup) { #ifdef GDK_WINDOWING_X11 /* Set the proper interaction time on the window. This seems necessary to make * gtk_window_present() really bring the main window into the foreground on some * window managers like Gnome's metacity. * Code taken from Gedit. */ gdk_x11_window_set_user_time(window->window, gdk_x11_get_server_time(window->window)); #endif gtk_window_present(GTK_WINDOW(window)); #ifdef G_OS_WIN32 gdk_window_show(window->window); #endif } socket_fd_close(sock); return TRUE; }
static gboolean session_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct avctp *session = data; uint8_t buf[1024], *operands, code, subunit; struct avctp_header *avctp; struct avc_header *avc; int ret, packet_size, operand_count, sock; struct avctp_pdu_handler *handler; if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) goto failed; sock = g_io_channel_unix_get_fd(session->io); ret = read(sock, buf, sizeof(buf)); if (ret <= 0) goto failed; DBG("Got %d bytes of data for AVCTP session %p", ret, session); if ((unsigned int) ret < sizeof(struct avctp_header)) { error("Too small AVCTP packet"); goto failed; } avctp = (struct avctp_header *) buf; DBG("AVCTP transaction %u, packet type %u, C/R %u, IPID %u, " "PID 0x%04X", avctp->transaction, avctp->packet_type, avctp->cr, avctp->ipid, ntohs(avctp->pid)); ret -= sizeof(struct avctp_header); if ((unsigned int) ret < sizeof(struct avc_header)) { error("Too small AVCTP packet"); goto failed; } avc = (struct avc_header *) (buf + sizeof(struct avctp_header)); ret -= sizeof(struct avc_header); operands = buf + sizeof(struct avctp_header) + sizeof(struct avc_header); operand_count = ret; DBG("AV/C %s 0x%01X, subunit_type 0x%02X, subunit_id 0x%01X, " "opcode 0x%02X, %d operands", avctp->cr ? "response" : "command", avc->code, avc->subunit_type, avc->subunit_id, avc->opcode, operand_count); if (avctp->cr == AVCTP_RESPONSE) { handle_response(session, avctp, avc, operands, operand_count); return TRUE; } packet_size = AVCTP_HEADER_LENGTH + AVC_HEADER_LENGTH; avctp->cr = AVCTP_RESPONSE; if (avctp->packet_type != AVCTP_PACKET_SINGLE) { avc->code = AVC_CTYPE_NOT_IMPLEMENTED; goto done; } if (avctp->pid != htons(AV_REMOTE_SVCLASS_ID)) { avctp->ipid = 1; packet_size = AVCTP_HEADER_LENGTH; /* return only AVCTP header*/ goto done; } handler = find_handler(handlers, avc->opcode); if (!handler) { DBG("handler not found for 0x%02x", avc->opcode); packet_size += avrcp_handle_vendor_reject(&code, operands); avc->code = code; goto done; } code = avc->code; subunit = avc->subunit_type; packet_size += handler->cb(session, avctp->transaction, &code, &subunit, operands, operand_count, handler->user_data); avc->code = code; avc->subunit_type = subunit; done: ret = write(sock, buf, packet_size); if (ret != packet_size) goto failed; return TRUE; failed: DBG("AVCTP session %p got disconnected", session); avctp_set_state(session, AVCTP_STATE_DISCONNECTED); return FALSE; }
static int hidp_add_connection(struct input_device *idev) { struct hidp_connadd_req *req; sdp_record_t *rec; char src_addr[18], dst_addr[18]; char filename[PATH_MAX + 1]; GKeyFile *key_file; char handle[11], *str; GError *gerr = NULL; int err; req = g_new0(struct hidp_connadd_req, 1); req->ctrl_sock = g_io_channel_unix_get_fd(idev->ctrl_io); req->intr_sock = g_io_channel_unix_get_fd(idev->intr_io); req->flags = 0; req->idle_to = idle_timeout; ba2str(&idev->src, src_addr); ba2str(&idev->dst, dst_addr); snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", src_addr, dst_addr); filename[PATH_MAX] = '\0'; sprintf(handle, "0x%8.8X", idev->handle); key_file = g_key_file_new(); g_key_file_load_from_file(key_file, filename, 0, NULL); str = g_key_file_get_string(key_file, "ServiceRecords", handle, NULL); g_key_file_free(key_file); if (!str) { error("Rejected connection from unknown device %s", dst_addr); err = -EPERM; goto cleanup; } rec = record_from_string(str); g_free(str); err = extract_hid_record(rec, req); sdp_record_free(rec); if (err < 0) { error("Could not parse HID SDP record: %s (%d)", strerror(-err), -err); goto cleanup; } req->vendor = btd_device_get_vendor(idev->device); req->product = btd_device_get_product(idev->device); req->version = btd_device_get_version(idev->device); if (idev->name) strncpy(req->name, idev->name, sizeof(req->name) - 1); /* Encryption is mandatory for keyboards */ if (req->subclass & 0x40) { if (!bt_io_set(idev->intr_io, &gerr, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_INVALID)) { error("btio: %s", gerr->message); g_error_free(gerr); err = -EFAULT; goto cleanup; } idev->req = req; idev->sec_watch = g_io_add_watch(idev->intr_io, G_IO_OUT, encrypt_notify, idev); return 0; } err = ioctl_connadd(req); cleanup: g_free(req->rd_data); g_free(req); return err; }