chrysn / aiocoap

The Python CoAP library
Other
266 stars 120 forks source link

Answer Request Entity Incomplete while sending Request GET Block #1 #362

Closed JulienPnt closed 2 months ago

JulienPnt commented 2 months ago

Hi,

I designed a CoAP to CoAP proxy using aiocoap. The proxy's purpose was to test the reliability of my CoAP client and server during blockwise transfers. To create the specific awkward cases I needed, I had to remove the automatic blockwise handle from aicoap.

I set the blockwise_handle parameter to False in the request function and I received a 408 error. To bypass this issue, I had to comment some lines into the Block2Cache class.

Observed Behavior

When sending GET Block#1 , the proxy returns the error 4.08 which stands for Request Entity Incomplete. See WireShark capture below: RequestEntityIncomplete.csv

Steps to Reproduce

  1. Send a request requiring blockwise transfer from your client to your proxy
  2. Transfer the request from the proxy to the server by setting the block_handle parameter to False
  3. Send the request GET #Block1
  4. Get 408 error

Expected Behavior

The proxy should properly handle the blockwise transfer request and return the appropriate block of data without errors.

According to RFC 7959 about the BlockWiseTransfer chapter 2.9.2, the 408 error is raised to indicate:

The client has not sent all blocks, not sent them in the order required by the server, or has sent them long enough ago that the server has already discarded them.

Upon checking the Wireshark capture, it was observed that my client never sent the GET Block#0 request before requesting Block#1. This occurs because my client cannot know beforehand that the response will require handling a blockwise transfer.

As it is shown on the figure 2 from the chapter 3.2 in the RFC 7959.

   CLIENT                                                     SERVER
     |                                                            |
     | CON [MID=1234], GET, /status                       ------> |
     |                                                            |
     | <------   ACK [MID=1234], 2.05 Content, 2:0/1/128          |
     |                                                            |
     | CON [MID=1235], GET, /status, 2:1/0/128            ------> |
     |                                                            |
     | <------   ACK [MID=1235], 2.05 Content, 2:1/1/128          |
     |                                                            |
     | CON [MID=1236], GET, /status, 2:2/0/128            ------> |
     |                                                            |
     | <------   ACK [MID=1236], 2.05 Content, 2:2/0/128          |

Conclusion

To bypass this issue, I had to comment the line from 120 to 128 in blockwise.py. The issue seems to be related to the cache management.

Environment

Python version: 3.12.4 (main, Jun  7 2024, 06:33:07) [GCC 14.1.1 20240522]
aiocoap version: 0.4.11
Modules missing for subsystems:
    dtls: missing DTLSSocket
    oscore: missing cbor2, cryptography, filelock, ge25519, lakers-python
    linkheader: everything there
    prettyprint: missing cbor2, pygments, cbor-diag
    ws: missing websockets
Python platform: linux
Default server transports:  tcpserver:tcpclient:tlsserver:tlsclient:udp6
Selected server transports: tcpserver:tcpclient:tlsserver:tlsclient:udp6
Default client transports:  tcpclient:tlsclient:udp6
Selected client transports: tcpclient:tlsclient:udp6
SO_REUSEPORT available (default, selected): True, True
JulienPnt commented 2 months ago

By writing the issue, I realized it was a false alarm. The server in my proxy is working as expected. The error occurs because it does not have the requested block from my client at the moment the client asks for it.

Sorry, yet could you advise me some tools to better test the reliability of CoAP client please. Because aicoap handles in background to much actions while I'm trying to create awkward situation.