mwasilak / txThings

CoAP library for Twisted
94 stars 43 forks source link

CoAP blockwise transfer not handled completly ? #5

Closed darkopetrovic closed 8 years ago

darkopetrovic commented 8 years ago

I'm referring to the code below from the processResponse function.

        elif (response.token, response.remote) in self.observations:
            ## @TODO: deduplication based on observe option value, collecting
            # the rest of the resource if blockwise
            callback, args, kw = self.observations[(response.token, response.remote)]
            args = args or ()
            kw = kw or {}
            callback(response, *args, **kw)

Assuming that the client has registered to the server and this latter is doing a notification to inform the client of new values for a resource. After the verification of the remote and the token value, the client finds out that the notification correspond to a resource it has registered to and enter the elif code above. Until now everything is fine.

But then the code do nothing to request the rest of the resource. As I understand it, it is of the responsibility of the user application to request the next block of the resource via the callback registered at the resource registration (the observeCallback parameter of Coap.request).

Note that the resource retrieval works perfectly but only at registration via the processBlock2InResponse method since a request is made at this moment. But thereafter there is no new request made at the reception of a notification which contain the more option.

Is there another way or am I missing something?

mwasilak commented 8 years ago

Observe support in the library is very basic - collecting the rest of the blockwise resource is not yet supported by the code (as the comment implies). I'll look into it this week - maybe it's not a big problem to add it.

darkopetrovic commented 8 years ago

Great thanks!

If that can help, I'm actually using this little hack at the location of interest to create the required request.

        elif (response.token, response.remote) in self.observations:
            ## @TODO: deduplication based on observe option value, collecting
            # the rest of the resource if blockwise
            callback, args, kw = self.observations[(response.token, response.remote)]
            args = args or ()
            kw = kw or {}
            #callback(response, *args, **kw)

            block2 = response.opt.block2
            if block2.more is True and block2.block_number == 0:

                request = Message(code=GET)
                request.opt.uri_path = (kw,)
                request.remote = response.remote
                request = request.generateNextBlock2Request(response)
                requester = Requester(response.protocol, request, None, None, None,
                             None, None, None,
                             None, None, None)

                requester.assembled_response = response
                d = requester.deferred
                d.addCallback( callback )

As you can see I'm using the observeCallbackKeywords parameter to find the URI of the resource the pair (response.token, response.remote) is registered to. I'm sure there is a better way and let you find and decide what is the best way to do that.

I hope this can be fixed.

mwasilak commented 8 years ago

I've uploaded new version of library (0.1.2) with a fix based on your proposal. URI path is saved in self.observations, along with callback. There is a new example file client_observe_block.py which demonstrates blockwise observe operation (with ETH Zurich CoAP test server).

mwasilak commented 8 years ago

There is an obvious bug in the code above which needs to be fixed. If block2 option is not present in the notification the code will fail.

mwasilak commented 8 years ago

Fixed in version 0.1.4 on PyPI.

darkopetrovic commented 8 years ago

thanks :+1:

janaki2 commented 7 years ago

Hi,

I have a question on SZX in the Block2 Option.

Does the payload bytes of the response packet MUST be exactly same as the SZX chosen in Block2 Option or Can it differ with that of SZX?

For example, I send a Block which is NOT the last block and I choose SZX = 2 (i.e., Block size is 64 bytes). But the actual payload in the response is 75 bytes or 57 bytes not 64 bytes. Is this valid?

Thanks!

mwasilak commented 7 years ago

If M bit is not set (last block) the size of the payload can be smaller than SZX in Block2 option. Please refer to RFC: https://tools.ietf.org/html/rfc7959#section-2.4