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!

  • 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

  • Hi Ladivin,

     

    Sorry if I am going a bit too deep into the debug rabbit hole here.

    Ladivin said:

    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.

    EIO is typically seen when the connection is reset or has timed out, or that the 'fd' is .

     

    Ladivin said:

    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?

    the VTABLE_CALL is effectively a function pointer lookup macro:

    https://github.com/nrfconnect/sdk-zephyr/blob/v3.7.99-ncs2/subsys/net/lib/sockets/sockets.c#L40

     

    which is a helper library for the zephyr native net stack. Here's an example from nrf/samples/net/udp, where I break on net/ip/udp.c::net_udp_create():

    Breakpoint 7, net_udp_create (pkt=pkt@entry=0x200400f0 <_k_mem_slab_buf_tx_pkts+192>, src_port=29428, dst_port=dst_port@entry=42249) at /opt/ncs/zephyr/subsys/net/ip/udp.c:22
    22		NET_PKT_DATA_ACCESS_DEFINE(udp_access, struct net_udp_hdr);
    (gdb) bt
    #0  net_udp_create (pkt=pkt@entry=0x200400f0 <_k_mem_slab_buf_tx_pkts+192>, src_port=29428, 
        dst_port=dst_port@entry=42249) at /opt/ncs/zephyr/subsys/net/ip/udp.c:22
    #1  0x00072884 in context_setup_udp_packet (addrlen=<optimized out>, dst_addr=<optimized out>, msg=0x0, len=10, 
        buf=0x20021bec <sys_work_q_stack+1948>, pkt=0x200400f0 <_k_mem_slab_buf_tx_pkts+192>, family=1, 
        context=0x2000ff0c <contexts+336>) at /opt/ncs/zephyr/subsys/net/ip/net_context.c:1843
    #2  context_sendto (context=context@entry=0x2000ff0c <contexts+336>, 
        buf=buf@entry=0x20021bec <sys_work_q_stack+1948>, len=len@entry=10, dst_addr=<optimized out>, 
        dst_addr@entry=0x2000ff3c <contexts+384>, addrlen=<optimized out>, cb=<optimized out>, cb@entry=0x0, 
        user_data=<optimized out>, user_data@entry=0x0, sendto=<optimized out>, sendto@entry=false, timeout=...)
        at /opt/ncs/zephyr/subsys/net/ip/net_context.c:2251
    #3  0x00072b48 in net_context_send (context=context@entry=0x2000ff0c <contexts+336>, 
        buf=buf@entry=0x20021bec <sys_work_q_stack+1948>, len=len@entry=10, cb=cb@entry=0x0, timeout=..., user_data=0x0)
        at /opt/ncs/zephyr/subsys/net/ip/net_context.c:2364
    #4  0x00042f80 in zsock_sendto_ctx (ctx=0x2000ff0c <contexts+336>, buf=0x20021bec <sys_work_q_stack+1948>, len=10, 
        flags=<optimized out>, dest_addr=0x0, addrlen=0) at /opt/ncs/zephyr/subsys/net/lib/sockets/sockets_inet.c:620
    #5  0x00042406 in z_impl_zsock_sendto (sock=<optimized out>, buf=0x20021bec <sys_work_q_stack+1948>, 
        buf@entry=0x20021bd4 <sys_work_q_stack+1924>, len=len@entry=10, flags=flags@entry=0, 
        dest_addr=dest_addr@entry=0x0, addrlen=addrlen@entry=0) at /opt/ncs/zephyr/subsys/net/lib/sockets/sockets.c:358
    #6  0x0006fc5c in zsock_sendto (addrlen=0, dest_addr=0x0, flags=flags@entry=0, len=len@entry=10, 
        buf=buf@entry=0x20021bd4 <sys_work_q_stack+1924>, sock=<optimized out>)
        at /opt/ncs/nrf/samples/net/udp/build/udp/zephyr/include/generated/zephyr/syscalls/socket.h:260
    #7  zsock_send (flags=flags@entry=0, len=len@entry=10, buf=buf@entry=0x20021bd4 <sys_work_q_stack+1924>, 
        sock=<optimized out>) at /opt/ncs/zephyr/include/zephyr/net/socket.h:462
    #8  send (sock=<optimized out>, buf=buf@entry=0x20021bf4 <sys_work_q_stack+1956>, len=len@entry=10, 
        flags=flags@entry=0) at /opt/ncs/zephyr/lib/posix/options/net.c:360
    #9  0x00022230 in server_transmission_work_fn (work=<optimized out>) at /opt/ncs/nrf/samples/net/udp/src/main.c:61
    #10 0x0005b014 in work_queue_main (workq_ptr=0x2000f1d0 <k_sys_work_q>, p2=<optimized out>, p3=<optimized out>)
        at /opt/ncs/zephyr/kernel/work.c:688
    #11 0x00022c42 in z_thread_entry (entry=0x5af91 <work_queue_main>, p1=0x2000f1d0 <k_sys_work_q>, p2=0x0, p3=0x0)
        at /opt/ncs/zephyr/lib/os/thread_entry.c:48
    #12 0xaaaaaaaa in ?? ()
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)
    (gdb) 
    
    Frame #9 is the call from main:

    https://github.com/nrfconnect/sdk-nrf/blob/main/samples/net/udp/src/main.c#L61

     

    It will be similar with other socket types, for instance TCP or TLS. They will then end up in the corresponding native net implementation provided that CONFIG_NET_NATIVE is y-selected:

    https://github.com/nrfconnect/sdk-zephyr/tree/main/subsys/net/ip

     

    Kind regards,

    Håkon

Related