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 <[email protected]>:
> Zitat von "hui li" <[email protected]>:
>
>> 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
[email protected]
http://lists.sourceforge.net/lists/listinfo/openobex-users