mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
138 lines
3.3 KiB
C
138 lines
3.3 KiB
C
/*
|
|
* Copyright (C) 2016-17 Kaspar Schleiser <kaspar@schleiser.de>
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup sys_net_nanocoap
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Nanocoap sock helpers
|
|
*
|
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "net/nanocoap.h"
|
|
#include "net/sock/udp.h"
|
|
|
|
#define ENABLE_DEBUG (0)
|
|
#include "debug.h"
|
|
|
|
ssize_t nanocoap_get(sock_udp_ep_t *remote, const char *path, uint8_t *buf, size_t len)
|
|
{
|
|
ssize_t res;
|
|
sock_udp_t sock;
|
|
|
|
if (!remote->port) {
|
|
remote->port = COAP_PORT;
|
|
}
|
|
|
|
res = sock_udp_create(&sock, NULL, remote, 0);
|
|
if (res < 0) {
|
|
return res;
|
|
}
|
|
|
|
uint8_t *pktpos = buf;
|
|
pktpos += coap_build_hdr((coap_hdr_t *)pktpos, COAP_REQ, NULL, 0, COAP_METHOD_GET, 1);
|
|
pktpos += coap_put_option_uri(pktpos, 0, path, COAP_OPT_URI_PATH);
|
|
|
|
/* TODO: timeout random between between ACK_TIMEOUT and (ACK_TIMEOUT *
|
|
* ACK_RANDOM_FACTOR) */
|
|
uint32_t timeout = COAP_ACK_TIMEOUT * (1000000U);
|
|
int tries = 0;
|
|
while (tries++ < COAP_MAX_RETRANSMIT) {
|
|
if (!tries) {
|
|
DEBUG("nanocoap: maximum retries reached.\n");
|
|
res = -ETIMEDOUT;
|
|
goto out;
|
|
}
|
|
|
|
res = sock_udp_send(&sock, buf, pktpos - buf, NULL);
|
|
if (res <= 0) {
|
|
DEBUG("nanocoap: error sending coap request\n");
|
|
goto out;
|
|
}
|
|
|
|
res = sock_udp_recv(&sock, buf, len, timeout, NULL);
|
|
if (res <= 0) {
|
|
if (res == -ETIMEDOUT) {
|
|
DEBUG("nanocoap: timeout\n");
|
|
|
|
timeout *= 2;
|
|
continue;
|
|
}
|
|
DEBUG("nanocoap: error receiving coap request\n");
|
|
break;
|
|
}
|
|
|
|
coap_pkt_t pkt;
|
|
if (coap_parse(&pkt, (uint8_t *)buf, res) < 0) {
|
|
puts("error parsing packet");
|
|
continue;
|
|
}
|
|
else {
|
|
res = coap_get_code(&pkt);
|
|
if (res != 205) {
|
|
res = -res;
|
|
}
|
|
else {
|
|
if (pkt.payload_len) {
|
|
memcpy(buf, pkt.payload, pkt.payload_len);
|
|
}
|
|
res = pkt.payload_len;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
out:
|
|
sock_udp_close(&sock);
|
|
|
|
return res;
|
|
}
|
|
|
|
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 == -1) {
|
|
return -1;
|
|
}
|
|
|
|
while (1) {
|
|
res = sock_udp_recv(&sock, buf, bufsize, -1, &remote);
|
|
if (res == -1) {
|
|
DEBUG("error receiving UDP packet\n");
|
|
return -1;
|
|
}
|
|
else {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|