mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Update component/coap to libcoap version release-4.2.0
This takes the code up to the latest released version of libcoap. As there have been API changes, coap_client and coap_server in examples/protocols have been updated to use the new APIs. Further information on the new libcoap APIs can be found at https://libcoap.net/doc/reference/4.2.0/ coap_client has been updated to handle BLOCK2 responses from "coap://californium.eclipse.org" coap_client has been modified to only send out one request (and wait for the response) coap_server has been updated to support Observe subscriptions, and well as adding in PUT and DELETE handlers to work on the Espressif resource coap_server and coap_client have had their stack sizes increased. port/coap_io.c has been added, a copy of libcoap/src/coap_io.c with support added for systems that do not have RFC 3542 section 20 support. port/coap_io_socket.c has been removed as a lot of the code is now replicated in different libcoap files. Once this PR is place, then adding in DTLS will be a lot simpler (as a separate PR) Signed-off-by: Jitin George <jitin@espressif.com> Merges https://github.com/espressif/esp-idf/pull/3148
This commit is contained in:
parent
96aa08a0ff
commit
bc9d1a65d7
@ -1,12 +1,14 @@
|
|||||||
set(COMPONENT_ADD_INCLUDEDIRS port/include port/include/coap libcoap/include libcoap/include/coap)
|
set(COMPONENT_ADD_INCLUDEDIRS port/include port/include/coap libcoap/include libcoap/include/coap2)
|
||||||
|
|
||||||
set(COMPONENT_SRCS "libcoap/src/address.c"
|
set(COMPONENT_SRCS "libcoap/src/address.c"
|
||||||
"libcoap/src/async.c"
|
"libcoap/src/async.c"
|
||||||
"libcoap/src/block.c"
|
"libcoap/src/block.c"
|
||||||
|
"libcoap/src/coap_event.c"
|
||||||
|
"libcoap/src/coap_hashkey.c"
|
||||||
|
"libcoap/src/coap_session.c"
|
||||||
"libcoap/src/coap_time.c"
|
"libcoap/src/coap_time.c"
|
||||||
"libcoap/src/debug.c"
|
"libcoap/src/coap_debug.c"
|
||||||
"libcoap/src/encode.c"
|
"libcoap/src/encode.c"
|
||||||
"libcoap/src/hashkey.c"
|
|
||||||
"libcoap/src/mem.c"
|
"libcoap/src/mem.c"
|
||||||
"libcoap/src/net.c"
|
"libcoap/src/net.c"
|
||||||
"libcoap/src/option.c"
|
"libcoap/src/option.c"
|
||||||
@ -15,7 +17,8 @@ set(COMPONENT_SRCS "libcoap/src/address.c"
|
|||||||
"libcoap/src/str.c"
|
"libcoap/src/str.c"
|
||||||
"libcoap/src/subscribe.c"
|
"libcoap/src/subscribe.c"
|
||||||
"libcoap/src/uri.c"
|
"libcoap/src/uri.c"
|
||||||
"port/coap_io_socket.c")
|
"libcoap/src/coap_notls.c"
|
||||||
|
"port/coap_io.c")
|
||||||
|
|
||||||
set(COMPONENT_REQUIRES lwip)
|
set(COMPONENT_REQUIRES lwip)
|
||||||
|
|
||||||
@ -26,16 +29,3 @@ register_component()
|
|||||||
# TODO: find a way to move this to a port header
|
# TODO: find a way to move this to a port header
|
||||||
target_compile_definitions(${COMPONENT_TARGET} PUBLIC WITH_POSIX)
|
target_compile_definitions(${COMPONENT_TARGET} PUBLIC WITH_POSIX)
|
||||||
|
|
||||||
set_source_files_properties(
|
|
||||||
libcoap/src/debug.c
|
|
||||||
libcoap/src/pdu.c
|
|
||||||
PROPERTIES COMPILE_FLAGS
|
|
||||||
-Wno-write-strings)
|
|
||||||
|
|
||||||
if(GCC_NOT_5_2_0)
|
|
||||||
# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo
|
|
||||||
set_source_files_properties(
|
|
||||||
libcoap/src/option.c
|
|
||||||
PROPERTIES COMPILE_FLAGS
|
|
||||||
-Wno-implicit-fallthrough)
|
|
||||||
endif()
|
|
@ -2,17 +2,11 @@
|
|||||||
# Component Makefile
|
# Component Makefile
|
||||||
#
|
#
|
||||||
|
|
||||||
COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap
|
COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap2
|
||||||
|
|
||||||
COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_time.o libcoap/src/debug.o libcoap/src/encode.o libcoap/src/hashkey.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_io_socket.o
|
COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_session.o libcoap/src/coap_time.o libcoap/src/coap_debug.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o libcoap/src/coap_notls.o port/coap_io.o
|
||||||
|
|
||||||
COMPONENT_SRCDIRS := libcoap/src libcoap port
|
COMPONENT_SRCDIRS := libcoap/src libcoap port
|
||||||
|
|
||||||
COMPONENT_SUBMODULES += libcoap
|
COMPONENT_SUBMODULES += libcoap
|
||||||
|
|
||||||
libcoap/src/debug.o: CFLAGS += -Wno-write-strings
|
|
||||||
libcoap/src/pdu.o: CFLAGS += -Wno-write-strings
|
|
||||||
ifeq ($(GCC_NOT_5_2_0), 1)
|
|
||||||
# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo
|
|
||||||
libcoap/src/option.o: CFLAGS += -Wno-implicit-fallthrough
|
|
||||||
endif
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 6468887a12666f88b8704d797fc176cd4f40ee4c
|
Subproject commit cfec0d072c5b99ed3e54828ca50ea2f6b91e1f50
|
1422
components/coap/port/coap_io.c
Normal file
1422
components/coap/port/coap_io.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,468 +0,0 @@
|
|||||||
/*
|
|
||||||
* Network function implementation with socket for ESP32 platform.
|
|
||||||
*
|
|
||||||
* Uses libcoap software implementation for failover when concurrent
|
|
||||||
* network operations are in use.
|
|
||||||
*
|
|
||||||
* coap_io.h -- Default network I/O functions for libcoap
|
|
||||||
*
|
|
||||||
* Copyright (C) 2012,2014 Olaf Bergmann <bergmann@tzi.org>
|
|
||||||
*
|
|
||||||
* Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
*
|
|
||||||
* This file is part of the CoAP library libcoap. Please see
|
|
||||||
* README for terms of use.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "coap_config.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_STDIO_H
|
|
||||||
# include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
|
||||||
# include <sys/select.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
|
||||||
# include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_NETINET_IN_H
|
|
||||||
# include <netinet/in.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_UIO_H
|
|
||||||
# include <sys/uio.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
# include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#ifdef WITH_CONTIKI
|
|
||||||
# include "uip.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "pdu.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "mem.h"
|
|
||||||
#include "coap_io.h"
|
|
||||||
|
|
||||||
#ifdef WITH_POSIX
|
|
||||||
/* define generic PKTINFO for IPv4 */
|
|
||||||
#if defined(IP_PKTINFO)
|
|
||||||
# define GEN_IP_PKTINFO IP_PKTINFO
|
|
||||||
#elif defined(IP_RECVDSTADDR)
|
|
||||||
# define GEN_IP_PKTINFO IP_RECVDSTADDR
|
|
||||||
#else
|
|
||||||
# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
|
|
||||||
#endif /* IP_PKTINFO */
|
|
||||||
|
|
||||||
/* define generic KTINFO for IPv6 */
|
|
||||||
#ifdef IPV6_RECVPKTINFO
|
|
||||||
# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
|
|
||||||
#elif defined(IPV6_PKTINFO)
|
|
||||||
# define GEN_IPV6_PKTINFO IPV6_PKTINFO
|
|
||||||
#else
|
|
||||||
# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
|
|
||||||
#endif /* IPV6_RECVPKTINFO */
|
|
||||||
|
|
||||||
struct coap_packet_t {
|
|
||||||
coap_if_handle_t hnd; /**< the interface handle */
|
|
||||||
coap_address_t src; /**< the packet's source address */
|
|
||||||
coap_address_t dst; /**< the packet's destination address */
|
|
||||||
const coap_endpoint_t *interface;
|
|
||||||
|
|
||||||
int ifindex;
|
|
||||||
void *session; /**< opaque session data */
|
|
||||||
|
|
||||||
size_t length; /**< length of payload */
|
|
||||||
unsigned char payload[]; /**< payload */
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CUSTOM_COAP_NETWORK_ENDPOINT
|
|
||||||
|
|
||||||
#ifdef WITH_CONTIKI
|
|
||||||
static int ep_initialized = 0;
|
|
||||||
|
|
||||||
static inline struct coap_endpoint_t *
|
|
||||||
coap_malloc_contiki_endpoint() {
|
|
||||||
static struct coap_endpoint_t ep;
|
|
||||||
|
|
||||||
if (ep_initialized) {
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
ep_initialized = 1;
|
|
||||||
return &ep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
coap_free_contiki_endpoint(struct coap_endpoint_t *ep) {
|
|
||||||
ep_initialized = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
coap_endpoint_t *
|
|
||||||
coap_new_endpoint(const coap_address_t *addr, int flags) {
|
|
||||||
struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint();
|
|
||||||
|
|
||||||
if (ep) {
|
|
||||||
memset(ep, 0, sizeof(struct coap_endpoint_t));
|
|
||||||
ep->handle.conn = udp_new(NULL, 0, NULL);
|
|
||||||
|
|
||||||
if (!ep->handle.conn) {
|
|
||||||
coap_free_endpoint(ep);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
coap_address_init(&ep->addr);
|
|
||||||
uip_ipaddr_copy(&ep->addr.addr, &addr->addr);
|
|
||||||
ep->addr.port = addr->port;
|
|
||||||
udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port);
|
|
||||||
}
|
|
||||||
return ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
coap_free_endpoint(coap_endpoint_t *ep) {
|
|
||||||
if (ep) {
|
|
||||||
if (ep->handle.conn) {
|
|
||||||
uip_udp_remove((struct uip_udp_conn *)ep->handle.conn);
|
|
||||||
}
|
|
||||||
coap_free_contiki_endpoint(ep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* WITH_CONTIKI */
|
|
||||||
static inline struct coap_endpoint_t *
|
|
||||||
coap_malloc_posix_endpoint(void) {
|
|
||||||
return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
coap_free_posix_endpoint(struct coap_endpoint_t *ep) {
|
|
||||||
coap_free(ep);
|
|
||||||
}
|
|
||||||
|
|
||||||
coap_endpoint_t *
|
|
||||||
coap_new_endpoint(const coap_address_t *addr, int flags) {
|
|
||||||
int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0);
|
|
||||||
int on = 1;
|
|
||||||
struct coap_endpoint_t *ep;
|
|
||||||
|
|
||||||
if (sockfd < 0) {
|
|
||||||
coap_log(LOG_WARNING, "coap_new_endpoint: socket");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
|
|
||||||
coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR");
|
|
||||||
|
|
||||||
if (bind(sockfd, &addr->addr.sa, addr->size) < 0) {
|
|
||||||
coap_log(LOG_WARNING, "coap_new_endpoint: bind");
|
|
||||||
close (sockfd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ep = coap_malloc_posix_endpoint();
|
|
||||||
if (!ep) {
|
|
||||||
coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
|
|
||||||
close(sockfd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(ep, 0, sizeof(struct coap_endpoint_t));
|
|
||||||
ep->handle.fd = sockfd;
|
|
||||||
ep->flags = flags;
|
|
||||||
|
|
||||||
ep->addr.size = addr->size;
|
|
||||||
if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) {
|
|
||||||
coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address");
|
|
||||||
close (sockfd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (LOG_DEBUG <= coap_get_log_level()) {
|
|
||||||
#ifndef INET6_ADDRSTRLEN
|
|
||||||
#define INET6_ADDRSTRLEN 40
|
|
||||||
#endif
|
|
||||||
unsigned char addr_str[INET6_ADDRSTRLEN+8];
|
|
||||||
|
|
||||||
if (coap_print_addr(&ep->addr, addr_str, INET6_ADDRSTRLEN+8)) {
|
|
||||||
debug("created %sendpoint %s\n",
|
|
||||||
ep->flags & COAP_ENDPOINT_DTLS ? "DTLS " : "",
|
|
||||||
addr_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* NDEBUG */
|
|
||||||
|
|
||||||
return (coap_endpoint_t *)ep;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
coap_free_endpoint(coap_endpoint_t *ep) {
|
|
||||||
if(ep) {
|
|
||||||
if (ep->handle.fd >= 0)
|
|
||||||
close(ep->handle.fd);
|
|
||||||
coap_free_posix_endpoint((struct coap_endpoint_t *)ep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* WITH_CONTIKI */
|
|
||||||
#endif /* CUSTOM_COAP_NETWORK_ENDPOINT */
|
|
||||||
|
|
||||||
#ifdef CUSTOM_COAP_NETWORK_SEND
|
|
||||||
|
|
||||||
#if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H)
|
|
||||||
/* define struct in6_pktinfo and struct in_pktinfo if not available
|
|
||||||
FIXME: check with configure
|
|
||||||
*/
|
|
||||||
struct in6_pktinfo {
|
|
||||||
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
|
|
||||||
unsigned int ipi6_ifindex; /* send/recv interface index */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct in_pktinfo {
|
|
||||||
int ipi_ifindex;
|
|
||||||
struct in_addr ipi_spec_dst;
|
|
||||||
struct in_addr ipi_addr;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(WITH_POSIX) && !defined(SOL_IP)
|
|
||||||
/* Solaris expects level IPPROTO_IP for ancillary data. */
|
|
||||||
#define SOL_IP IPPROTO_IP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#define UNUSED_PARAM __attribute__ ((unused))
|
|
||||||
#else /* not a GCC */
|
|
||||||
#define UNUSED_PARAM
|
|
||||||
#endif /* GCC */
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
coap_network_send(struct coap_context_t *context UNUSED_PARAM,
|
|
||||||
const coap_endpoint_t *local_interface,
|
|
||||||
const coap_address_t *dst,
|
|
||||||
unsigned char *data,
|
|
||||||
size_t datalen) {
|
|
||||||
|
|
||||||
struct coap_endpoint_t *ep =
|
|
||||||
(struct coap_endpoint_t *)local_interface;
|
|
||||||
|
|
||||||
#ifndef WITH_CONTIKI
|
|
||||||
return sendto(ep->handle.fd, data, datalen, 0, (struct sockaddr*)&dst->addr.sa, sizeof(struct sockaddr));
|
|
||||||
#else /* WITH_CONTIKI */
|
|
||||||
/* FIXME: untested */
|
|
||||||
/* FIXME: is there a way to check if send was successful? */
|
|
||||||
uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen,
|
|
||||||
&dst->addr, dst->port);
|
|
||||||
return datalen;
|
|
||||||
#endif /* WITH_CONTIKI */
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CUSTOM_COAP_NETWORK_SEND */
|
|
||||||
|
|
||||||
#ifdef CUSTOM_COAP_NETWORK_READ
|
|
||||||
|
|
||||||
#define SIN6(A) ((struct sockaddr_in6 *)(A))
|
|
||||||
|
|
||||||
#ifdef WITH_POSIX
|
|
||||||
static coap_packet_t *
|
|
||||||
coap_malloc_packet(void) {
|
|
||||||
coap_packet_t *packet;
|
|
||||||
const size_t need = sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE;
|
|
||||||
|
|
||||||
packet = (coap_packet_t *)coap_malloc(need);
|
|
||||||
if (packet) {
|
|
||||||
memset(packet, 0, need);
|
|
||||||
}
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
coap_free_packet(coap_packet_t *packet) {
|
|
||||||
coap_free(packet);
|
|
||||||
}
|
|
||||||
#endif /* WITH_POSIX */
|
|
||||||
#ifdef WITH_CONTIKI
|
|
||||||
static inline coap_packet_t *
|
|
||||||
coap_malloc_packet(void) {
|
|
||||||
return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
coap_free_packet(coap_packet_t *packet) {
|
|
||||||
coap_free_type(COAP_PACKET, packet);
|
|
||||||
}
|
|
||||||
#endif /* WITH_CONTIKI */
|
|
||||||
|
|
||||||
static inline size_t
|
|
||||||
coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) {
|
|
||||||
return COAP_MAX_PDU_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target)
|
|
||||||
{
|
|
||||||
target->handle = packet->interface->handle;
|
|
||||||
memcpy(&target->addr, &packet->dst, sizeof(target->addr));
|
|
||||||
target->ifindex = packet->ifindex;
|
|
||||||
target->flags = 0; /* FIXME */
|
|
||||||
}
|
|
||||||
void
|
|
||||||
coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target)
|
|
||||||
{
|
|
||||||
memcpy(target, &packet->src, sizeof(coap_address_t));
|
|
||||||
}
|
|
||||||
void
|
|
||||||
coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
|
|
||||||
{
|
|
||||||
*address = packet->payload;
|
|
||||||
*length = packet->length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a message with destination address @p dst matches the
|
|
||||||
* local interface with address @p local. This function returns @c 1
|
|
||||||
* if @p dst is a valid match, and @c 0 otherwise.
|
|
||||||
*/
|
|
||||||
static inline int
|
|
||||||
is_local_if(const coap_address_t *local, const coap_address_t *dst) {
|
|
||||||
return coap_address_isany(local) || coap_address_equals(dst, local) ||
|
|
||||||
coap_is_mcast(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t
|
|
||||||
coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) {
|
|
||||||
ssize_t len = -1;
|
|
||||||
|
|
||||||
#ifdef WITH_POSIX
|
|
||||||
#define SOC_APPDATA_LEN 1460
|
|
||||||
char *soc_appdata = NULL;
|
|
||||||
struct sockaddr_in soc_srcipaddr;
|
|
||||||
socklen_t soc_srcsize = sizeof(struct sockaddr_in);
|
|
||||||
#endif /* WITH_POSIX */
|
|
||||||
|
|
||||||
assert(ep);
|
|
||||||
assert(packet);
|
|
||||||
|
|
||||||
*packet = coap_malloc_packet();
|
|
||||||
|
|
||||||
if (!*packet) {
|
|
||||||
warn("coap_network_read: insufficient memory, drop packet\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
coap_address_init(&(*packet)->dst); /* the local interface address */
|
|
||||||
coap_address_init(&(*packet)->src); /* the remote peer */
|
|
||||||
|
|
||||||
#ifdef WITH_POSIX
|
|
||||||
soc_appdata = coap_malloc(SOC_APPDATA_LEN);
|
|
||||||
if (soc_appdata){
|
|
||||||
len = recvfrom(ep->handle.fd, soc_appdata, SOC_APPDATA_LEN, 0, (struct sockaddr *)&soc_srcipaddr, (socklen_t *)&soc_srcsize);
|
|
||||||
|
|
||||||
if (len < 0){
|
|
||||||
coap_log(LOG_WARNING, "coap_network_read: %s\n", strerror(errno));
|
|
||||||
goto error;
|
|
||||||
} else {
|
|
||||||
/* use getsockname() to get the local port */
|
|
||||||
(*packet)->dst.size = sizeof((*packet)->dst.addr);
|
|
||||||
if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) {
|
|
||||||
coap_log(LOG_DEBUG, "cannot determine local port\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* local interface for IPv4 */
|
|
||||||
(*packet)->src.size = sizeof((*packet)->src.addr.sa);
|
|
||||||
memcpy(&((*packet)->src.addr.sa), &soc_srcipaddr, (*packet)->src.size);
|
|
||||||
|
|
||||||
if (len > coap_get_max_packetlength(*packet)) {
|
|
||||||
/* FIXME: we might want to send back a response */
|
|
||||||
warn("discarded oversized packet\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
|
|
||||||
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
|
|
||||||
printf("error 3\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*packet)->length = len;
|
|
||||||
|
|
||||||
memcpy(&(*packet)->payload, soc_appdata, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
coap_free(soc_appdata);
|
|
||||||
soc_appdata = NULL;
|
|
||||||
} else {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
#endif /* WITH_POSIX */
|
|
||||||
#ifdef WITH_CONTIKI
|
|
||||||
/* FIXME: untested, make this work */
|
|
||||||
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
|
||||||
#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
|
|
||||||
|
|
||||||
if(uip_newdata()) {
|
|
||||||
uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr);
|
|
||||||
(*packet)->src.port = UIP_UDP_BUF->srcport;
|
|
||||||
uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr);
|
|
||||||
(*packet)->dst.port = UIP_UDP_BUF->destport;
|
|
||||||
|
|
||||||
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
|
|
||||||
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = uip_datalen();
|
|
||||||
|
|
||||||
if (len > coap_get_max_packetlength(*packet)) {
|
|
||||||
/* FIXME: we might want to send back a response */
|
|
||||||
warn("discarded oversized packet\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
((char *)uip_appdata)[len] = 0;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (LOG_DEBUG <= coap_get_log_level()) {
|
|
||||||
#ifndef INET6_ADDRSTRLEN
|
|
||||||
#define INET6_ADDRSTRLEN 40
|
|
||||||
#endif
|
|
||||||
unsigned char addr_str[INET6_ADDRSTRLEN+8];
|
|
||||||
|
|
||||||
if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) {
|
|
||||||
debug("received %zd bytes from %s\n", len, addr_str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* NDEBUG */
|
|
||||||
|
|
||||||
(*packet)->length = len;
|
|
||||||
memcpy(&(*packet)->payload, uip_appdata, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef UIP_IP_BUF
|
|
||||||
#undef UIP_UDP_BUF
|
|
||||||
#endif /* WITH_CONTIKI */
|
|
||||||
#ifdef WITH_LWIP
|
|
||||||
#error "coap_network_read() not implemented on this platform"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
(*packet)->interface = ep;
|
|
||||||
|
|
||||||
return len;
|
|
||||||
error:
|
|
||||||
#ifdef WITH_POSIX
|
|
||||||
if (soc_appdata)
|
|
||||||
coap_free(soc_appdata);
|
|
||||||
soc_appdata = NULL;
|
|
||||||
#endif
|
|
||||||
coap_free_packet(*packet);
|
|
||||||
*packet = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef SIN6
|
|
||||||
|
|
||||||
#endif /* CUSTOM_COAP_NETWORK_READ */
|
|
@ -17,19 +17,21 @@
|
|||||||
#ifndef _COAP_H_
|
#ifndef _COAP_H_
|
||||||
#define _COAP_H_
|
#define _COAP_H_
|
||||||
|
|
||||||
#include "libcoap.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "libcoap.h"
|
||||||
|
|
||||||
#include "address.h"
|
#include "address.h"
|
||||||
#include "async.h"
|
#include "async.h"
|
||||||
#include "bits.h"
|
#include "bits.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
#include "coap_dtls.h"
|
||||||
|
#include "coap_event.h"
|
||||||
#include "coap_io.h"
|
#include "coap_io.h"
|
||||||
#include "coap_time.h"
|
#include "coap_time.h"
|
||||||
#include "debug.h"
|
#include "coap_debug.h"
|
||||||
#include "encode.h"
|
#include "encode.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
@ -40,8 +42,6 @@ extern "C" {
|
|||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "subscribe.h"
|
#include "subscribe.h"
|
||||||
#include "uri.h"
|
#include "uri.h"
|
||||||
#include "uthash.h"
|
|
||||||
#include "utlist.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#define HAVE_SYS_SOCKET_H
|
#define HAVE_SYS_SOCKET_H
|
||||||
#define HAVE_MALLOC
|
#define HAVE_MALLOC
|
||||||
#define HAVE_ARPA_INET_H
|
#define HAVE_ARPA_INET_H
|
||||||
|
#define HAVE_TIME_H
|
||||||
|
|
||||||
#define IP_PKTINFO IP_MULTICAST_IF
|
#define IP_PKTINFO IP_MULTICAST_IF
|
||||||
#define IPV6_PKTINFO IPV6_V6ONLY
|
#define IPV6_PKTINFO IPV6_V6ONLY
|
||||||
@ -32,10 +33,7 @@
|
|||||||
#define PACKAGE_NAME "libcoap-posix"
|
#define PACKAGE_NAME "libcoap-posix"
|
||||||
#define PACKAGE_VERSION "?"
|
#define PACKAGE_VERSION "?"
|
||||||
|
|
||||||
#define CUSTOM_COAP_NETWORK_ENDPOINT
|
#define COAP_BAD_RECVMSG
|
||||||
#define CUSTOM_COAP_NETWORK_SEND
|
|
||||||
#define CUSTOM_COAP_NETWORK_READ
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#endif /* WITH_POSIX */
|
||||||
#endif /* COAP_CONFIG_POSIX_H_ */
|
#endif /* COAP_CONFIG_POSIX_H_ */
|
||||||
|
@ -37,7 +37,8 @@ make -j4 flash monitor
|
|||||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||||
|
|
||||||
## Example Output
|
## Example Output
|
||||||
Prerequisite: we startup a CoAP server on coap server example.
|
Prerequisite: we startup a CoAP server on coap server example,
|
||||||
|
or use the default of coap://californium.eclipse.org.
|
||||||
|
|
||||||
and you could receive data from CoAP server if succeed,
|
and you could receive data from CoAP server if succeed,
|
||||||
such as the following log:
|
such as the following log:
|
||||||
@ -54,12 +55,26 @@ I (1692) wifi: pm start, type: 1
|
|||||||
|
|
||||||
I (2582) event: sta ip: 192.168.3.89, mask: 255.255.255.0, gw: 192.168.3.1
|
I (2582) event: sta ip: 192.168.3.89, mask: 255.255.255.0, gw: 192.168.3.1
|
||||||
I (2582) CoAP_client: Connected to AP
|
I (2582) CoAP_client: Connected to AP
|
||||||
I (2582) CoAP_client: DNS lookup succeeded. IP=192.168.3.84
|
I (2582) CoAP_client: DNS lookup succeeded. IP=104.196.15.150
|
||||||
Received: Hello World!
|
Received:
|
||||||
E (8102) CoAP_client: select timeout
|
************************************************************
|
||||||
E (13102) CoAP_client: select timeout
|
CoAP RFC 7252 Cf 2.0.0-SNAPSHOT
|
||||||
|
************************************************************
|
||||||
|
This server is using the Eclipse Californium (Cf) CoAP framework
|
||||||
|
published under EPL+EDL: http://www.eclipse.org/californium/
|
||||||
|
|
||||||
|
(c) 2014, 2015, 2016 Institute for Pervasive Computing, ETH Zurich and others
|
||||||
|
************************************************************
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## libcoap Documentation
|
||||||
|
This can be found at https://libcoap.net/doc/reference/4.2.0/
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
* Please make sure Target Url includes valid `host`, `port`, `path`, and begins with `coap://`
|
* Please make sure Target Url includes valid `host`, optional `port`, optional `path`, and begins
|
||||||
|
with `coap://` or `coap+tcp://` for a coap server that supports TCP
|
||||||
|
(not all do including coap+tcp://californium.eclipse.org).
|
||||||
|
|
||||||
|
* libcoap logging can be increased by changing `#define COAP_LOGGING_LEVEL 0`
|
||||||
|
to `#define COAP_LOGGING_LEVEL 9`
|
||||||
|
@ -33,7 +33,9 @@
|
|||||||
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
|
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
|
||||||
|
|
||||||
#define COAP_DEFAULT_TIME_SEC 5
|
#define COAP_DEFAULT_TIME_SEC 5
|
||||||
#define COAP_DEFAULT_TIME_USEC 0
|
|
||||||
|
/* Set this to 9 to get verbose logging from within libcoap */
|
||||||
|
#define COAP_LOGGING_LEVEL 0
|
||||||
|
|
||||||
/* The examples use uri "coap://californium.eclipse.org" that
|
/* The examples use uri "coap://californium.eclipse.org" that
|
||||||
you can set via 'make menuconfig'.
|
you can set via 'make menuconfig'.
|
||||||
@ -52,17 +54,88 @@ const static int CONNECTED_BIT = BIT0;
|
|||||||
|
|
||||||
const static char *TAG = "CoAP_client";
|
const static char *TAG = "CoAP_client";
|
||||||
|
|
||||||
static void message_handler(struct coap_context_t *ctx, const coap_endpoint_t *local_interface, const coap_address_t *remote,
|
static int resp_wait = 1;
|
||||||
|
static coap_optlist_t *optlist = NULL;
|
||||||
|
static int wait_ms;
|
||||||
|
|
||||||
|
static void message_handler(coap_context_t *ctx, coap_session_t *session,
|
||||||
coap_pdu_t *sent, coap_pdu_t *received,
|
coap_pdu_t *sent, coap_pdu_t *received,
|
||||||
const coap_tid_t id)
|
const coap_tid_t id)
|
||||||
{
|
{
|
||||||
unsigned char* data = NULL;
|
unsigned char* data = NULL;
|
||||||
size_t data_len;
|
size_t data_len;
|
||||||
if (COAP_RESPONSE_CLASS(received->hdr->code) == 2) {
|
coap_pdu_t *pdu = NULL;
|
||||||
|
coap_opt_t *block_opt;
|
||||||
|
coap_opt_iterator_t opt_iter;
|
||||||
|
unsigned char buf[4];
|
||||||
|
coap_optlist_t *option;
|
||||||
|
coap_tid_t tid;
|
||||||
|
|
||||||
|
if (COAP_RESPONSE_CLASS(received->code) == 2) {
|
||||||
|
/* Need to see if blocked response */
|
||||||
|
block_opt = coap_check_option(received, COAP_OPTION_BLOCK2, &opt_iter);
|
||||||
|
if (block_opt) {
|
||||||
|
uint16_t blktype = opt_iter.type;
|
||||||
|
|
||||||
|
if (coap_opt_block_num(block_opt) == 0) {
|
||||||
|
printf("Received:\n");
|
||||||
|
}
|
||||||
if (coap_get_data(received, &data_len, &data)) {
|
if (coap_get_data(received, &data_len, &data)) {
|
||||||
printf("Received: %s\n", data);
|
printf("%.*s", (int)data_len, data);
|
||||||
|
}
|
||||||
|
if (COAP_OPT_BLOCK_MORE(block_opt)) {
|
||||||
|
/* more bit is set */
|
||||||
|
|
||||||
|
/* create pdu with request for next block */
|
||||||
|
pdu = coap_new_pdu(session);
|
||||||
|
if (!pdu) {
|
||||||
|
ESP_LOGE(TAG, "coap_new_pdu() failed");
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
pdu->type = COAP_MESSAGE_CON;
|
||||||
|
pdu->tid = coap_new_message_id(session);
|
||||||
|
pdu->code = COAP_REQUEST_GET;
|
||||||
|
|
||||||
|
/* add URI components from optlist */
|
||||||
|
for (option = optlist; option; option = option->next ) {
|
||||||
|
switch (option->number) {
|
||||||
|
case COAP_OPTION_URI_HOST :
|
||||||
|
case COAP_OPTION_URI_PORT :
|
||||||
|
case COAP_OPTION_URI_PATH :
|
||||||
|
case COAP_OPTION_URI_QUERY :
|
||||||
|
coap_add_option(pdu, option->number, option->length,
|
||||||
|
option->data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
; /* skip other options */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* finally add updated block option from response, clear M bit */
|
||||||
|
/* blocknr = (blocknr & 0xfffffff7) + 0x10; */
|
||||||
|
coap_add_option(pdu,
|
||||||
|
blktype,
|
||||||
|
coap_encode_var_safe(buf, sizeof(buf),
|
||||||
|
((coap_opt_block_num(block_opt) + 1) << 4) |
|
||||||
|
COAP_OPT_BLOCK_SZX(block_opt)), buf);
|
||||||
|
|
||||||
|
tid = coap_send(session, pdu);
|
||||||
|
|
||||||
|
if (tid != COAP_INVALID_TID) {
|
||||||
|
resp_wait = 1;
|
||||||
|
wait_ms = COAP_DEFAULT_TIME_SEC * 1000;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
} else {
|
||||||
|
if (coap_get_data(received, &data_len, &data)) {
|
||||||
|
printf("Received: %.*s\n", (int)data_len, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clean_up:
|
||||||
|
resp_wait = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void coap_example_task(void *p)
|
static void coap_example_task(void *p)
|
||||||
@ -70,17 +143,22 @@ static void coap_example_task(void *p)
|
|||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
struct ip4_addr *ip4_addr;
|
struct ip4_addr *ip4_addr;
|
||||||
|
|
||||||
coap_context_t* ctx = NULL;
|
|
||||||
coap_address_t dst_addr, src_addr;
|
coap_address_t dst_addr, src_addr;
|
||||||
static coap_uri_t uri;
|
static coap_uri_t uri;
|
||||||
fd_set readfds;
|
|
||||||
struct timeval tv;
|
|
||||||
int flags, result;
|
|
||||||
coap_pdu_t* request = NULL;
|
|
||||||
const char* server_uri = COAP_DEFAULT_DEMO_URI;
|
const char* server_uri = COAP_DEFAULT_DEMO_URI;
|
||||||
uint8_t get_method = 1;
|
|
||||||
char* phostname = NULL;
|
char* phostname = NULL;
|
||||||
|
|
||||||
|
coap_set_log_level(COAP_LOGGING_LEVEL);
|
||||||
while (1) {
|
while (1) {
|
||||||
|
#define BUFSIZE 40
|
||||||
|
unsigned char _buf[BUFSIZE];
|
||||||
|
unsigned char *buf;
|
||||||
|
size_t buflen;
|
||||||
|
int res;
|
||||||
|
coap_context_t *ctx = NULL;
|
||||||
|
coap_session_t *session = NULL;
|
||||||
|
coap_pdu_t *request = NULL;
|
||||||
|
|
||||||
/* Wait for the callback to set the CONNECTED_BIT in the
|
/* Wait for the callback to set the CONNECTED_BIT in the
|
||||||
event group.
|
event group.
|
||||||
*/
|
*/
|
||||||
@ -88,11 +166,18 @@ static void coap_example_task(void *p)
|
|||||||
false, true, portMAX_DELAY);
|
false, true, portMAX_DELAY);
|
||||||
ESP_LOGI(TAG, "Connected to AP");
|
ESP_LOGI(TAG, "Connected to AP");
|
||||||
|
|
||||||
|
optlist = NULL;
|
||||||
if (coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri) == -1) {
|
if (coap_split_uri((const uint8_t *)server_uri, strlen(server_uri), &uri) == -1) {
|
||||||
ESP_LOGE(TAG, "CoAP server uri error");
|
ESP_LOGE(TAG, "CoAP server uri error");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((uri.scheme==COAP_URI_SCHEME_COAPS && !coap_dtls_is_supported()) ||
|
||||||
|
(uri.scheme==COAP_URI_SCHEME_COAPS_TCP && !coap_tls_is_supported())) {
|
||||||
|
ESP_LOGE(TAG, "CoAP server uri scheme error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
phostname = (char *)calloc(1, uri.host.length + 1);
|
phostname = (char *)calloc(1, uri.host.length + 1);
|
||||||
|
|
||||||
if (phostname == NULL) {
|
if (phostname == NULL) {
|
||||||
@ -107,6 +192,7 @@ static void coap_example_task(void *p)
|
|||||||
if (hp == NULL) {
|
if (hp == NULL) {
|
||||||
ESP_LOGE(TAG, "DNS lookup failed");
|
ESP_LOGE(TAG, "DNS lookup failed");
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
free(phostname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,46 +207,94 @@ static void coap_example_task(void *p)
|
|||||||
src_addr.addr.sin.sin_port = htons(0);
|
src_addr.addr.sin.sin_port = htons(0);
|
||||||
src_addr.addr.sin.sin_addr.s_addr = INADDR_ANY;
|
src_addr.addr.sin.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
ctx = coap_new_context(&src_addr);
|
if (uri.path.length) {
|
||||||
if (ctx) {
|
buflen = BUFSIZE;
|
||||||
|
buf = _buf;
|
||||||
|
res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
|
||||||
|
|
||||||
|
while (res--) {
|
||||||
|
coap_insert_optlist(&optlist,
|
||||||
|
coap_new_optlist(COAP_OPTION_URI_PATH,
|
||||||
|
coap_opt_length(buf),
|
||||||
|
coap_opt_value(buf)));
|
||||||
|
|
||||||
|
buf += coap_opt_size(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri.query.length) {
|
||||||
|
buflen = BUFSIZE;
|
||||||
|
buf = _buf;
|
||||||
|
res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
|
||||||
|
|
||||||
|
while (res--) {
|
||||||
|
coap_insert_optlist(&optlist,
|
||||||
|
coap_new_optlist(COAP_OPTION_URI_QUERY,
|
||||||
|
coap_opt_length(buf),
|
||||||
|
coap_opt_value(buf)));
|
||||||
|
|
||||||
|
buf += coap_opt_size(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = coap_new_context(NULL);
|
||||||
|
if (!ctx) {
|
||||||
|
ESP_LOGE(TAG, "coap_new_context() failed");
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
coap_address_init(&dst_addr);
|
coap_address_init(&dst_addr);
|
||||||
dst_addr.addr.sin.sin_family = AF_INET;
|
dst_addr.addr.sin.sin_family = AF_INET;
|
||||||
dst_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT);
|
dst_addr.addr.sin.sin_port = htons(uri.port);
|
||||||
dst_addr.addr.sin.sin_addr.s_addr = ip4_addr->addr;
|
dst_addr.addr.sin.sin_addr.s_addr = ip4_addr->addr;
|
||||||
|
|
||||||
request = coap_new_pdu();
|
session = coap_new_client_session(ctx, &src_addr, &dst_addr,
|
||||||
if (request){
|
uri.scheme==COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP :
|
||||||
request->hdr->type = COAP_MESSAGE_CON;
|
uri.scheme==COAP_URI_SCHEME_COAPS_TCP ? COAP_PROTO_TLS :
|
||||||
request->hdr->id = coap_new_message_id(ctx);
|
uri.scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_UDP);
|
||||||
request->hdr->code = get_method;
|
if (!session) {
|
||||||
coap_add_option(request, COAP_OPTION_URI_PATH, uri.path.length, uri.path.s);
|
ESP_LOGE(TAG, "coap_new_client_session() failed");
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
|
||||||
coap_register_response_handler(ctx, message_handler);
|
coap_register_response_handler(ctx, message_handler);
|
||||||
coap_send_confirmed(ctx, ctx->endpoint, &dst_addr, request);
|
|
||||||
|
|
||||||
flags = fcntl(ctx->sockfd, F_GETFL, 0);
|
request = coap_new_pdu(session);
|
||||||
fcntl(ctx->sockfd, F_SETFL, flags|O_NONBLOCK);
|
if (!request) {
|
||||||
|
ESP_LOGE(TAG, "coap_new_pdu() failed");
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
request->type = COAP_MESSAGE_CON;
|
||||||
|
request->tid = coap_new_message_id(session);
|
||||||
|
request->code = COAP_REQUEST_GET;
|
||||||
|
coap_add_optlist_pdu(request, &optlist);
|
||||||
|
|
||||||
tv.tv_usec = COAP_DEFAULT_TIME_USEC;
|
resp_wait = 1;
|
||||||
tv.tv_sec = COAP_DEFAULT_TIME_SEC;
|
coap_send(session, request);
|
||||||
|
|
||||||
for(;;) {
|
wait_ms = COAP_DEFAULT_TIME_SEC * 1000;
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_CLR( ctx->sockfd, &readfds );
|
while (resp_wait) {
|
||||||
FD_SET( ctx->sockfd, &readfds );
|
int result = coap_run_once(ctx, wait_ms > 1000 ? 1000 : wait_ms);
|
||||||
result = select( ctx->sockfd+1, &readfds, 0, 0, &tv );
|
if (result >= 0) {
|
||||||
if (result > 0) {
|
if (result >= wait_ms) {
|
||||||
if (FD_ISSET( ctx->sockfd, &readfds ))
|
ESP_LOGE(TAG, "select timeout");
|
||||||
coap_read(ctx);
|
|
||||||
} else if (result < 0) {
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "select timeout");
|
wait_ms -= result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
coap_free_context(ctx);
|
clean_up:
|
||||||
|
if (optlist) {
|
||||||
|
coap_delete_optlist(optlist);
|
||||||
|
optlist = NULL;
|
||||||
}
|
}
|
||||||
|
if (session) coap_session_release(session);
|
||||||
|
if (ctx) coap_free_context(ctx);
|
||||||
|
coap_cleanup();
|
||||||
|
/* Only send the request off once */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
@ -210,5 +344,5 @@ void app_main(void)
|
|||||||
{
|
{
|
||||||
ESP_ERROR_CHECK( nvs_flash_init() );
|
ESP_ERROR_CHECK( nvs_flash_init() );
|
||||||
wifi_conn_init();
|
wifi_conn_init();
|
||||||
xTaskCreate(coap_example_task, "coap", 2048, NULL, 5, NULL);
|
xTaskCreate(coap_example_task, "coap", 10240, NULL, 5, NULL);
|
||||||
}
|
}
|
||||||
|
@ -51,13 +51,18 @@ I (1692) wifi: pm start, type: 1
|
|||||||
|
|
||||||
I (2622) event: sta ip: 192.168.3.84, mask: 255.255.255.0, gw: 192.168.3.1
|
I (2622) event: sta ip: 192.168.3.84, mask: 255.255.255.0, gw: 192.168.3.1
|
||||||
I (2622) CoAP_server: Connected to AP
|
I (2622) CoAP_server: Connected to AP
|
||||||
E (7622) CoAP_server: select timeout
|
|
||||||
E (12622) CoAP_server: select timeout
|
|
||||||
E (17622) CoAP_server: select timeout
|
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
if a CoAP client query `/Espressif` resource, CoAP server would return `"Hello World!"`
|
if a CoAP client query `/Espressif` resource, CoAP server would return `"no data"`
|
||||||
|
until a CoAP client does a PUT with some data.
|
||||||
|
|
||||||
|
## libcoap Documentation
|
||||||
|
This can be found at https://libcoap.net/doc/reference/4.2.0/
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
* Please make sure CoAP client fetchs data under path: `/Espressif`
|
* Please make sure CoAP client fetchs or puts data under path: `/Espressif` or
|
||||||
|
fetches `/.well-known/core`
|
||||||
|
|
||||||
|
* libcoap logging can be increased by changing `#define COAP_LOGGING_LEVEL 0`
|
||||||
|
to `#define COAP_LOGGING_LEVEL 9`
|
||||||
|
@ -31,8 +31,8 @@
|
|||||||
#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
|
#define EXAMPLE_WIFI_SSID CONFIG_WIFI_SSID
|
||||||
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
|
#define EXAMPLE_WIFI_PASS CONFIG_WIFI_PASSWORD
|
||||||
|
|
||||||
#define COAP_DEFAULT_TIME_SEC 5
|
/* Set this to 9 to get verbose logging from within libcoap */
|
||||||
#define COAP_DEFAULT_TIME_USEC 0
|
#define COAP_LOGGING_LEVEL 0
|
||||||
|
|
||||||
static EventGroupHandle_t wifi_event_group;
|
static EventGroupHandle_t wifi_event_group;
|
||||||
|
|
||||||
@ -42,53 +42,86 @@ static EventGroupHandle_t wifi_event_group;
|
|||||||
const static int CONNECTED_BIT = BIT0;
|
const static int CONNECTED_BIT = BIT0;
|
||||||
|
|
||||||
const static char *TAG = "CoAP_server";
|
const static char *TAG = "CoAP_server";
|
||||||
|
static char espressif_data[100];
|
||||||
static coap_async_state_t *async = NULL;
|
static int espressif_data_len = 0;
|
||||||
|
|
||||||
static void
|
|
||||||
send_async_response(coap_context_t *ctx, const coap_endpoint_t *local_if)
|
|
||||||
{
|
|
||||||
coap_pdu_t *response;
|
|
||||||
unsigned char buf[3];
|
|
||||||
const char* response_data = "Hello World!";
|
|
||||||
response = coap_pdu_init(async->flags & COAP_MESSAGE_CON, COAP_RESPONSE_CODE(205), 0, COAP_MAX_PDU_SIZE);
|
|
||||||
response->hdr->id = coap_new_message_id(ctx);
|
|
||||||
if (async->tokenlen)
|
|
||||||
coap_add_token(response, async->tokenlen, async->token);
|
|
||||||
coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
|
|
||||||
coap_add_data (response, strlen(response_data), (unsigned char *)response_data);
|
|
||||||
|
|
||||||
if (coap_send(ctx, local_if, &async->peer, response) == COAP_INVALID_TID) {
|
|
||||||
|
|
||||||
}
|
|
||||||
coap_delete_pdu(response);
|
|
||||||
coap_async_state_t *tmp;
|
|
||||||
coap_remove_async(ctx, async->id, &tmp);
|
|
||||||
coap_free_async(async);
|
|
||||||
async = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The resource handler
|
* The resource handler
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
async_handler(coap_context_t *ctx, struct coap_resource_t *resource,
|
hnd_espressif_get(coap_context_t *ctx, coap_resource_t *resource,
|
||||||
const coap_endpoint_t *local_interface, coap_address_t *peer,
|
coap_session_t *session,
|
||||||
coap_pdu_t *request, str *token, coap_pdu_t *response)
|
coap_pdu_t *request, coap_binary_t *token,
|
||||||
|
coap_string_t *query, coap_pdu_t *response)
|
||||||
{
|
{
|
||||||
async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM, (void*)"no data");
|
coap_add_data_blocked_response(resource, session, request, response, token,
|
||||||
|
COAP_MEDIATYPE_TEXT_PLAIN, 0,
|
||||||
|
(size_t)espressif_data_len,
|
||||||
|
(const u_char *)espressif_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hnd_espressif_put(coap_context_t *ctx,
|
||||||
|
coap_resource_t *resource,
|
||||||
|
coap_session_t *session,
|
||||||
|
coap_pdu_t *request,
|
||||||
|
coap_binary_t *token,
|
||||||
|
coap_string_t *query,
|
||||||
|
coap_pdu_t *response)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
|
coap_resource_notify_observers(resource, NULL);
|
||||||
|
|
||||||
|
if (strcmp (espressif_data, "no data") == 0) {
|
||||||
|
response->code = COAP_RESPONSE_CODE(201);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
response->code = COAP_RESPONSE_CODE(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* coap_get_data() sets size to 0 on error */
|
||||||
|
(void)coap_get_data(request, &size, &data);
|
||||||
|
|
||||||
|
if (size == 0) { /* re-init */
|
||||||
|
snprintf(espressif_data, sizeof(espressif_data), "no data");
|
||||||
|
espressif_data_len = strlen(espressif_data);
|
||||||
|
} else {
|
||||||
|
espressif_data_len = size > sizeof (espressif_data) ? sizeof (espressif_data) : size;
|
||||||
|
memcpy (espressif_data, data, espressif_data_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hnd_espressif_delete(coap_context_t *ctx,
|
||||||
|
coap_resource_t *resource,
|
||||||
|
coap_session_t *session,
|
||||||
|
coap_pdu_t *request,
|
||||||
|
coap_binary_t *token,
|
||||||
|
coap_string_t *query,
|
||||||
|
coap_pdu_t *response)
|
||||||
|
{
|
||||||
|
coap_resource_notify_observers(resource, NULL);
|
||||||
|
snprintf(espressif_data, sizeof(espressif_data), "no data");
|
||||||
|
espressif_data_len = strlen(espressif_data);
|
||||||
|
response->code = COAP_RESPONSE_CODE(202);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void coap_example_thread(void *p)
|
static void coap_example_thread(void *p)
|
||||||
{
|
{
|
||||||
coap_context_t* ctx = NULL;
|
coap_context_t *ctx = NULL;
|
||||||
coap_address_t serv_addr;
|
coap_address_t serv_addr;
|
||||||
coap_resource_t* resource = NULL;
|
coap_resource_t *resource = NULL;
|
||||||
fd_set readfds;
|
|
||||||
struct timeval tv;
|
|
||||||
int flags = 0;
|
|
||||||
|
|
||||||
|
snprintf(espressif_data, sizeof(espressif_data), "no data");
|
||||||
|
espressif_data_len = strlen(espressif_data);
|
||||||
|
coap_set_log_level(COAP_LOGGING_LEVEL);
|
||||||
while (1) {
|
while (1) {
|
||||||
|
coap_endpoint_t *ep_udp = NULL;
|
||||||
|
coap_endpoint_t *ep_tcp = NULL;
|
||||||
|
unsigned wait_ms;
|
||||||
|
|
||||||
/* Wait for the callback to set the CONNECTED_BIT in the
|
/* Wait for the callback to set the CONNECTED_BIT in the
|
||||||
event group.
|
event group.
|
||||||
*/
|
*/
|
||||||
@ -101,43 +134,49 @@ static void coap_example_thread(void *p)
|
|||||||
serv_addr.addr.sin.sin_family = AF_INET;
|
serv_addr.addr.sin.sin_family = AF_INET;
|
||||||
serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY;
|
serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY;
|
||||||
serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT);
|
serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT);
|
||||||
ctx = coap_new_context(&serv_addr);
|
|
||||||
if (ctx) {
|
|
||||||
flags = fcntl(ctx->sockfd, F_GETFL, 0);
|
|
||||||
fcntl(ctx->sockfd, F_SETFL, flags|O_NONBLOCK);
|
|
||||||
|
|
||||||
tv.tv_usec = COAP_DEFAULT_TIME_USEC;
|
ctx = coap_new_context(NULL);
|
||||||
tv.tv_sec = COAP_DEFAULT_TIME_SEC;
|
if (!ctx) {
|
||||||
/* Initialize the resource */
|
continue;
|
||||||
resource = coap_resource_init((unsigned char *)"Espressif", 9, 0);
|
}
|
||||||
if (resource){
|
ep_udp = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_UDP);
|
||||||
coap_register_handler(resource, COAP_REQUEST_GET, async_handler);
|
if (!ep_udp) {
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
ep_tcp = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_TCP);
|
||||||
|
if (!ep_tcp) {
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
resource = coap_resource_init(coap_make_str_const("Espressif"), 0);
|
||||||
|
if (!resource) {
|
||||||
|
goto clean_up;
|
||||||
|
}
|
||||||
|
coap_register_handler(resource, COAP_REQUEST_GET, hnd_espressif_get);
|
||||||
|
coap_register_handler(resource, COAP_REQUEST_PUT, hnd_espressif_put);
|
||||||
|
coap_register_handler(resource, COAP_REQUEST_DELETE, hnd_espressif_delete);
|
||||||
|
/* We possibly want to Observe the GETs */
|
||||||
|
coap_resource_set_get_observable(resource, 1);
|
||||||
coap_add_resource(ctx, resource);
|
coap_add_resource(ctx, resource);
|
||||||
/*For incoming connections*/
|
|
||||||
for (;;) {
|
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_CLR( ctx->sockfd, &readfds);
|
|
||||||
FD_SET( ctx->sockfd, &readfds);
|
|
||||||
|
|
||||||
int result = select( ctx->sockfd+1, &readfds, 0, 0, &tv );
|
wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
|
||||||
if (result > 0){
|
|
||||||
if (FD_ISSET( ctx->sockfd, &readfds ))
|
while (1) {
|
||||||
coap_read(ctx);
|
int result = coap_run_once(ctx, wait_ms);
|
||||||
} else if (result < 0){
|
if (result < 0) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else if (result && (unsigned)result < wait_ms) {
|
||||||
ESP_LOGE(TAG, "select timeout");
|
/* decrement if there is a result wait time returned */
|
||||||
|
wait_ms -= result;
|
||||||
}
|
}
|
||||||
|
if (result) {
|
||||||
if (async) {
|
/* result must have been >= wait_ms, so reset wait_ms */
|
||||||
send_async_response(ctx, ctx->endpoint);
|
wait_ms = COAP_RESOURCE_CHECK_TIME * 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
clean_up:
|
||||||
coap_free_context(ctx);
|
coap_free_context(ctx);
|
||||||
}
|
coap_cleanup();
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
@ -187,5 +226,5 @@ void app_main(void)
|
|||||||
ESP_ERROR_CHECK( nvs_flash_init() );
|
ESP_ERROR_CHECK( nvs_flash_init() );
|
||||||
wifi_conn_init();
|
wifi_conn_init();
|
||||||
|
|
||||||
xTaskCreate(coap_example_thread, "coap", 2048, NULL, 5, NULL);
|
xTaskCreate(coap_example_thread, "coap", 10240, NULL, 5, NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user