/* * Function send_body(object, header, txmsg, tx_left) * * Fragment and send the body * */ static int send_body(obex_object_t *object, struct obex_header_element *h, buf_t *txmsg, unsigned int tx_left) { struct obex_byte_stream_hdr *body_txh; unsigned int actual; body_txh = (struct obex_byte_stream_hdr*) buf_reserve_end(txmsg, sizeof(struct obex_byte_stream_hdr)); if (!h->body_touched) { /* This is the first time we try to send this header obex_object_addheaders has added a struct_byte_stream_hdr before the actual body-data. We shall send this in every fragment so we just remove it for now.*/ buf_remove_begin(h->buf, sizeof(struct obex_byte_stream_hdr) ); h->body_touched = TRUE; } if (tx_left < ( h->buf->data_size + sizeof(struct obex_byte_stream_hdr) ) ) { DEBUG(4, "Add BODY header\n"); body_txh->hi = OBEX_HDR_BODY; body_txh->hl = htons((uint16_t)tx_left); buf_insert_end(txmsg, h->buf->data, tx_left - sizeof(struct obex_byte_stream_hdr) ); buf_remove_begin(h->buf, tx_left - sizeof(struct obex_byte_stream_hdr) ); /* We have completely filled the tx-buffer */ actual = tx_left; } else { DEBUG(4, "Add BODY_END header\n"); body_txh->hi = OBEX_HDR_BODY_END; body_txh->hl = htons((uint16_t) (h->buf->data_size + sizeof(struct obex_byte_stream_hdr))); buf_insert_end(txmsg, h->buf->data, h->buf->data_size); actual = h->buf->data_size; object->tx_headerq = slist_remove(object->tx_headerq, h); buf_free(h->buf); free(h); } return actual; }
/* * does fragmented write */ static int do_write(int fd, buf_t *msg, unsigned int mtu, ssize_t (*write_func)(int, const void *, size_t)) { int actual = -1; int size; /* Send and fragment if necessary */ while (msg->data_size) { if (msg->data_size > mtu) size = mtu; else size = msg->data_size; DEBUG(1, "sending %d bytes\n", size); actual = write_func(fd, msg->data, size); if (actual <= 0) return actual; /* Hide sent data */ buf_remove_begin(msg, actual); } return actual; }
static int obex_verify_seq(obex_t *self, uint8_t seq) { int retval, actual_length = 0, count = 0; char * buffer; buffer = buf_reserve_end(self->rx_msg, self->mtu_rx); do { retval = libusb_bulk_transfer(self->usb_dev, self->read_endpoint_address, buffer, self->mtu_rx, &actual_length, 1245); if (retval < 0) break; count++; } while (count < 100 && actual_length == 0); buf_remove_end(self->rx_msg, self->mtu_rx - actual_length); if (retval < 0 || actual_length == 0) { DEBUG(self, 4, "Error reading seq number (%d)\n", retval); return 0; } if ((uint8_t)buffer[0] != seq) { DEBUG(self, 4, "Sequence mismatch %u != %u\n", (uint8_t)buffer[0], seq); return 0; } buf_remove_begin(self->rx_msg, 1); return 1; }
/* * Function obex_object_receive() * * Add any incoming headers to headerqueue. * */ int obex_object_receive(obex_t *self, buf_t *msg) { obex_object_t *object; struct obex_header_element *element; uint8_t *source = NULL; unsigned int len, hlen; uint8_t hi; int err = 0; union { struct obex_unicode_hdr *unicode; struct obex_byte_stream_hdr *bstream; struct obex_uint_hdr *uint; } h; DEBUG(4, "\n"); object = self->object; /* Remove command from buffer */ buf_remove_begin(msg, sizeof(struct obex_common_hdr)); /* Copy any non-header data (like in CONNECT and SETPATH) */ if (object->headeroffset) { object->rx_nonhdr_data = buf_new(object->headeroffset); if (!object->rx_nonhdr_data) return -1; buf_insert_end(object->rx_nonhdr_data, msg->data, object->headeroffset); DEBUG(4, "Command has %d bytes non-headerdata\n", object->rx_nonhdr_data->data_size); buf_remove_begin(msg, object->headeroffset); object->headeroffset = 0; } while ((msg->data_size > 0) && (!err)) { hi = msg->data[0]; DEBUG(4, "Header: %02x\n", hi); switch (hi & OBEX_HI_MASK) { case OBEX_UNICODE: h.unicode = (struct obex_unicode_hdr *) msg->data; source = &msg->data[3]; hlen = ntohs(h.unicode->hl); len = hlen - 3; break; case OBEX_BYTE_STREAM: h.bstream = (struct obex_byte_stream_hdr *) msg->data; source = &msg->data[3]; hlen = ntohs(h.bstream->hl); len = hlen - 3; if (hi == OBEX_HDR_BODY || hi == OBEX_HDR_BODY_END) { /* The body-header need special treatment */ if (object->s_srv) obex_object_receive_stream(self, hi, source, len); else { if (obex_object_receive_body(object, msg, hi, source, len) < 0) err = -1; } /* We have already handled this data! */ source = NULL; } break; case OBEX_BYTE: source = &msg->data[1]; len = 1; hlen = 2; break; case OBEX_INT: source = &msg->data[1]; len = 4; hlen = 5; break; default: DEBUG(1, "Badly formed header received\n"); source = NULL; hlen = 0; len = 0; err = -1; break; } /* Make sure that the msg is big enough for header */ if (len > msg->data_size) { DEBUG(1, "Header %d to big. HSize=%d Buffer=%d\n", hi, len, msg->data_size); source = NULL; err = -1; } if (source) { /* The length MAY be useful when receiving body. */ if (hi == OBEX_HDR_LENGTH) { h.uint = (struct obex_uint_hdr *) msg->data; object->hinted_body_len = ntohl(h.uint->hv); DEBUG(4, "Hinted body len is %d\n", object->hinted_body_len); } if ( (element = malloc(sizeof(struct obex_header_element)) ) ) { memset(element, 0, sizeof(struct obex_header_element)); element->length = len; element->hi = hi; /* If we get an emtpy we have to deal with it... * This might not be an optimal way, but it works. */ if (len == 0) { DEBUG(4, "Got empty header. Allocating dummy buffer anyway\n"); element->buf = buf_new(1); } else { element->buf = buf_new(len); if (element->buf) { DEBUG(4, "Copying %d bytes\n", len); buf_insert_end(element->buf, source, len); } } if (element->buf) { /* Add element to rx-list */ object->rx_headerq = slist_append(object->rx_headerq, element); } else{ DEBUG(1, "Cannot allocate memory\n"); free(element); err = -1; } } else { DEBUG(1, "Cannot allocate memory\n"); err = -1; } } if (err) return err; DEBUG(4, "Pulling %d bytes\n", hlen); buf_remove_begin(msg, hlen); } return 1; }