Exemplo n.º 1
0
static void test_sock_udp_create__EADDRINUSE(void)
{
    static const sock_udp_ep_t local = { .family = AF_INET6,
                                         .port = _TEST_PORT_LOCAL };

    assert(0 == sock_udp_create(&_sock, &local, NULL, 0));
    assert(-EADDRINUSE == sock_udp_create(&_sock2, &local, NULL, 0));
}
Exemplo n.º 2
0
static void test_sock_udp_create__EAFNOSUPPORT(void)
{
    /* port may not be NULL according to doc */
    static const sock_udp_ep_t local = { .family = AF_UNSPEC,
                                         .port = _TEST_PORT_LOCAL };
    /* port may not be NULL according to doc */
    static const sock_udp_ep_t remote = { .family = AF_UNSPEC,
                                          .port = _TEST_PORT_REMOTE };

    assert(-EAFNOSUPPORT == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
    assert(-EAFNOSUPPORT == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
}
Exemplo n.º 3
0
/**
 * @brief Request prefix from uhcp server
 *
 * Never returns.
 * Calls @c uhcp_handle_prefix() when a prefix or prefix change is received.
 *
 * @param[in]   iface   interface to request prefix on
 */
void uhcp_client(uhcp_iface_t iface)
{
    sock_udp_t sock;
    sock_udp_ep_t local = { .family=AF_INET6, .port=UHCP_PORT, .netif=iface };
    sock_udp_ep_t req_target = { .family=AF_INET6, .port=UHCP_PORT, .netif=iface };
    sock_udp_ep_t remote;

    inet_pton(AF_INET6, "ff15::abcd", req_target.addr.ipv6);

    /* prepare UHCP header */
    uhcp_req_t req;
    uhcp_hdr_set(&req.hdr, UHCP_REQ);
    req.prefix_len = 64;

    /* create listening socket */
    int res = sock_udp_create(&sock, &local, NULL, 0);

    uint8_t buf[sizeof(uhcp_push_t) + 16];

    while(1) {
        puts("uhcp_client(): sending REQ...");
        sock_udp_send(&sock, &req, sizeof(uhcp_req_t), &req_target);
        res = sock_udp_recv(&sock, buf, sizeof(buf), 10U*US_PER_SEC, &remote);
        if (res > 0) {
            uhcp_handle_udp(buf, res, remote.addr.ipv6, remote.port, iface);
            xtimer_sleep(60);
        }
        else {
            puts("uhcp_client(): no reply received");
        }
    }
}
Exemplo n.º 4
0
/*
 * Starts a blocking and never-returning loop dispatching CoAP requests.
 *
 * When using gnrc, make sure the calling thread has an initialized msg queue.
 */
void microcoap_server_loop(void)
{

    static const sock_udp_ep_t local = { .family = AF_INET6,
                                         .port = COAP_SERVER_PORT };
    sock_udp_ep_t remote;

    sock_udp_t sock;

    int rc = sock_udp_create(&sock, &local, NULL, 0);

    while (1) {
        DEBUG("Waiting for incoming UDP packet...\n");
        rc = sock_udp_recv(&sock, (char *)_udp_buf, sizeof(_udp_buf),
                           SOCK_NO_TIMEOUT, &remote);
        if (rc < 0) {
            DEBUG("Error in sock_udp_recv(). rc=%u\n", rc);
            continue;
        }

        size_t n = rc;

        coap_packet_t pkt;
        DEBUG("Received packet: ");
        coap_dump(_udp_buf, n, true);
        DEBUG("\n");

        /* parse UDP packet to CoAP */
        if (0 != (rc = coap_parse(&pkt, _udp_buf, n))) {
            DEBUG("Bad packet rc=%d\n", rc);
        }
        else {
            coap_packet_t rsppkt;
            DEBUG("content:\n");
            coap_dumpPacket(&pkt);

            /* handle CoAP request */
            coap_handle_req(&scratch_buf, &pkt, &rsppkt);

            /* build reply */
            size_t rsplen = sizeof(_udp_buf);
            if ((rc = coap_build(_udp_buf, &rsplen, &rsppkt)) != 0) {
                DEBUG("coap_build failed rc=%d\n", rc);
            }
            else {
                DEBUG("Sending packet: ");
                coap_dump(_udp_buf, rsplen, true);
                DEBUG("\n");
                DEBUG("content:\n");
                coap_dumpPacket(&rsppkt);

                /* send reply via UDP */
                rc = sock_udp_send(&sock, _udp_buf, rsplen, &remote);
                if (rc < 0) {
                    DEBUG("Error sending CoAP reply via udp; %u\n", rc);
                }
            }
        }
    }
}
Exemplo n.º 5
0
static void test_sock_udp_recv__EADDRNOTAVAIL(void)
{
    assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));

    assert(-EADDRNOTAVAIL == sock_udp_recv(&_sock, _test_buffer,
                                           sizeof(_test_buffer),
                                           SOCK_NO_TIMEOUT, NULL));
}
Exemplo n.º 6
0
static void test_sock_udp_create__no_endpoints(void)
{
    sock_udp_ep_t ep;

    assert(0 == sock_udp_create(&_sock, NULL, NULL, SOCK_FLAGS_REUSE_EP));
    assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep));
    assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
}
Exemplo n.º 7
0
Arquivo: sock.c Projeto: A-Paul/RIOT
ssize_t nanocoap_request(coap_pkt_t *pkt, sock_udp_ep_t *local, sock_udp_ep_t *remote, size_t len)
{
    ssize_t res;
    size_t pdu_len = (pkt->payload - (uint8_t *)pkt->hdr) + pkt->payload_len;
    uint8_t *buf = (uint8_t*)pkt->hdr;
    sock_udp_t sock;

    if (!remote->port) {
        remote->port = COAP_PORT;
    }

    res = sock_udp_create(&sock, local, remote, 0);
    if (res < 0) {
        return res;
    }

    /* TODO: timeout random between between ACK_TIMEOUT and (ACK_TIMEOUT *
     * ACK_RANDOM_FACTOR) */
    uint32_t timeout = COAP_ACK_TIMEOUT * US_PER_SEC;
    unsigned tries_left = COAP_MAX_RETRANSMIT + 1;  /* add 1 for initial transmit */
    while (tries_left) {

        res = sock_udp_send(&sock, buf, pdu_len, NULL);
        if (res <= 0) {
            DEBUG("nanocoap: error sending coap request, %d\n", (int)res);
            break;
        }

        res = sock_udp_recv(&sock, buf, len, timeout, NULL);
        if (res <= 0) {
            if (res == -ETIMEDOUT) {
                DEBUG("nanocoap: timeout\n");

                timeout *= 2;
                tries_left--;
                if (!tries_left) {
                    DEBUG("nanocoap: maximum retries reached\n");
                }
                continue;
            }
            DEBUG("nanocoap: error receiving coap response, %d\n", (int)res);
            break;
        }
        else {
            if (coap_parse(pkt, (uint8_t *)buf, res) < 0) {
                DEBUG("nanocoap: error parsing packet\n");
                res = -EBADMSG;
            }
            break;
        }
    }

    sock_udp_close(&sock);

    return res;
}
Exemplo n.º 8
0
static void test_sock_udp_recv__EAGAIN(void)
{
    static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
                                         .port = _TEST_PORT_LOCAL };

    assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));

    assert(-EAGAIN == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer),
                                    0, NULL));
}
Exemplo n.º 9
0
static void test_sock_udp_create__EINVAL_addr(void)
{
    /* port may not be NULL according to doc */
    static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
                                         .port = _TEST_PORT_LOCAL };
    /* port may not be NULL according to doc */
    static const sock_udp_ep_t remote = { .family = AF_INET6,
                                          .netif = _TEST_NETIF,
                                          .port = _TEST_PORT_REMOTE };

    assert(-EINVAL == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
}
Exemplo n.º 10
0
static void test_sock_udp_recv__ENOBUFS(void)
{
    static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_REMOTE };
    static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
    static const sock_udp_ep_t local = { .family = AF_INET6,
                                         .port = _TEST_PORT_LOCAL };

    assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
    assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
                          _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"), _TEST_NETIF));
    assert(-ENOBUFS == sock_udp_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT,
                                     NULL));
    assert(_check_net());
}
Exemplo n.º 11
0
static void test_sock_udp_create__only_local_reuse_ep(void)
{
    static const sock_udp_ep_t local = { .family = AF_INET6,
                                         .port = _TEST_PORT_LOCAL };
    sock_udp_ep_t ep, ep2;

    assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
    assert(0 == sock_udp_create(&_sock2, &local, NULL, SOCK_FLAGS_REUSE_EP));
    assert(0 == sock_udp_get_local(&_sock, &ep));
    assert(0 == sock_udp_get_local(&_sock2, &ep2));
    assert(AF_INET6 == ep.family);
    assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
                  sizeof(ipv6_addr_t)) == 0);
    assert(SOCK_ADDR_ANY_NETIF == ep.netif);
    assert(_TEST_PORT_LOCAL == ep.port);
    assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep));
    assert(AF_INET6 == ep2.family);
    assert(memcmp(&ipv6_addr_unspecified, &ep2.addr.ipv6,
                  sizeof(ipv6_addr_t)) == 0);
    assert(SOCK_ADDR_ANY_NETIF == ep2.netif);
    assert(_TEST_PORT_LOCAL == ep2.port);
    assert(-ENOTCONN == sock_udp_get_remote(&_sock, &ep2));
    sock_udp_close(&_sock2);
}
Exemplo n.º 12
0
static void test_sock_udp_create__only_remote(void)
{
    static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
    static const sock_udp_ep_t remote = { .family = AF_INET6,
                                          .port = _TEST_PORT_REMOTE,
                                          .addr = { .ipv6 = _TEST_ADDR_REMOTE } };
    sock_udp_ep_t ep;

    assert(0 == sock_udp_create(&_sock, NULL, &remote, SOCK_FLAGS_REUSE_EP));
    assert(-EADDRNOTAVAIL == sock_udp_get_local(&_sock, &ep));
    assert(0 == sock_udp_get_remote(&_sock, &ep));
    assert(AF_INET6 == ep.family);
    assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
    assert(SOCK_ADDR_ANY_NETIF == ep.netif);
    assert(_TEST_PORT_REMOTE == ep.port);
}
Exemplo n.º 13
0
int sntp_sync(sock_udp_ep_t *server, uint32_t timeout)
{
    int result;

    mutex_lock(&_sntp_mutex);
    if ((result = sock_udp_create(&_sntp_sock,
                                  NULL,
                                  server,
                                  0)) < 0) {
        DEBUG("Error creating UDP sock\n");
        mutex_unlock(&_sntp_mutex);
        return result;
    }
    memset(&_sntp_packet, 0, sizeof(_sntp_packet));
    ntp_packet_set_vn(&_sntp_packet);
    ntp_packet_set_mode(&_sntp_packet, NTP_MODE_CLIENT);

    if ((result = (int)sock_udp_send(&_sntp_sock,
                                     &_sntp_packet,
                                     sizeof(_sntp_packet),
                                     NULL)) < 0) {
        DEBUG("Error sending message\n");
        sock_udp_close(&_sntp_sock);
        mutex_unlock(&_sntp_mutex);
        return result;
    }
    if ((result = (int)sock_udp_recv(&_sntp_sock,
                                     &_sntp_packet,
                                     sizeof(_sntp_packet),
                                     timeout,
                                     NULL)) < 0) {
        DEBUG("Error receiving message\n");
        sock_udp_close(&_sntp_sock);
        mutex_unlock(&_sntp_mutex);
        return result;
    }
    sock_udp_close(&_sntp_sock);
    _sntp_offset = (byteorder_ntohl(_sntp_packet.transmit.seconds) * US_PER_SEC) +
                   ((byteorder_ntohl(_sntp_packet.transmit.fraction) * 232)
                   / 1000000) - xtimer_now64();
    mutex_unlock(&_sntp_mutex);
    return 0;
}
Exemplo n.º 14
0
static int
sock_send_payload (long dest, int port, char *packet, int packet_len)
{
    int sock;

    /* create udp socket */
    sock = sock_udp_create ();
    if (sock_connect (sock, dest, PROTO_3G_A11_PORT) < 0)
	    return -1;

    /* send packet */
    send (sock, packet, packet_len, 0);

    printf ("[-] UDP packet sent (%d bytes).\n", packet_len);
    fflush (stdout);

    /* disconnect socket */
    sock_disconnect (sock);

    return 0;
}
Exemplo n.º 15
0
/* Event/Message loop for gcoap _pid thread. */
static void *_event_loop(void *arg)
{
    msg_t msg_rcvd, msg_queue[GCOAP_MSG_QUEUE_SIZE];
    (void)arg;

    msg_init_queue(msg_queue, GCOAP_MSG_QUEUE_SIZE);

    sock_udp_ep_t local;
    memset(&local, 0, sizeof(sock_udp_ep_t));
    local.family = AF_INET6;
    local.netif  = SOCK_ADDR_ANY_NETIF;
    local.port   = GCOAP_PORT;

    int res = sock_udp_create(&_sock, &local, NULL, 0);
    if (res < 0) {
        DEBUG("gcoap: cannot create sock: %d\n", res);
        return 0;
    }

    while(1) {
        res = msg_try_receive(&msg_rcvd);

        if (res > 0) {
            switch (msg_rcvd.type) {
                case GCOAP_MSG_TYPE_TIMEOUT:
                    _expire_request((gcoap_request_memo_t *)msg_rcvd.content.ptr);
                    break;
                case GCOAP_MSG_TYPE_INTR:
                    /* next _listen() timeout will account for open requests */
                    break;
                default:
                    break;
            }
        }

        _listen(&_sock);
    }

    return 0;
}
Exemplo n.º 16
0
Arquivo: udp.c Projeto: A-Paul/RIOT
static void *_server_thread(void *args)
{
    sock_udp_ep_t server_addr = SOCK_IPV6_EP_ANY;
    int res;

    msg_init_queue(server_msg_queue, SERVER_MSG_QUEUE_SIZE);
    /* parse port */
    server_addr.port = atoi(args);
    if ((res = sock_udp_create(&server_sock, &server_addr, NULL, 0)) < 0) {
        printf("Unable to open UDP server on port %" PRIu16 " (error code %d)\n",
               server_addr.port, -res);
        return NULL;
    }
    server_running = true;
    printf("Success: started UDP server on port %" PRIu16 "\n",
           server_addr.port);
    while (1) {
        sock_udp_ep_t src;
        int res;

        if ((res = sock_udp_recv(&server_sock, sock_inbuf, sizeof(sock_inbuf),
                                 SOCK_NO_TIMEOUT, &src)) < 0) {
            puts("Error on receive");
        }
        else if (res == 0) {
            puts("No data received");
        }
        else {
            char addrstr[IPV6_ADDR_MAX_STR_LEN];

            printf("Received UDP data from [%s]:%" PRIu16 ":\n",
                   ipv6_addr_to_str(addrstr, (ipv6_addr_t *)&src.addr.ipv6,
                                    sizeof(addrstr)), src.port);
            od_hex_dump(sock_inbuf, res, 0);
        }
    }
    return NULL;
}
Exemplo n.º 17
0
static void test_sock_udp_create__full(void)
{
    static const ipv6_addr_t remote_addr = { .u8 = _TEST_ADDR_REMOTE };
    static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
                                         .port = _TEST_PORT_LOCAL };
    static const sock_udp_ep_t remote = { .family = AF_INET6,
                                          .port = _TEST_PORT_REMOTE,
                                          .addr = { .ipv6 = _TEST_ADDR_REMOTE } };
    sock_udp_ep_t ep;

    assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
    assert(0 == sock_udp_get_local(&_sock, &ep));
    assert(AF_INET6 == ep.family);
    assert(memcmp(&ipv6_addr_unspecified, &ep.addr.ipv6,
                  sizeof(ipv6_addr_t)) == 0);
    assert(_TEST_NETIF == ep.netif);
    assert(_TEST_PORT_LOCAL == ep.port);
    assert(0 == sock_udp_get_remote(&_sock, &ep));
    assert(AF_INET6 == ep.family);
    assert(memcmp(&remote_addr, &ep.addr.ipv6, sizeof(ipv6_addr_t)) == 0);
    assert(SOCK_ADDR_ANY_NETIF == ep.netif);
    assert(_TEST_PORT_REMOTE == ep.port);
}
Exemplo n.º 18
0
Arquivo: sock.c Projeto: A-Paul/RIOT
int nanocoap_server(sock_udp_ep_t *local, uint8_t *buf, size_t bufsize)
{
    sock_udp_t sock;
    sock_udp_ep_t remote;

    if (!local->port) {
        local->port = COAP_PORT;
    }

    ssize_t res = sock_udp_create(&sock, local, NULL, 0);
    if (res != 0) {
        return -1;
    }

    while (1) {
        res = sock_udp_recv(&sock, buf, bufsize, -1, &remote);
        if (res < 0) {
            DEBUG("error receiving UDP packet %d\n", (int)res);
        }
        else if (res > 0) {
            coap_pkt_t pkt;
            if (coap_parse(&pkt, (uint8_t *)buf, res) < 0) {
                DEBUG("error parsing packet\n");
                continue;
            }
            if ((res = coap_handle_req(&pkt, buf, bufsize)) > 0) {
                res = sock_udp_send(&sock, buf, res, &remote);
            }
            else {
                DEBUG("error handling request %d\n", (int)res);
            }
        }
    }

    return 0;
}
Exemplo n.º 19
0
    assert(-ENOBUFS == sock_udp_recv(&_sock, _test_buffer, 2, SOCK_NO_TIMEOUT,
                                     NULL));
    assert(_check_net());
}

static void test_sock_udp_recv__EPROTO(void)
{
    static const ipv6_addr_t src_addr = { .u8 = _TEST_ADDR_WRONG };
    static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL };
    static const sock_udp_ep_t local = { .family = AF_INET6,
                                         .port = _TEST_PORT_LOCAL };
    static const sock_udp_ep_t remote = { .addr = { .ipv6 = _TEST_ADDR_REMOTE },
                                          .family = AF_INET6,
                                          .port = _TEST_PORT_REMOTE };

    assert(0 == sock_udp_create(&_sock, &local, &remote, SOCK_FLAGS_REUSE_EP));
    assert(_inject_packet(&src_addr, &dst_addr, _TEST_PORT_REMOTE,
                          _TEST_PORT_LOCAL, "ABCD", sizeof("ABCD"),
                          _TEST_NETIF));
    assert(-EPROTO == sock_udp_recv(&_sock, _test_buffer, sizeof(_test_buffer),
                                    SOCK_NO_TIMEOUT, NULL));
    assert(_check_net());
}

static void test_sock_udp_recv__ETIMEDOUT(void)
{
    static const sock_udp_ep_t local = { .family = AF_INET6, .netif = _TEST_NETIF,
                                         .port = _TEST_PORT_LOCAL };

    assert(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP));
Exemplo n.º 20
0
void emcute_run(uint16_t port, const char *id)
{
    assert(strlen(id) < EMCUTE_ID_MAXLEN);

    sock_udp_ep_t local = SOCK_IPV6_EP_ANY;
    sock_udp_ep_t remote;
    local.port = port;
    cli_id = id;
    timer.callback = time_evt;
    timer.arg = NULL;
    mutex_init(&txlock);

    if (sock_udp_create(&sock, &local, NULL, 0) < 0) {
        LOG_ERROR("[emcute] unable to open UDP socket on port %i\n", (int)port);
        return;
    }

    uint32_t start = xtimer_now_usec();
    uint32_t t_out = (EMCUTE_KEEPALIVE * US_PER_SEC);

    while (1) {
        ssize_t len = sock_udp_recv(&sock, rbuf, sizeof(rbuf), t_out, &remote);

        if ((len < 0) && (len != -ETIMEDOUT)) {
            LOG_ERROR("[emcute] error while receiving UDP packet\n");
            return;
        }

        if (len >= 2) {
            /* handle the packet */
            uint16_t pkt_len;
            /* catch invalid length field */
            if ((len == 2) && (rbuf[0] == 0x01)) {
                continue;
            }
            /* parse length field */
            size_t pos = get_len(rbuf, &pkt_len);
            /* verify length to prevent overflows */
            if (((size_t)pkt_len > (size_t)len) || (pos >= (size_t)len)) {
                continue;
            }
            /* get packet type */
            uint8_t type = rbuf[pos];

            switch (type) {
                case CONNACK:       on_ack(type, 0, 2, 0);              break;
                case WILLTOPICREQ:  on_ack(type, 0, 0, 0);              break;
                case WILLMSGREQ:    on_ack(type, 0, 0, 0);              break;
                case REGACK:        on_ack(type, 4, 6, 2);              break;
                case PUBLISH:       on_publish((size_t)pkt_len, pos);   break;
                case PUBACK:        on_ack(type, 4, 6, 0);              break;
                case SUBACK:        on_ack(type, 5, 7, 3);              break;
                case UNSUBACK:      on_ack(type, 2, 0, 0);              break;
                case PINGREQ:       on_pingreq(&remote);                break;
                case PINGRESP:      on_pingresp();                      break;
                case DISCONNECT:    on_disconnect();                    break;
                case WILLTOPICRESP: on_ack(type, 0, 0, 0);              break;
                case WILLMSGRESP:   on_ack(type, 0, 0, 0);              break;
                default:
                    LOG_DEBUG("[emcute] received unexpected type [%s]\n",
                              emcute_type_str(type));
            }
        }

        uint32_t now = xtimer_now_usec();
        if ((now - start) >= (EMCUTE_KEEPALIVE * US_PER_SEC)) {
            send_ping();
            start = now;
            t_out = (EMCUTE_KEEPALIVE * US_PER_SEC);
        }
        else {
            t_out = (EMCUTE_KEEPALIVE * US_PER_SEC) - (now - start);
        }
    }
}
Exemplo n.º 21
0
/* Event/Message loop for gcoap _pid thread. */
static void *_event_loop(void *arg)
{
    msg_t msg_rcvd;
    (void)arg;

    msg_init_queue(_msg_queue, GCOAP_MSG_QUEUE_SIZE);

    sock_udp_ep_t local;
    memset(&local, 0, sizeof(sock_udp_ep_t));
    local.family = AF_INET6;
    local.netif  = SOCK_ADDR_ANY_NETIF;
    local.port   = GCOAP_PORT;

    int res = sock_udp_create(&_sock, &local, NULL, 0);
    if (res < 0) {
        DEBUG("gcoap: cannot create sock: %d\n", res);
        return 0;
    }

    while(1) {
        res = msg_try_receive(&msg_rcvd);

        if (res > 0) {
            switch (msg_rcvd.type) {
            case GCOAP_MSG_TYPE_TIMEOUT: {
                gcoap_request_memo_t *memo = (gcoap_request_memo_t *)msg_rcvd.content.ptr;

                /* no retries remaining */
                if ((memo->send_limit == GCOAP_SEND_LIMIT_NON)
                        || (memo->send_limit == 0)) {
                    _expire_request(memo);
                }
                /* reduce retries remaining, double timeout and resend */
                else {
                    memo->send_limit--;
                    unsigned i        = COAP_MAX_RETRANSMIT - memo->send_limit;
                    uint32_t timeout  = ((uint32_t)COAP_ACK_TIMEOUT << i) * US_PER_SEC;
                    uint32_t variance = ((uint32_t)COAP_ACK_VARIANCE << i) * US_PER_SEC;
                    timeout = random_uint32_range(timeout, timeout + variance);

                    ssize_t bytes = sock_udp_send(&_sock, memo->msg.data.pdu_buf,
                                                  memo->msg.data.pdu_len,
                                                  &memo->remote_ep);
                    if (bytes > 0) {
                        xtimer_set_msg(&memo->response_timer, timeout,
                                       &memo->timeout_msg, _pid);
                    }
                    else {
                        DEBUG("gcoap: sock resend failed: %d\n", (int)bytes);
                        _expire_request(memo);
                    }
                }
                break;
            }
            default:
                break;
            }
        }

        _listen(&_sock);
    }

    return 0;
}