Understanding Error Codes in HTTPS Client Implementation

Dear Nordic Team,

I am currently working on a project that utilizes your HTTPS client sample, specifically on the nRF5340 with the 7002EK. The main difference from the sample is that I am using the http_client_req function. Initially, I followed the same workflow as the sample: opening a socket, connecting, sending data, receiving a response, and then closing the socket. However, I encountered an issue where the connect function occasionally returned a negative value and set errno to 2.

Since I frequently communicate with my server, I modified the workflow to keep the socket open after connecting, allowing me to exchange requests continuously before closing the socket when finished. This change resolved the "errno 2" issue, but I still occasionally receive a -5 return value from http_client_req, indicating an I/O error. I have implemented a workaround by waiting briefly and then retrying, but I would like to know if there is a better solution.

Additionally, could you clarify the exact meanings of the error values I am encountering with the connect function and http_client_req? Is there a way to determine whether these errors are caused by the server or are local issues? Could there be a hardware problem or an issue within the networking/Wi-Fi stack? I know that error nr 2 means "No such file or directory" and error 5 " I/O error", but unfortunately, this does help me to understand the situation. 

I am using SDK version 2.6.1.

Thank you for your assistance!

Parents
  • Hi,

     

    You mention that this happens sometimes, ie. not always.

    Is the occurrence of this issue changed if you adjust these two configurations?

    # Set these to a higher value than your default values
    CONFIG_POSIX_MAX_FDS=20 
    CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4

    Since I frequently communicate with my server, I modified the workflow to keep the socket open after connecting, allowing me to exchange requests continuously before closing the socket when finished. This change resolved the "errno 2" issue, but I still occasionally receive a -5 return value from http_client_req, indicating an I/O error. I have implemented a workaround by waiting briefly and then retrying, but I would like to know if there is a better solution.

    How long do you keep the socket open for?

    If kept open for a longer period, the peer might have closed your connection.

     

    Additionally, could you clarify the exact meanings of the error values I am encountering with the connect function and http_client_req? Is there a way to determine whether these errors are caused by the server or are local issues? Could there be a hardware problem or an issue within the networking/Wi-Fi stack? I know that error nr 2 means "No such file or directory" and error 5 " I/O error", but unfortunately, this does help me to understand the situation. 

    http_client_req looks to return directly, meaning that the function itself does not explicitly set errno. If errno is read, this can be a red herring, depending on the underlying function call wrote to errno or not.

     

    connect() shall return -1 and errno shall then hold the output, so that one is quite clear, but -2 (ENOENT) is not a defined return from connect itself. Are you certain that this is the correct call that returns -2? Do you do a getaddrinfo() call first? If so, it could be a "DNS_EAI_NONAME" returned from that one, which is also defined as -2.

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    You mention that this happens sometimes, ie. not always.

    Is the occurrence of this issue changed if you adjust these two configurations?

    # Set these to a higher value than your default values
    CONFIG_POSIX_MAX_FDS=20 
    CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4

    Since I frequently communicate with my server, I modified the workflow to keep the socket open after connecting, allowing me to exchange requests continuously before closing the socket when finished. This change resolved the "errno 2" issue, but I still occasionally receive a -5 return value from http_client_req, indicating an I/O error. I have implemented a workaround by waiting briefly and then retrying, but I would like to know if there is a better solution.

    How long do you keep the socket open for?

    If kept open for a longer period, the peer might have closed your connection.

     

    Additionally, could you clarify the exact meanings of the error values I am encountering with the connect function and http_client_req? Is there a way to determine whether these errors are caused by the server or are local issues? Could there be a hardware problem or an issue within the networking/Wi-Fi stack? I know that error nr 2 means "No such file or directory" and error 5 " I/O error", but unfortunately, this does help me to understand the situation. 

    http_client_req looks to return directly, meaning that the function itself does not explicitly set errno. If errno is read, this can be a red herring, depending on the underlying function call wrote to errno or not.

     

    connect() shall return -1 and errno shall then hold the output, so that one is quite clear, but -2 (ENOENT) is not a defined return from connect itself. Are you certain that this is the correct call that returns -2? Do you do a getaddrinfo() call first? If so, it could be a "DNS_EAI_NONAME" returned from that one, which is also defined as -2.

     

    Kind regards,

    Håkon

Children
  • Hello Håkon,

    Thanks for your answer!

    Is the occurrence of this issue changed if you adjust these two configurations?

    I'll try this out, and let you know, thanks! 

    How long do you keep the socket open for?

    If kept open for a longer period, the peer might have closed your connection.

    Sometimes for a very long time (e.g. an hour). Let me talk to the server guys if they can tell me if they closed the connection. 

    http_client_req looks to return directly, meaning that the function itself does not explicitly set errno. If errno is read, this can be a red herring, depending on the underlying function call wrote to errno or not.

    Sorry for the confusion. I know that http_client_req does not set errno and when I mentioned the "-5 error", this error value was directly returned from this function. 

    connect() shall return -1 and errno shall then hold the output, so that one is quite clear, but -2 (ENOENT) is not a defined return from connect itself. Are you certain that this is the correct call that returns -2? Do you do a getaddrinfo() call first? If so, it could be a "DNS_EAI_NONAME" returned from that one, which is also defined as -2.

    Same as above, sorry for the confusion. When I mentioned the "-2 error" I mean that connect returned -1 and errno was -2

    Best Regards,

    Ladivin

  • Hi Ladivin,

     

    Ladivin said:
    Sometimes for a very long time (e.g. an hour). Let me talk to the server guys if they can tell me if they closed the connection. 

    1 hour is very long to keep a socket open without any communication.

    There is a high probability that this connection will be timed out or that the peer drops the connection. Even if the server you're communicating with has the option to provide such a long TCP keep-alive, the network-path between you and the server (routing/NAT/firewalls etc) can potentially terminate the connection based on their local keep-alive policy.

    Ladivin said:
    Same as above, sorry for the confusion. When I mentioned the "-2 error" I mean that connect returned -1 and errno was -2

    no problem, thank you for clarifying!

    Let us assume that send() is the underlying call that returns EIO/ENOENT:

    https://pubs.opengroup.org/onlinepubs/000095399/functions/sendto.html

    ENOENT does not make sense for send/sendto, as the socket type here is not AF_UNIX (AF_INET or AF_INET6 is used here), so there might be another posix related call that returns this.

    Are there anything else in the debug log that can indicate where the failure occurred? I would expect to see a timeout related error/errno returned somewhere.

     

    Kind regards,

    Håkon

  • 1 hour is very long to keep a socket open without any communication.

    Actually, it is never without any communication - as long as the socket is open, there is one request after another. 

    There is a high probability that this connection will be timed out or that the peer drops the connection. Even if the server you're communicating with has the option to provide such a long TCP keep-alive, the network-path between you and the server (routing/NAT/firewalls etc) can potentially terminate the connection based on their local keep-alive policy.

    Ok, one possible meaning for http_client_req returning -5 is that the connection was dropped, correct?

    Are there anything else in the debug log that can indicate where the failure occurred? I would expect to see a timeout related error/errno returned somewhere.

    Actually I'm not seeing any other error. Would it makes sense to set log level to DBG for some modules? If so, could you please suggest which modules would be suitable for this? 

    Thanks!

    Best Regards,

    Ladivin

  • Hi Ladivin,

     

    Ladivin said:

    Actually, it is never without any communication - as long as the socket is open, there is one request after another. 

    This is good info. If the connection is maintained, then it should not be reset or timed out.

    Ladivin said:
    Ok, one possible meaning for http_client_req returning -5 is that the connection was dropped, correct?

    Depending on the timing between each request; yes, this is a potential cause.

    Ladivin said:
    Actually I'm not seeing any other error. Would it makes sense to set log level to DBG for some modules? If so, could you please suggest which modules would be suitable for this? 

    I believe these configurations shall emit some debug traces for you:

    CONFIG_NET_LOG=y
    CONFIG_NET_HTTP_LOG_LEVEL_DBG=y
    # Increase the log buffer in case there's an overflow
    CONFIG_LOG_BUFFER_SIZE=4096

    I added a increase of your log buffer, as you can get "dropped messages" if the log thread is not able to run for longer periods of time (ie. firmware is busy doing something else)

     

    Kind regards,

    Håkon

  • Hi Håkon,

    I believe these configurations shall emit some debug traces for you:

    Thank you! I've discovered that http_client_req returns -5, which originates from zsock_send() in the sendall() function within http_client.c. Specifically, zsock_send() returns -1 and sets errno to -5.

    I attempted to investigate the implementation of zsock_send(), but I got confused with z_impl_zsock_sendto(). I'm unable to determine what is being called by VTABLE_CALL. While I could use a debugger, my Wi-Fi projects are typically too large to compile in debug mode. Could you please advise me on how to uncover the implementation behind the VTABLE?

    Best regards,

    Ladivin

Related