libcoap
libcoap copied to clipboard
coap create client session with lwip
Hi @obgm I find coap server example with lwip in examples/lwip/.
I want to create coap client with lwip. but I found if I use coap_new_client_session to create client session. coap_endpoint will not create.
I also found in coap_recv ==>coap_endpoint_get_session, this function can bind endpoint to session,but is COAP_SESSION_TYPE_SERVER.
so is there any function to bind endpoint to session in LWIP? Thanks
@frankielii The coap_endpoint_t is there for a listening endpoint and so is used for a CoAP Server. When a new connection comes into the server, a coap_session_t is created to handle the ongoing traffic interchange. For CoAP Clients, a coap_session_t is immediately created, bypassing the coap_endpoint_t logic. In both cases (coap_endpoint_t and coap_session_t) are associated with a coap_context_t
So, for CoAP clients you do a coap_new_context()
followed by a coap_new_client_session()
which will 'establish' a session with the target server and then traffic is sent over this session. The manual pages for coap_session(3) and coap_handler(3) are a good starting point for this https://libcoap.net/doc/reference/4.2.0/manpage.html .
https://github.com/obgm/libcoap-minimal/blob/master/client.cc gives you minimal outline of code as a starting point.
Thanks @obgm. I test https://github.com/obgm/libcoap-minimal/blob/master/client.cc before, but I found when use coap_new_client_session( ) to create session ,it will fail because coap_session_create_client( )==> coap_session_create_client( ) ==>coap_socket_connect_udp( ) ==0,
actually, UDP sock.pcb registered in coap_new_endpoint WITH LWIP
@frankielii It looks like when libcoap was re-factored some time back to better handle networking that this part of LwIP support was overlooked and needs to be fixed.
Thanks a lot @mrdeep1. so is there any contributor plan to fix this issue?
If I get a chance, I will look at this.
Thanks again @mrdeep1
@mrdeep1 did you finally get a chance to look at this? @frankielii how did you solve the issue?
It seems I'm currently running into the same thing...
@bahm-lgs I have got something that works here as a LwIP client, but the code needs to be tidied up before a PR is created. I will be back in the office next week when I can do this tidying up.
Thanks @mrdeep1, that sounds great, because I could not manage to get the code work as a client. For some reason no packets are sent out by LwIP. It worked for a server though.
libcoap LwIP support has been re-written in PR https://github.com/obgm/libcoap/pull/884, which has full coap-client support. @bahm-lgs Please try it out and feedback welcome..
libcoap LwIP support has been re-written in PR #884, which has full coap-client support. @bahm-lgs Please try it out and feedback welcome..
@mrdeep1 Thanks a lot, I will give it a try. This might take a few days since I will have some work adapting it to my build (using it on Zynq7000 in Xilinx Vitis environment). Just to make sure, is the code expected to also work with LwIP in NO_SYS=1 mode? Since I'm running it without threads in a standalone application...
@bahm-lgs The challenge here is that I am making use of "#define LWIP_SOCKET 1
" so that the socket()
, accept()
etc. calls function with no change. At present, lwip/src/core/init.c
has
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
#endif
which means that I cannot use "#define LWIP_SOCKET 1
" with "#define NO_SYS 0
".
The LwIP documentation for NO_SYS ==0 stats that sockets are not supported.
So, it looks like this PR will not help you unless there is a way of making everything single threaded. I'm open to suggestions here.
Yep, without OS there are no threads and without threads there are no sockets. However, the current libcoap code worked without sockets as server, so I still hope I can somehow make this work for client-mode as well. @mrdeep1 I will let you know, if I make some progress with this.
This week I had some time looking again into the libcoap client for LwIP with NO_SYS=1 and made some progress. The code was mainly just missing some essential stuff in coap_socket_connect_udp(). @mrdeep1 I will clean it up next week so you can have a look... or do you have already planned dropping support for NO_SYS=1 completely?
At the moment, I am not convinced that dropping NO_SYS=1 completely is the right way to go, so am interested at looking at your work.
@mrdeep1 I forked the repo and cleaned up my changes. Please have a look at this commit: https://github.com/hexagon-oss/libcoap/commit/8090b64875e24259b28bb43030c4524a64877d67
This is not thoroughly tested and still work in progress for evaluating client mode. And since I have no good understanding of libcoap contexts, sessions and endpoints, I might have broken something. However, for me this code seems to work better than the develop branch...
@bahm-lgs Thanks - I will have a look at this.
@bahm-lgs Apologies for taking so long. I have taken your code, along with some modifications, and have created PR #926 which has NO_SYS=1. If you could try this out it would be great.
@bahm-lgs Apologies for taking so long. I have taken your code, along with some modifications, and have created PR #926 which has NO_SYS=1. If you could try this out it would be great.
@mrdeep1 Yes, I can do this. Just gave it a quick try this afternoon compiling the code - I had to "#ifdef LWIP_UNIX_LINUX" the tapif_select call since my environment doesn't have it. Then I could link the library into my application.
I was able to send five messages, then everything got stuck because of PDUs not being freed... s.th. may be wrong in the recv() part and messages are not unqueued when ACK'ed. I will have a look at that in the next days.
@bahm-lgs Thanks for coming back.
I had to "#ifdef LWIP_UNIX_LINUX" the tapif_select call since my environment doesn't have it. Then I could link the library into my application.
Was this in coap_client_delay_first()
? It is unlikely that this function will be being called that often when using LwIP and I was thinking of looking at re-writing it now that we have a LwIP coap_io_process()
function (but that has no way of LwIP select type delaying that I can find).
I was able to send five messages, then everything got stuck because of PDUs not being freed... s.th. may be wrong in the recv() part and messages are not unqueued when ACK'ed. I will have a look at that in the next days.
Interesting. I have only done up to sending 2 requests, but valgrind did not complain about PDUs or pbuf RAM being freed off. I will look into that. I did have an issue where pbuf cannot be used on a re-transmit (i.e, missing ACK response, but that was fixed using pbuf_clone()
.
@bahm-lgs Thanks for coming back.
No big deal, just back from vacation, I'm glad you take care of this so I'm eager to help.
I had to "#ifdef LWIP_UNIX_LINUX" the tapif_select call since my environment doesn't have it. Then I could link the library into my application.
Was this in
coap_client_delay_first()
? It is unlikely that this function will be being called that often when using LwIP and I was thinking of looking at re-writing it now that we have a LwIPcoap_io_process()
function (but that has no way of LwIP select type delaying that I can find).
Yes.
I was able to send five messages, then everything got stuck because of PDUs not being freed... s.th. may be wrong in the recv() part and messages are not unqueued when ACK'ed. I will have a look at that in the next days.
Interesting. I have only done up to sending 2 requests, but valgrind did not complain about PDUs or pbuf RAM being freed off. I will look into that. I did have an issue where pbuf cannot be used on a re-transmit (i.e, missing ACK response, but that was fixed using
pbuf_clone()
.
Let me check this again in the next days, I really did not have much time today to do any analysis.
@bahm-lgs I did find an issue with transmits obeying NSTART which has now been fixed and code pushed. The libcoap version of the LwIP Makefile has updated the version of lwip / lwip-contrib to STABLE-2_1_3_RELEASE / STABLE-2_1_0_RELEASE. There was difference in how these versions handled pbuf's in udp_sendto() - the later version being more reliable.
@bahm-lgs I have re-written coap_client_delay_first()
and pushed the code update to PR #926.
@bahm-lgs I have re-written
coap_client_delay_first()
and pushed the code update to PR #926.
@mrdeep1 both your old and new code did not work for me, the new code ran out of memory even earlier. But I found the issue: After reverting your setting of MEM_SIZE in lwipopts.h everything seems to work, both, your old and your new commit.
However, there still seems to be something wrong with retransmissions not being sent at all which seemed to have worked better on my branch before. But I was about to look into this anyway: retransmitted messages were not removed from the sendqueue after finally an ACK arrived.
After reverting your setting of MEM_SIZE in lwipopts.h everything seems to work, both, your old and your new commit.
So, what do you now have for #define MEM_SIZE (32 * 1024)
? I needed to add this in otherwise I could only allocate a single pbuf for a PDU.
I will look to see why there are issues after re-transmit - should be fairly easy to reproduce.
After reverting your setting of MEM_SIZE in lwipopts.h everything seems to work, both, your old and your new commit.
So, what do you now have for
#define MEM_SIZE (32 * 1024)
? I needed to add this in otherwise I could only allocate a single pbuf for a PDU.I will look to see why there are issues after re-transmit - should be fairly easy to reproduce.
For my environment this is set in the Xilinx Vitis GUI, currently it is set to the GUI's default 131072. Before compilation all the GUI settings for lwip are merged into a lwipopts.h file for compilation of lwip. For some reason your setting overruled the lwip setting. Must have been s.th. to do with moving header files around so libcoap used a different lwipopts.h file than lwip and it got somehow included twice. Sorry for the confusion.
No worries. Yes, lwipopts.h now sits under the config/ directory and the -iquote
. compiler option updated to -iquote./config
in Makefile.
Still trying to see why there is a issue of re-transmitted messages not being removed from the sendqueue (not reproduced it yet)
I am not able to reproduce the issue you are seeing where the sendqueue entry is not removed on receiving an ACK after re-transmits.
I am not able to reproduce the issue you are seeing where the sendqueue entry is not removed on receiving an ACK after re-transmits.
@mrdeep1 I found the reason for this: With many unanswered requests I was running out of PDU memory. If the server then came back online and answered requests there were no PDUs left for the responses :-)
Fixed it now by monitoring the length of context->sendqueue and session->delayqueue before initiating new requests.
Maybe we should have some libcoap-internal mechanism to ensure there is always one PDU left for responses or for sending RST messages to not get into such a lockup condition?
Thanks for tracking this down.
I assume that you are running out of PDUs (struct that describe the state of the PDU data) as opposed to to the pbuf
that contains the data (ethernet, IP, UDP, CoAP headers along with the CoAP options + data) that comes out of the LwIP heap (MEM_SIZE).
While trying to reproduce the issue, I have come up with some debug code describing the state of all the memory space as described by lwipppools.h
which helped my understanding of what is happening here. I will look to see whether we can have the concept of "reserved" for the PDUs (I think it needs to be 2 - the response PDU and for any reaction to the response PDU).