Currently when openobex calls obex_data_indication() to read socket data, it first calls obex_transport_read() to read first 3 data to decide message length, then calls obex_transport_read() again to read remaining data. But when we run obex over l2cap, you can find the second obex_transport_read() return zero. The log is below: ----------------------------------------------------------------------------------------- io callback OBEX_HandleInput(): obex_transport_standard_handle_input(): obex_transport_standard_handle_input(): Data available on client socket obex_data_indication(): obex_transport_read(): Request to read max 3 bytes obex_data_indication(): Got 3 bytes obex_transport_read(): Request to read max 23 bytes obex_data_indication(): Got 0 bytes msg len=3 obex_data_indication(): Need more data, size=26, len=3! io callback server session closed closing connection --------------------------------------------------------------------------------------------- You can find the reason why the second read socket return 0 in kernel/ net /Bluetooth/l2cap.c and kernel/ net /Bluetooth/ af_bluetooth.c files.
l2cap_sock_recvmsg()---> bt_sock_recvmsg()--->skb_recv_datagram() ,skb_free_datagram() So the datagram is free after first read. So when use obex over l2cap, we need to call obex_transport_read() once to receive all the message data. Maybe we can modify obex_data_indication() like below: #define MAX_BUFF_SIZE 32767 int obex_data_indication(obex_t *self) { obex_common_hdr_t *hdr; buf_t *msg; int final; int actual = 0; unsigned int size; int ret; DEBUG(4, "\n"); obex_return_val_if_fail(self != NULL, -1); msg = self->rx_msg; /*need to konw RFCOMM socket or L2CAP socket*/ if(obex_over_l2cap){ actual = obex_transport_read(self, MAX_BUFF_SIZE); DEBUG(4, "Got %d bytes\n", actual); if (actual < 0) { obex_deliver_event(self, OBEX_EV_LINKERR, 0, 0, TRUE); return actual; } if(actual<sizeof(*hdr)) { /* Wait until we have at least 3 bytes data */ DEBUG(3, "Need at least 3 bytes got only %lu!\n", actual); return actual; } hdr = (obex_common_hdr_t *) msg->data; size = ntohs(hdr->len); } else{ /* First we need 3 bytes to be able to know how much data to read */ if(msg->data_size < sizeof(*hdr)) { actual = obex_transport_read(self, sizeof(*hdr)-msg->data_size); DEBUG(4, "Got %d bytes\n", actual); /* Check if we are still connected */ /* do not error if the data is from non-empty but * partial buffer (custom transport) */ if (actual < 0) { obex_deliver_event(self, OBEX_EV_LINKERR, 0, 0, TRUE); return actual; } } /* If we have 3 bytes data we can decide how big the packet is */ if(msg->data_size >= sizeof(*hdr)) { hdr = (obex_common_hdr_t *) msg->data; size = ntohs(hdr->len); actual = 0; if(msg->data_size < (int) ntohs(hdr->len)) { actual = obex_transport_read(self, size - msg->data_size); /* hdr might not be valid anymore if the _read * did a realloc */ hdr = (obex_common_hdr_t *) msg->data; /* Check if we are still connected */ /* do not error if the data is from non-empty * but partial buffer (custom transport) */ if (actual < 0) { obex_deliver_event(self, OBEX_EV_LINKERR, 0, 0, TRUE); return actual; } } } else { /* Wait until we have at least 3 bytes data */ DEBUG(3, "Need at least 3 bytes got only %lu!\n", (unsigned long) msg->data_size); return actual; } } /* New data has been inserted at the end of message */ DEBUG(1, "Got %d bytes msg len=%lu\n", actual, (unsigned long) msg->data_size); /* * Make sure that the buffer we have, actually has the specified * number of bytes. If not the frame may have been fragmented, and * we will then need to read more from the socket. */ /* Make sure we have a whole packet */ if (size > msg->data_size) { DEBUG(3, "Need more data, size=%d, len=%lu!\n", size, (unsigned long)msg->data_size); /* I'll be back! */ return msg->data_size; } DUMPBUFFER(2, "Rx", msg); actual = msg->data_size; final = hdr->opcode & OBEX_FINAL; /* Extract final bit */ /* Dispatch to the mode we are in */ if(self->mode == MODE_SRV) ret = obex_server(self, msg, final); else ret = obex_client(self, msg, final); buf_reuse(msg); /* Check parse errors */ if(ret < 0) actual = ret; return actual; } 2010/11/9 Hendrik Sattler <p...@hendrik-sattler.de>: > Zitat von "hui li" <nami.li1...@gmail.com>: > >> OBEX_MT_SEQPACKET and OBEX_MT_STREAM indicate different socket types >> ,corresponding to SOCK_SEQPACKET and SOCK_STREAM. If obex is over >> l2cap, we may would like to use SOCK_SEQPACKET type and >> obex_data_indication() function may need to how to parse incoming >> data. > > Actually not. The transport reads data from somewhere. How that is done is > completely up to the transport. Note that you based that patch on 8 month > old code and much happened since then. > Also note that the transport's read() function can return more bytes than > requested, e.g. USB support always does that (it always reads a full packet) > and custom transports always did. This is not a problem. > > Where exactly is OBEX-over-L2CAP-without-RFCOMM specified? The bluetooth > specs that I've seen so far always said that OBEX is bound to RFCOMM. > > HS > > > ------------------------------------------------------------------------------ Centralized Desktop Delivery: Dell and VMware Reference Architecture Simplifying enterprise desktop deployment and management using Dell EqualLogic storage and VMware View: A highly scalable, end-to-end client virtualization framework. Read more! http://p.sf.net/sfu/dell-eql-dev2dev _______________________________________________ Openobex-users mailing list Openobex-users@lists.sourceforge.net http://lists.sourceforge.net/lists/listinfo/openobex-users