obgm / libcoap

A CoAP (RFC 7252) implementation in C

Repository from Github https://github.comobgm/libcoapRepository from Github https://github.comobgm/libcoap

Examples: coap_client fails on second run

Laczen opened this issue · comments

I am very new to libcoap. I'm trying to use it in NuttX on a esp32. I have been able to get it running in a notls config (libcoap 4.3.4).

When I do a first call to coap_client I am getting the correct response. However if I run the same command again coap_client fails. It seems to be stuck in the optlist sorting.

Could this be a result of a bad init of the optlist ?

@Laczen Good that you are getting to try out libcoap.

It is unclear how you are invoking coap_client. What are you using as the source for coap_client?

@Laczen Good that you are getting to try out libcoap.

It is unclear how you are invoking coap_client. What are you using as the source for coap_client?

Thanks for the quick reply.

coap_client is invoked as: coap_client -a fe80::ff:fe00:feff -m get coap://[fe80::ff:fe00:a]/time

I am using coap_server as the source.

I think the problem is caused by *optlist being a static and that coap_client is not cleaning up the optlist properly. If I set optlist = NULL at the start of main I can get it to work a second time, but it seems to add a new entry into optlist resulting in a loop of sending the same request.

examples/coap-client.c source file frees off the optlist structure at the end of main(), but does not reset it to NULL.

I suspect that this is your issue here if the executable code is left in memory and you are calling main() from some outer loop.

It is worth noting that there are several other static variables thet get free'd off, but the pointers / counts are not reset.

@mrdeep1 Thanks for the reply.

I am new to coap, after some changes I have been able to get the optlist sorting corrected.

However I can't repeat the command line to get a good response, it seems that the token from the second reply is considered incorrect. I have tried adding a coap_session_disconnected but this didn't solve the problem. Is it required to pass a token at the command line to "reconnect" to the server session ?

There are too many unknowns here to be able to just answer.

Certainly for the same 5-tuple of (src-ip, src-port, dst-ip,dst-port, ip-proto), each new request should have a different token. With the standard examples libcoap client (which is named coap-client, not coap_client) when it is executed the second time the 5-tuple is likely to be different (src-port).

It would be good to see the debug log for the second request/reply (-v7 option for coap-client or coap_set_log_level(COAP_LOG_DEBUG) in your code) to have a better understanding of what is going on here.

@mrdeep1 coap_client is the same as coap-client, it is just compiled as coap_client. The debug log is:

nsh> coap_client -v 7 -m get coap://[fe80::ff:fe00:a]/time
Jan 01 00:00:32.390 WARN coap_socket_connect_udp: setsockopt IPV6_V6ONLY: Unknown error 38
Jan 01 00:00:32.400 DEBG ***[::]:5738 <-> [fe80::ff:fe00:a]:5738 UDP : session 0x3ffddd00: created outgoing session
Jan 01 00:00:32.400 DEBG ***[::]:5738 <-> [fe80::ff:fe00:a]:5738 UDP : session connected
Jan 01 00:00:32.400 DEBG timeout is set to 90 seconds
Jan 01 00:00:32.400 DEBG sending CoAP request:
Jan 01 00:00:32.400 DEBG *  [::]:5738 <-> [fe80::ff:fe00:a]:5738 UDP : netif: sent   17 bytes
v:1 t:CON c:GET i:9fab {01} [ Uri-Path:time, Request-Tag:0x2e1bec13 ]
Jan 01 00:00:32.410 DEBG ** [::]:5738 <-> [fe80::ff:fe00:a]:5738UDP packet processed 0 UDP : mid=0x9fab: added to retransmit queue (2313ms)

Jan 01 00:00:32.430 DEBG *  [::]:5738 <-> [fe80::ff:fe00:a]:5738 UDP : netif: recv   24 bytes
v:1 t:ACK c:2.05 i:9fab {01} [ Content-Format:text/plain, Max-Age:1 ] :: 'Jan 01 02:31:08'
Jan 01 00:00:32.440 DEBG ** [::]:5738 <-> [fe80::ff:fe00:a]:5738 UDP : mid=0x9fab: removed (1)
Jan 01 00:00:32.460 DEBG ** process incoming 2.05 response:
Jan 01 00:00:32.460 DEBG show pdu ? NOJan 01 02:31:08Jan 01 00:00:32.470 DEBG delete pduJan 01 00:00:32.470 DEBG delete pdu tokenJan 01 00:00:32.470 DEBG coap pduJan 01 00:00:32.480 DEBG delete pduJan 01 00:00:32.480 DEBG delete pdu tokenJan 01 00:00:32.480 DEBG coap pduJan 01 00:00:32.480 DEBG ***[::]:5738 <-> [fe80::ff:fe00:a]:5738 UDP : session 0x3ffddd00: closed

nsh> coap_client -v 7 -m get coap://[fe80::ff:fe00:a]/time
Jan 01 00:01:09.480 WARN coap_socket_connect_udp: setsockopt IPV6_V6ONLY: Unknown error 38
Jan 01 00:01:09.490 DEBG ***[::]:5739 <-> [fe80::ff:fe00:a]:5739 UDP : session 0x3ffddd00: created outgoing session
Jan 01 00:01:09.490 DEBG ***[::]:5739 <-> [fe80::ff:fe00:a]:5739 UDP : session connected
Jan 01 00:01:09.490 DEBG timeout is set to 90 seconds
Jan 01 00:01:09.490 DEBG sending CoAP request:
Jan 01 00:01:09.490 DEBG *  [::]:5739 <-> [fe80::ff:fe00:a]:5739 UDP : netif: sent   17 bytes
v:1 t:CON c:GET i:aeed {02} [ Uri-Path:time, Request-Tag:0x313f86ca ]
Jan 01 00:01:09.500 DEBG ** [::]:5739 <-> [fe80::ff:fe00:a]:5739UDP packet processed 0 UDP : mid=0xaeed: added to retransmit queue (2250ms)

Jan 01 00:01:09.530 DEBG *  [::]:5739 <-> [fe80::ff:fe00:a]:5739 UDP : netif: recv   24 bytes
v:1 t:ACK c:2.05 i:aeed {02} [ Content-Format:text/plain, Max-Age:1 ] :: 'Jan 01 02:31:45'
Jan 01 00:01:09.540 DEBG ** [::]:5739 <-> [fe80::ff:fe00:a]:5739 UDP : mid=0xaeed: removed (1)
Jan 01 00:01:09.550 DEBG ** process incoming 2.05 response:
Jan 01 00:01:09.550 DEBG show pdu ? NObad token
Jan 01 00:01:09.560 DEBG delete pduJan 01 00:01:09.560 DEBG delete pdu tokenJan 01 00:01:09.560 DEBG coap pduJan 01 00:01:09.560 DEBG delete pduJan 01 00:01:09.570 DEBG delete pdu tokenJan 01 00:01:09.570 DEBG coap pdu

There are 2 extra debugging data that are added from my side : UDP packet processed (from ip handling) and bad token (inserted in coap_client code when !track_check_token(&token)). As can be seen the data is received ok, it is just considered invalid data.

As a note, when adding your own debug statements, they should be terminated with \n.

The setsockopt IPV6_V6ONLY: Unknown error 38 is down to NuttX not supporting this option - it is not an issue and is otherwise ignored.

The clue here is that the token in the first request is {01} and the second {02}. In the same way that you had optlist issues, you are now having issues with tracked_tokens.

In the section of code in examples/coap-client.c that comes after the finish: statement, you need to reset all the initial static variables back to their initial defined state having freed off the relevant data as you are calling the main() function multiple times from the wrapper code.

So, in this specific case, tracked_tokens_count = 0; and tracked_tokens = NULL; need to be added in after free(tracked_tokens); is called off. You will need to do all the static variables.

@mrdeep1 thanks, I was missing tracked_tokens = NULL.

When adding the following items at the end of main I can now succesfully run coap-(_)client multiple times:

  tracked_tokens = NULL;
  tracked_tokens_count = 0;

  optlist = NULL;

  repeat_count = 1;
  ready = 0;

Thanks again.

Thanks for confirming. Please feel free to close this issue.