static void transfer_response(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; gboolean rspcode, final; guint id; g_obex_debug(G_OBEX_DEBUG_TRANSFER, "transfer %u", transfer->id); id = transfer->req_id; transfer->req_id = 0; if (err != NULL) { transfer_complete(transfer, err); return; } rspcode = g_obex_packet_get_operation(rsp, &final); if (rspcode != G_OBEX_RSP_SUCCESS && rspcode != G_OBEX_RSP_CONTINUE) { err = g_error_new(G_OBEX_ERROR, rspcode, "%s", g_obex_strerror(rspcode)); goto failed; } if (transfer->opcode == G_OBEX_OP_GET) { handle_get_body(transfer, rsp, &err); if (err != NULL) goto failed; } if (rspcode == G_OBEX_RSP_SUCCESS) { transfer_complete(transfer, NULL); return; } if (transfer->opcode == G_OBEX_OP_PUT) { req = g_obex_packet_new(transfer->opcode, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(req, put_get_data, transfer); } else if (!g_obex_srm_active(transfer->obex)) { req = g_obex_packet_new(transfer->opcode, TRUE, G_OBEX_HDR_INVALID); } else { /* Keep id since request still outstanting */ transfer->req_id = id; return; } transfer->req_id = g_obex_send_req(obex, req, -1, transfer_response, transfer, &err); failed: if (err != NULL) { g_obex_debug(G_OBEX_DEBUG_ERROR, "%s", err->message); transfer_complete(transfer, err); g_error_free(err); } }
static void transfer_response(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; gboolean rspcode, final; transfer->req_id = 0; if (err != NULL) { transfer_complete(transfer, err); return; } rspcode = g_obex_packet_get_operation(rsp, &final); if (rspcode != G_OBEX_RSP_SUCCESS && rspcode != G_OBEX_RSP_CONTINUE) { err = g_error_new(G_OBEX_ERROR, rspcode, "Transfer failed (0x%02x)", rspcode); goto failed; } if (transfer->opcode == G_OBEX_OP_GET) { handle_get_body(transfer, rsp, &err); if (err != NULL) goto failed; } if (rspcode == G_OBEX_RSP_SUCCESS) { transfer_complete(transfer, NULL); return; } if (transfer->opcode == G_OBEX_OP_PUT) { req = g_obex_packet_new(transfer->opcode, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(req, put_get_data, transfer); } else { req = g_obex_packet_new(transfer->opcode, TRUE, G_OBEX_HDR_INVALID); } transfer->req_id = g_obex_send_req(obex, req, -1, transfer_response, transfer, &err); failed: if (err != NULL) { transfer_complete(transfer, err); g_error_free(err); } }
static gssize put_get_data(void *buf, gsize len, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; GError *err = NULL; gssize ret; ret = transfer->data_producer(buf, len, transfer->user_data); if (ret >= 0) return ret; if (ret == -EAGAIN) return ret; req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_INVALID); transfer->req_id = g_obex_send_req(transfer->obex, req, -1, transfer_abort_response, transfer, &err); if (err != NULL) { transfer_complete(transfer, err); g_error_free(err); } return ret; }
guint g_obex_setpath(GObex *obex, const char *path, GObexResponseFunc func, gpointer user_data, GError **err) { GObexPacket *req; struct setpath_data data; const char *folder; g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id); req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, G_OBEX_HDR_INVALID); memset(&data, 0, sizeof(data)); if (path != NULL && strncmp("..", path, 2) == 0) { data.flags = 0x03; folder = (path[2] == '/') ? &path[3] : NULL; } else { data.flags = 0x02; folder = path; } if (folder != NULL) { GObexHeader *hdr; hdr = g_obex_header_new_unicode(G_OBEX_HDR_NAME, folder); g_obex_packet_add_header(req, hdr); } g_obex_packet_set_data(req, &data, sizeof(data), G_OBEX_DATA_COPY); return g_obex_send_req(obex, req, -1, func, user_data, err); }
static void handle_connect(GObex *obex, GObexPacket *req, gpointer user_data) { GObexPacket *rsp; g_print("connect\n"); rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE, G_OBEX_HDR_INVALID); g_obex_send(obex, rsp, NULL); }
static void get_buf_xfer_progress(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { struct obc_transfer *transfer = user_data; struct transfer_callback *callback = transfer->callback; GObexPacket *req; GObexHeader *hdr; const guint8 *buf; gsize len; guint8 rspcode; gboolean final; if (err != NULL) { get_buf_xfer_complete(obex, err, transfer); return; } rspcode = g_obex_packet_get_operation(rsp, &final); if (rspcode != G_OBEX_RSP_SUCCESS && rspcode != G_OBEX_RSP_CONTINUE) { err = g_error_new(OBEX_IO_ERROR, rspcode, "Transfer failed (0x%02x)", rspcode); get_buf_xfer_complete(obex, err, transfer); g_error_free(err); return; } hdr = g_obex_packet_get_header(rsp, G_OBEX_HDR_APPARAM); if (hdr) { g_obex_header_get_bytes(hdr, &buf, &len); if (len != 0) { transfer->params->data = g_memdup(buf, len); transfer->params->size = len; } } hdr = g_obex_packet_get_body(rsp); if (hdr) { g_obex_header_get_bytes(hdr, &buf, &len); if (len != 0) obc_transfer_read(transfer, buf, len); } if (rspcode == G_OBEX_RSP_SUCCESS) { get_buf_xfer_complete(obex, err, transfer); return; } req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_INVALID); transfer->xfer = g_obex_send_req(obex, req, -1, get_buf_xfer_progress, transfer, &err); if (callback) callback->func(transfer, transfer->transferred, err, callback->data); }
static void test_pkt(void) { GObexPacket *pkt; pkt = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_INVALID); g_assert(pkt != NULL); g_obex_packet_free(pkt); }
guint g_obex_delete(GObex *obex, const char *name, GObexResponseFunc func, gpointer user_data, GError **err) { GObexPacket *req; g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id); req = g_obex_packet_new(G_OBEX_OP_PUT, TRUE, G_OBEX_HDR_NAME, name, G_OBEX_HDR_INVALID); return g_obex_send_req(obex, req, -1, func, user_data, err); }
static gssize put_get_data(void *buf, gsize len, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *req; GError *err = NULL; gssize ret; ret = transfer->data_producer(buf, len, transfer->user_data); if (ret == 0 || ret == -EAGAIN) return ret; if (ret > 0) { /* Check if SRM is active */ if (!g_obex_srm_active(transfer->obex)) return ret; /* Generate next packet */ req = g_obex_packet_new(transfer->opcode, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(req, put_get_data, transfer); transfer->req_id = g_obex_send_req(transfer->obex, req, -1, transfer_response, transfer, &err); goto done; } req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_INVALID); transfer->req_id = g_obex_send_req(transfer->obex, req, -1, transfer_abort_response, transfer, &err); done: if (err != NULL) { transfer_complete(transfer, err); g_error_free(err); } return ret; }
static void transfer_abort_req(GObex *obex, GObexPacket *req, gpointer user_data) { struct transfer *transfer = user_data; GObexPacket *rsp; GError *err; err = g_error_new(G_OBEX_ERROR, G_OBEX_ERROR_CANCELLED, "Request was aborted"); rsp = g_obex_packet_new(G_OBEX_RSP_SUCCESS, TRUE, G_OBEX_HDR_INVALID); g_obex_send(obex, rsp, NULL); transfer_complete(transfer, err); g_error_free(err); }
static void test_encode_on_demand_fail(void) { GObexPacket *pkt; uint8_t buf[255]; gssize len; pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(pkt, get_body_data_fail, NULL); len = g_obex_packet_encode(pkt, buf, sizeof(buf)); g_assert_cmpint(len, ==, -EIO); g_obex_packet_free(pkt); }
guint g_obex_mkdir(GObex *obex, const char *path, GObexResponseFunc func, gpointer user_data, GError **err) { GObexPacket *req; struct setpath_data data; g_obex_debug(G_OBEX_DEBUG_COMMAND, "conn %u", obex->conn_id); req = g_obex_packet_new(G_OBEX_OP_SETPATH, TRUE, G_OBEX_HDR_NAME, path, G_OBEX_HDR_INVALID); memset(&data, 0, sizeof(data)); g_obex_packet_set_data(req, &data, sizeof(data), G_OBEX_DATA_COPY); return g_obex_send_req(obex, req, -1, func, user_data, err); }
gboolean g_obex_pending_req_abort(GObex *obex, GError **err) { struct pending_pkt *p = obex->pending_req; GObexPacket *req; if (p->cancelled) return TRUE; p->cancelled = TRUE; g_source_remove(p->timeout_id); p->timeout = G_OBEX_ABORT_TIMEOUT; p->timeout_id = g_timeout_add_seconds(p->timeout, req_timeout, obex); req = g_obex_packet_new(G_OBEX_OP_ABORT, TRUE, G_OBEX_HDR_INVALID); return g_obex_send(obex, req, err); }
static void test_encode_on_demand(void) { GObexPacket *pkt; uint8_t buf[255]; gssize len; pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_INVALID); g_obex_packet_add_body(pkt, get_body_data, NULL); len = g_obex_packet_encode(pkt, buf, sizeof(buf)); if (len < 0) { g_printerr("Encoding failed: %s\n", g_strerror(-len)); g_assert_not_reached(); } assert_memequal(pkt_put_body, sizeof(pkt_put_body), buf, len); g_obex_packet_free(pkt); }
static void test_create_args(void) { GObexPacket *pkt; guint8 buf[255], body[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; gssize len; pkt = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_CONNECTION, 0x01020304, G_OBEX_HDR_TYPE, "foo/bar", strlen("foo/bar") + 1, G_OBEX_HDR_NAME, "file.txt", G_OBEX_HDR_ACTION, 0xab, G_OBEX_HDR_BODY, body, sizeof(body), G_OBEX_HDR_INVALID); g_assert(pkt != NULL); len = g_obex_packet_encode(pkt, buf, sizeof(buf)); g_assert(len > 0); assert_memequal(pkt_put_long, sizeof(pkt_put_long), buf, len); g_obex_packet_free(pkt); }
int obc_transfer_put(struct obc_transfer *transfer, transfer_callback_t func, void *user_data) { struct obc_session *session = transfer->session; GError *err = NULL; GObex *obex; GObexPacket *req; GObexDataProducer data_cb; struct stat st; int fd; if (transfer->xfer != 0) return -EALREADY; if (transfer->buffer) { data_cb = put_buf_xfer_progress; goto done; } fd = open(transfer->filename, O_RDONLY); if (fd < 0) { error("open(): %s(%d)", strerror(errno), errno); return -errno; } if (fstat(fd, &st) < 0) { close(fd); error("fstat(): %s(%d)", strerror(errno), errno); return -errno; } transfer->fd = fd; transfer->size = st.st_size; data_cb = put_xfer_progress; done: obex = obc_session_get_obex(session); req = g_obex_packet_new(G_OBEX_OP_PUT, FALSE, G_OBEX_HDR_INVALID); if (transfer->name != NULL) g_obex_packet_add_unicode(req, G_OBEX_HDR_NAME, transfer->name); if (transfer->type != NULL) g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, transfer->type, strlen(transfer->type) + 1); if (transfer->size < UINT32_MAX) g_obex_packet_add_uint32(req, G_OBEX_HDR_LENGTH, transfer->size); if (transfer->params != NULL) g_obex_packet_add_bytes(req, G_OBEX_HDR_APPARAM, transfer->params->data, transfer->params->size); transfer->xfer = g_obex_put_req_pkt(obex, req, data_cb, xfer_complete, transfer, &err); if (transfer->xfer == 0) return -ENOTCONN; if (func) obc_transfer_set_callback(transfer, func, user_data); return 0; }
int obc_transfer_get(struct obc_transfer *transfer, transfer_callback_t func, void *user_data) { struct obc_session *session = transfer->session; GError *err = NULL; GObex *obex; GObexPacket *req; GObexDataConsumer data_cb; GObexFunc complete_cb; GObexResponseFunc rsp_cb = NULL; if (transfer->xfer != 0) return -EALREADY; if (transfer->type != NULL && (strncmp(transfer->type, "x-obex/", 7) == 0 || strncmp(transfer->type, "x-bt/", 5) == 0)) { rsp_cb = get_buf_xfer_progress; } else { int fd = open(transfer->name ? : transfer->filename, O_WRONLY | O_CREAT, 0600); if (fd < 0) { error("open(): %s(%d)", strerror(errno), errno); return -errno; } transfer->fd = fd; data_cb = get_xfer_progress; complete_cb = xfer_complete; } obex = obc_session_get_obex(session); req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_INVALID); if (transfer->filename != NULL) g_obex_packet_add_unicode(req, G_OBEX_HDR_NAME, transfer->filename); if (transfer->type != NULL) g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, transfer->type, strlen(transfer->type) + 1); if (transfer->params != NULL) g_obex_packet_add_bytes(req, G_OBEX_HDR_APPARAM, transfer->params->data, transfer->params->size); if (rsp_cb) transfer->xfer = g_obex_send_req(obex, req, -1, rsp_cb, transfer, &err); else transfer->xfer = g_obex_get_req_pkt(obex, req, data_cb, complete_cb, transfer, &err); if (transfer->xfer == 0) return -ENOTCONN; if (func) obc_transfer_set_callback(transfer, func, user_data); return 0; }