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

Reply via email to