mirror of
https://github.com/obgm/libcoap.git
synced 2026-11-12 11:40:39 +03:00
LwIP: Support TCP
If LWIP_TCP is set, then CoAP TCP support is compiled in.
This commit is contained in:
1 parent
fa88e3235b
commit
805d148dd0
15 files changed
+377
-83
No files matched your search
@@ -76,7 +76,7 @@ nack_handler(coap_session_t *session COAP_UNUSED,
|
||||
|
||||
static int
|
||||
resolve_address(const char *host, const char *service, coap_address_t *dst,
|
||||
int scheme_hint_bits) {
|
||||
coap_proto_t *proto, int scheme_hint_bits) {
|
||||
|
||||
coap_addr_info_t *addr_info;
|
||||
coap_str_const_t str_host;
|
||||
@@ -92,6 +92,7 @@ resolve_address(const char *host, const char *service, coap_address_t *dst,
|
||||
if (addr_info) {
|
||||
ret = 1;
|
||||
*dst = addr_info->addr;
|
||||
*proto = addr_info->proto;
|
||||
}
|
||||
|
||||
coap_free_address_info(addr_info);
|
||||
@@ -118,6 +119,7 @@ client_coap_init(coap_lwip_input_wait_handler_t input_wait, void *input_arg,
|
||||
const char *use_psk = "secretPSK";
|
||||
const char *use_id = "abc";
|
||||
coap_pdu_type_t pdu_type = COAP_MESSAGE_CON;
|
||||
coap_proto_t proto;
|
||||
|
||||
/* Initialize libcoap library */
|
||||
coap_startup();
|
||||
@@ -155,17 +157,12 @@ client_coap_init(coap_lwip_input_wait_handler_t input_wait, void *input_arg,
|
||||
/* Parse the URI */
|
||||
len = coap_split_uri((const unsigned char *)use_uri, strlen(use_uri), &uri);
|
||||
LWIP_ASSERT("Failed to parse uri", len == 0);
|
||||
LWIP_ASSERT("Unsupported URI type", uri.scheme == COAP_URI_SCHEME_COAP ||
|
||||
uri.scheme == COAP_URI_SCHEME_COAPS);
|
||||
if (uri.scheme == COAP_URI_SCHEME_COAPS) {
|
||||
LWIP_ASSERT("DTLS not supported", coap_dtls_is_supported());
|
||||
}
|
||||
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", uri.port);
|
||||
snprintf((char *)buf, sizeof(buf), "%*.*s", (int)uri.host.length,
|
||||
(int)uri.host.length, (const char *)uri.host.s);
|
||||
/* resolve destination address where server should be sent */
|
||||
len = resolve_address((const char *)buf, portbuf, &dst, 1 << uri.scheme);
|
||||
len = resolve_address((const char *)buf, portbuf, &dst, &proto, 1 << uri.scheme);
|
||||
LWIP_ASSERT("Failed to resolve address", len > 0);
|
||||
|
||||
main_coap_context = coap_new_context(NULL);
|
||||
@@ -174,10 +171,8 @@ client_coap_init(coap_lwip_input_wait_handler_t input_wait, void *input_arg,
|
||||
coap_context_set_block_mode(main_coap_context, COAP_BLOCK_USE_LIBCOAP);
|
||||
coap_lwip_set_input_wait_handler(main_coap_context, input_wait, input_arg);
|
||||
|
||||
if (uri.scheme == COAP_URI_SCHEME_COAP) {
|
||||
session = coap_new_client_session(main_coap_context, NULL, &dst,
|
||||
COAP_PROTO_UDP);
|
||||
} else {
|
||||
if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS ||
|
||||
proto == COAP_PROTO_WSS) {
|
||||
static coap_dtls_cpsk_t dtls_psk;
|
||||
static char client_sni[256];
|
||||
|
||||
@@ -197,6 +192,9 @@ client_coap_init(coap_lwip_input_wait_handler_t input_wait, void *input_arg,
|
||||
|
||||
session = coap_new_client_session_psk2(main_coap_context, NULL, &dst,
|
||||
COAP_PROTO_DTLS, &dtls_psk);
|
||||
} else {
|
||||
session = coap_new_client_session(main_coap_context, NULL, &dst,
|
||||
proto);
|
||||
}
|
||||
|
||||
LWIP_ASSERT("Failed to create session", session != NULL);
|
||||
|
||||
@@ -33,7 +33,11 @@
|
||||
|
||||
#ifndef COAP_DISABLE_TCP
|
||||
/* Define to 1 to build without TCP support. */
|
||||
#if LWIP_TCP
|
||||
#define COAP_DISABLE_TCP 0
|
||||
#else /* ! LWIP_TCP */
|
||||
#define COAP_DISABLE_TCP 1
|
||||
#endif /* ! LWIP_TCP */
|
||||
#endif
|
||||
|
||||
#ifndef COAP_ASYNC_SUPPORT
|
||||
@@ -56,11 +60,21 @@
|
||||
#define COAP_Q_BLOCK_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#ifndef PACKAGE_NAME
|
||||
#define PACKAGE_NAME "libcoap"
|
||||
#define PACKAGE_VERSION "4.3.4"
|
||||
#define PACKAGE_STRING "libcoap 4.3.4"
|
||||
#endif /* PACKAGE_NAME */
|
||||
|
||||
#ifndef PACKAGE_VERSION
|
||||
#define PACKAGE_VERSION "4.3.4"
|
||||
#endif /* PACKAGE_VERSION */
|
||||
|
||||
#ifndef PACKAGE_STRING
|
||||
#define PACKAGE_STRING "libcoap 4.3.4"
|
||||
#endif /* PACKAGE_STRING */
|
||||
|
||||
#ifndef assert
|
||||
#define assert(x) LWIP_ASSERT("CoAP assert failed", x)
|
||||
#endif /* assert */
|
||||
|
||||
/* it's just provided by libc. i hope we don't get too many of those, as
|
||||
* actually we'd need autotools again to find out what environment we're
|
||||
|
||||
@@ -33,7 +33,11 @@
|
||||
|
||||
#ifndef COAP_DISABLE_TCP
|
||||
/* Define to 1 to build without TCP support. */
|
||||
#if LWIP_TCP
|
||||
#define COAP_DISABLE_TCP 0
|
||||
#else /* ! LWIP_TCP */
|
||||
#define COAP_DISABLE_TCP 1
|
||||
#endif /* ! LWIP_TCP */
|
||||
#endif
|
||||
|
||||
#ifndef COAP_ASYNC_SUPPORT
|
||||
@@ -56,11 +60,21 @@
|
||||
#define COAP_Q_BLOCK_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#ifndef PACKAGE_NAME
|
||||
#define PACKAGE_NAME "@PACKAGE_NAME@"
|
||||
#define PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
#define PACKAGE_STRING "@PACKAGE_STRING@"
|
||||
#endif /* PACKAGE_NAME */
|
||||
|
||||
#ifndef PACKAGE_VERSION
|
||||
#define PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
#endif /* PACKAGE_VERSION */
|
||||
|
||||
#ifndef PACKAGE_STRING
|
||||
#define PACKAGE_STRING "@PACKAGE_STRING@"
|
||||
#endif /* PACKAGE_STRING */
|
||||
|
||||
#ifndef assert
|
||||
#define assert(x) LWIP_ASSERT("CoAP assert failed", x)
|
||||
#endif /* assert */
|
||||
|
||||
/* it's just provided by libc. i hope we don't get too many of those, as
|
||||
* actually we'd need autotools again to find out what environment we're
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#define LWIP_IPV6_MLD 0
|
||||
#define LWIP_ICMP6 (LWIP_IPV6==1)
|
||||
|
||||
/* Set to 1 if TCP support is required */
|
||||
#define LWIP_TCP 0
|
||||
|
||||
#ifndef LWIP_RAND
|
||||
#define LWIP_RAND() ((u32_t)rand())
|
||||
#endif
|
||||
@@ -36,6 +39,8 @@
|
||||
#define UNLOCK_TCPIP_CORE()
|
||||
#endif
|
||||
|
||||
#define MEMP_NUM_SYS_TIMEOUT 10
|
||||
|
||||
#define MEMP_USE_CUSTOM_POOLS 1
|
||||
#define MEM_SIZE (4 * 1024)
|
||||
/* Support a 1500 MTU packet */
|
||||
|
||||
@@ -43,11 +43,19 @@ typedef struct l_coap_tiny_context_t {
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAPENDPOINT
|
||||
#if COAP_DISABLE_TCP
|
||||
#ifdef COAP_WITH_LIBTINYDTLS
|
||||
#define MEMP_NUM_COAPENDPOINT 2
|
||||
#else /* ! COAP_WITH_LIBTINYDTLS */
|
||||
#define MEMP_NUM_COAPENDPOINT 1
|
||||
#endif /* ! COAP_WITH_LIBTINYDTLS */
|
||||
#else /* ! COAP_DISABLE_TCP */
|
||||
#ifdef COAP_WITH_LIBTINYDTLS
|
||||
#define MEMP_NUM_COAPENDPOINT 4
|
||||
#else /* ! COAP_WITH_LIBTINYDTLS */
|
||||
#define MEMP_NUM_COAPENDPOINT 2
|
||||
#endif /* ! COAP_WITH_LIBTINYDTLS */
|
||||
#endif /* ! COAP_DISABLE_TCP */
|
||||
#endif
|
||||
|
||||
/* 1 is sufficient as this is very short-lived */
|
||||
@@ -92,7 +100,11 @@ typedef struct l_coap_tiny_context_t {
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_LEN_COAPSTRING
|
||||
#ifdef COAP_WITH_LIBTINYDTLS
|
||||
#define MEMP_LEN_COAPSTRING 120
|
||||
#else /* COAP_WITH_TINYDTLS */
|
||||
#define MEMP_LEN_COAPSTRING 40
|
||||
#endif /* COAP_WITH_TINYDTLS */
|
||||
#endif
|
||||
|
||||
#ifndef MEMP_NUM_COAPCACHE_KEYS
|
||||
|
||||
@@ -33,7 +33,12 @@ struct uip_udp_conn;
|
||||
|
||||
struct coap_socket_t {
|
||||
#if defined(WITH_LWIP)
|
||||
struct udp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
struct udp_pcb *udp_pcb;
|
||||
#if ! COAP_DISABLE_TCP
|
||||
struct tcp_pcb *tcp_pcb;
|
||||
#endif /* ! COAP_DISABLE_TCP */
|
||||
|
||||
#elif defined(WITH_CONTIKI)
|
||||
struct uip_udp_conn *udp_conn;
|
||||
coap_context_t *context;
|
||||
|
||||
@@ -143,13 +143,26 @@ coap_free(void *object) {
|
||||
COAP_STATIC_INLINE void
|
||||
coap_memory_init(void) {}
|
||||
|
||||
#if MEMP_STATS
|
||||
COAP_STATIC_INLINE void *
|
||||
coap_malloc_error(uint16_t *err) {
|
||||
(*err)++;
|
||||
return NULL;
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
/* It would be nice to check that size equals the size given at the memp
|
||||
* declaration, but i currently don't see a standard way to check that without
|
||||
* sourcing the custom memp pools and becoming dependent of its syntax
|
||||
*/
|
||||
#if MEMP_STATS
|
||||
#define coap_malloc_type(type, asize) \
|
||||
(((asize) <= memp_pools[MEMP_ ## type]->size) ? \
|
||||
memp_malloc(MEMP_ ## type) : coap_malloc_error(&memp_pools[MEMP_ ## type]->stats->err))
|
||||
#else /* ! MEMP_STATS */
|
||||
#define coap_malloc_type(type, asize) \
|
||||
(((asize) <= memp_pools[MEMP_ ## type]->size) ? \
|
||||
memp_malloc(MEMP_ ## type) : NULL)
|
||||
#endif /* ! MEMP_STATS */
|
||||
#define coap_free_type(type, p) memp_free(MEMP_ ## type, p)
|
||||
|
||||
/* As these are fixed size, return value if already defined */
|
||||
|
||||
@@ -128,10 +128,12 @@ int coap_netif_strm_listen(coap_endpoint_t *endpoint,
|
||||
*
|
||||
* @param endpoint Endpoint to to do the accept on.
|
||||
* @param session Session to to do the accept update on.
|
||||
* @param extra Available for use by any underlying network stack.
|
||||
*
|
||||
* @return @c 1 OK, 0 on failure.
|
||||
*/
|
||||
int coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session);
|
||||
int coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session,
|
||||
void *extra);
|
||||
|
||||
/**
|
||||
* Layer function interface for Netif stream connect (tcp).
|
||||
|
||||
@@ -309,14 +309,14 @@ int coap_session_refresh_psk_identity(coap_session_t *session,
|
||||
* Creates a new server session for the specified endpoint.
|
||||
* @param ctx The CoAP context.
|
||||
* @param ep An endpoint where an incoming connection request is pending.
|
||||
* @param extra Available for use by any underlying network stack.
|
||||
*
|
||||
* @return A new CoAP session or NULL if failed. Call coap_session_release to
|
||||
* add to unused queue.
|
||||
*/
|
||||
coap_session_t *coap_new_server_session(
|
||||
coap_context_t *ctx,
|
||||
coap_endpoint_t *ep
|
||||
);
|
||||
coap_session_t *coap_new_server_session(coap_context_t *ctx,
|
||||
coap_endpoint_t *ep,
|
||||
void *extra);
|
||||
#endif /* COAP_SERVER_SUPPORT */
|
||||
|
||||
/**
|
||||
@@ -384,6 +384,10 @@ coap_session_t *coap_session_new_dtls_session(coap_session_t *session,
|
||||
void coap_session_free(coap_session_t *session);
|
||||
void coap_session_mfree(coap_session_t *session);
|
||||
|
||||
void coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now);
|
||||
|
||||
void coap_connect_session(coap_session_t *session, coap_tick_t now);
|
||||
|
||||
#define COAP_SESSION_REF(s) ((s)->ref
|
||||
|
||||
/* RFC7252 */
|
||||
|
||||
@@ -93,13 +93,15 @@ int coap_socket_bind_tcp(coap_socket_t *sock,
|
||||
* session information
|
||||
* @param local_addr Filled in with the local address
|
||||
* @param remote_addr Filled in with the remote address
|
||||
* @param extra Available for use by any underlying network stack.
|
||||
*
|
||||
* @return @c 1 if succesful, @c 0 if failure of some sort
|
||||
*/
|
||||
int coap_socket_accept_tcp(coap_socket_t *server,
|
||||
coap_socket_t *new_client,
|
||||
coap_address_t *local_addr,
|
||||
coap_address_t *remote_addr);
|
||||
coap_address_t *remote_addr,
|
||||
void *extra);
|
||||
|
||||
#endif /* !COAP_DISABLE_TCP */
|
||||
|
||||
|
||||
+268
-46
@@ -202,7 +202,7 @@ coap_free_packet(coap_packet_t *packet) {
|
||||
coap_free_type(COAP_PACKET, packet);
|
||||
}
|
||||
|
||||
/** Callback from lwIP when a package was received for a server.
|
||||
/** Callback from lwIP when a UDP packet was received for a server.
|
||||
*
|
||||
* The current implementation deals this to coap_dispatch immediately, but
|
||||
* other mechanisms (as storing the package in a queue and later fetching it
|
||||
@@ -211,8 +211,8 @@ coap_free_packet(coap_packet_t *packet) {
|
||||
* It handles everything coap_io_do_io does on other implementations.
|
||||
*/
|
||||
static void
|
||||
coap_recvs(void *arg, struct udp_pcb *upcb, struct pbuf *p,
|
||||
const ip_addr_t *addr, u16_t port) {
|
||||
coap_udp_recvs(void *arg, struct udp_pcb *upcb, struct pbuf *p,
|
||||
const ip_addr_t *addr, u16_t port) {
|
||||
coap_endpoint_t *ep = (coap_endpoint_t *)arg;
|
||||
coap_pdu_t *pdu = NULL;
|
||||
coap_session_t *session = NULL;
|
||||
@@ -304,7 +304,7 @@ coap_socket_send_pdu(coap_socket_t *sock, coap_session_t *session,
|
||||
pbuf = pbuf_clone(PBUF_TRANSPORT, PBUF_RAM, pdu->pbuf);
|
||||
if (pbuf == NULL)
|
||||
return -1;
|
||||
err = udp_sendto(sock->pcb, pbuf, &session->addr_info.remote.addr,
|
||||
err = udp_sendto(sock->udp_pcb, pbuf, &session->addr_info.remote.addr,
|
||||
session->addr_info.remote.port);
|
||||
pbuf_free(pbuf);
|
||||
if (err < 0)
|
||||
@@ -332,7 +332,7 @@ coap_socket_send(coap_socket_t *sock, const coap_session_t *session,
|
||||
|
||||
LOCK_TCPIP_CORE();
|
||||
|
||||
err = udp_sendto(sock->pcb, pbuf, &session->addr_info.remote.addr,
|
||||
err = udp_sendto(sock->udp_pcb, pbuf, &session->addr_info.remote.addr,
|
||||
session->addr_info.remote.port);
|
||||
|
||||
UNLOCK_TCPIP_CORE();
|
||||
@@ -352,19 +352,19 @@ coap_socket_bind_udp(coap_socket_t *sock,
|
||||
int err;
|
||||
coap_address_t l_listen = *listen_addr;
|
||||
|
||||
sock->pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
if (sock->pcb == NULL)
|
||||
sock->udp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
if (sock->udp_pcb == NULL)
|
||||
return 0;
|
||||
|
||||
#if LWIP_IPV6 && LWIP_IPV4
|
||||
if (l_listen.addr.type == IPADDR_TYPE_V6)
|
||||
l_listen.addr.type = IPADDR_TYPE_ANY;
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV4 */
|
||||
udp_recv(sock->pcb, coap_recvs, (void *)sock->endpoint);
|
||||
err = udp_bind(sock->pcb, &l_listen.addr, l_listen.port);
|
||||
udp_recv(sock->udp_pcb, coap_udp_recvs, (void *)sock->endpoint);
|
||||
err = udp_bind(sock->udp_pcb, &l_listen.addr, l_listen.port);
|
||||
if (err) {
|
||||
udp_remove(sock->pcb);
|
||||
sock->pcb = NULL;
|
||||
udp_remove(sock->udp_pcb);
|
||||
sock->udp_pcb = NULL;
|
||||
}
|
||||
*bound_addr = l_listen;
|
||||
return err ? 0 : 1;
|
||||
@@ -413,9 +413,9 @@ coap_socket_connect_udp(coap_socket_t *sock,
|
||||
pcb->local_ip.type = pcb->remote_ip.type;
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV4 */
|
||||
|
||||
sock->pcb = pcb;
|
||||
sock->udp_pcb = pcb;
|
||||
|
||||
udp_recv(sock->pcb, coap_recvc, (void *)sock->session);
|
||||
udp_recv(sock->udp_pcb, coap_recvc, (void *)sock->session);
|
||||
|
||||
UNLOCK_TCPIP_CORE();
|
||||
|
||||
@@ -431,6 +431,77 @@ err_unlock:
|
||||
#endif /* ! COAP_CLIENT_SUPPORT */
|
||||
|
||||
#if ! COAP_DISABLE_TCP
|
||||
|
||||
#include <lwip/tcp.h>
|
||||
|
||||
static void
|
||||
do_tcp_err(void *arg, err_t err) {
|
||||
coap_session_t *session = (coap_session_t *)arg;
|
||||
|
||||
(void)err;
|
||||
|
||||
coap_handle_event(session->context, COAP_EVENT_TCP_FAILED, session);
|
||||
/*
|
||||
* as per tcp_err() documentation, the corresponding pcb is already freed
|
||||
* when this callback is called. So, stop a double free when
|
||||
* coap_session_disconnected() eventually coap_socket_close() is called.
|
||||
*/
|
||||
session->sock.tcp_pcb = NULL;
|
||||
coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE);
|
||||
}
|
||||
|
||||
/** Callback from lwIP when a TCP packet is received.
|
||||
*
|
||||
* The current implementation invokes coap_read_session() to do the bulk of the
|
||||
* work.
|
||||
*/
|
||||
static err_t
|
||||
coap_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
|
||||
coap_session_t *session = (coap_session_t *)arg;
|
||||
coap_socket_t *sock = &session->sock;
|
||||
coap_tick_t now;
|
||||
|
||||
(void)tpcb;
|
||||
if (p == NULL) {
|
||||
/* remote host closed connection */
|
||||
tcp_arg(sock->tcp_pcb, NULL);
|
||||
tcp_recv(sock->tcp_pcb, NULL);
|
||||
tcp_close(sock->tcp_pcb);
|
||||
sock->tcp_pcb = NULL;
|
||||
coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE);
|
||||
return ERR_OK;
|
||||
} else if (err != ERR_OK) {
|
||||
/* cleanup, for unknown reason */
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
sock->p = p;
|
||||
coap_ticks(&now);
|
||||
coap_read_session(session->context, session, now);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if COAP_CLIENT_SUPPORT
|
||||
|
||||
static err_t
|
||||
do_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
|
||||
coap_session_t *session = (coap_session_t *)arg;
|
||||
coap_tick_t now;
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
session->sock.flags |= COAP_SOCKET_CONNECTED;
|
||||
session->addr_info.local.addr = tpcb->local_ip;
|
||||
session->addr_info.local.port = tpcb->local_port;
|
||||
tcp_recv(tpcb, coap_tcp_recv);
|
||||
coap_ticks(&now);
|
||||
coap_connect_session(session, now);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int
|
||||
coap_socket_connect_tcp1(coap_socket_t *sock,
|
||||
const coap_address_t *local_if,
|
||||
@@ -438,13 +509,45 @@ coap_socket_connect_tcp1(coap_socket_t *sock,
|
||||
int default_port,
|
||||
coap_address_t *local_addr,
|
||||
coap_address_t *remote_addr) {
|
||||
(void)sock;
|
||||
(void)local_if;
|
||||
(void)server;
|
||||
(void)default_port;
|
||||
coap_address_t connect_addr;
|
||||
err_t err;
|
||||
|
||||
(void)local_addr;
|
||||
(void)remote_addr;
|
||||
return 0;
|
||||
|
||||
sock->flags &= ~(COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CONNECTED);
|
||||
|
||||
sock->tcp_pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
if (sock->tcp_pcb == NULL)
|
||||
return 0;
|
||||
|
||||
tcp_arg(sock->tcp_pcb, sock->session);
|
||||
tcp_recv(sock->tcp_pcb, coap_tcp_recv);
|
||||
tcp_err(sock->tcp_pcb, do_tcp_err);
|
||||
if (local_if) {
|
||||
coap_address_t l_local_if = *local_if;
|
||||
#if LWIP_IPV6 && LWIP_IPV4
|
||||
if (l_local_if.addr.type == IPADDR_TYPE_V6)
|
||||
l_local_if.addr.type = IPADDR_TYPE_ANY;
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV4 */
|
||||
err = tcp_bind(sock->tcp_pcb, &l_local_if.addr, l_local_if.port);
|
||||
if (err != ERR_OK) {
|
||||
tcp_arg(sock->tcp_pcb, NULL);
|
||||
tcp_recv(sock->tcp_pcb, NULL);
|
||||
tcp_close(sock->tcp_pcb);
|
||||
sock->tcp_pcb = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
coap_address_copy(&connect_addr, server);
|
||||
if (connect_addr.port == 0)
|
||||
connect_addr.port = htons(default_port);
|
||||
|
||||
err = tcp_connect(sock->tcp_pcb, &connect_addr.addr, connect_addr.port,
|
||||
do_tcp_connected);
|
||||
if (err == ERR_OK)
|
||||
sock->flags |= COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CONNECTED;
|
||||
return err ? 0 : 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -454,55 +557,174 @@ coap_socket_connect_tcp2(coap_socket_t *sock,
|
||||
(void)sock;
|
||||
(void)local_addr;
|
||||
(void)remote_addr;
|
||||
return 0;
|
||||
|
||||
sock->flags &= ~(COAP_SOCKET_WANT_CONNECT | COAP_SOCKET_CAN_CONNECT);
|
||||
return 1;
|
||||
}
|
||||
#endif /* COAP_CLIENT_SUPPORT */
|
||||
|
||||
#if COAP_SERVER_SUPPORT
|
||||
|
||||
static err_t
|
||||
do_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
|
||||
coap_endpoint_t *endpoint = arg;
|
||||
coap_session_t *session;
|
||||
coap_tick_t now;
|
||||
err_t ret_err = ERR_OK;
|
||||
|
||||
if ((err != ERR_OK) || (newpcb == NULL)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
coap_ticks(&now);
|
||||
|
||||
session = coap_new_server_session(endpoint->context, endpoint, newpcb);
|
||||
|
||||
if (session) {
|
||||
session->sock.tcp_pcb = newpcb;
|
||||
session->last_rx_tx = now;
|
||||
tcp_arg(newpcb, session);
|
||||
tcp_setprio(newpcb, TCP_PRIO_MIN);
|
||||
tcp_recv(newpcb, coap_tcp_recv);
|
||||
tcp_err(newpcb, do_tcp_err);
|
||||
} else {
|
||||
ret_err = ERR_MEM;
|
||||
}
|
||||
return ret_err;
|
||||
}
|
||||
|
||||
int
|
||||
coap_socket_bind_tcp(coap_socket_t *sock,
|
||||
const coap_address_t *listen_addr,
|
||||
coap_address_t *bound_addr) {
|
||||
(void)sock;
|
||||
(void)listen_addr;
|
||||
(void)bound_addr;
|
||||
return 0;
|
||||
int err;
|
||||
coap_address_t l_listen = *listen_addr;
|
||||
struct tcp_pcb *tcp_pcb;
|
||||
|
||||
sock->tcp_pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
if (sock->tcp_pcb == NULL)
|
||||
return 0;
|
||||
|
||||
#if LWIP_IPV6 && LWIP_IPV4
|
||||
if (l_listen.addr.type == IPADDR_TYPE_V6)
|
||||
l_listen.addr.type = IPADDR_TYPE_ANY;
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV4 */
|
||||
tcp_arg(sock->tcp_pcb, sock->endpoint);
|
||||
err = tcp_bind(sock->tcp_pcb, &l_listen.addr, l_listen.port);
|
||||
if (err != ERR_OK) {
|
||||
tcp_arg(sock->tcp_pcb, NULL);
|
||||
tcp_recv(sock->tcp_pcb, NULL);
|
||||
tcp_close(sock->tcp_pcb);
|
||||
sock->tcp_pcb = NULL;
|
||||
return 0;
|
||||
} else {
|
||||
tcp_pcb = tcp_listen(sock->tcp_pcb);
|
||||
if (tcp_pcb) {
|
||||
sock->tcp_pcb = tcp_pcb;
|
||||
tcp_accept(sock->tcp_pcb, do_tcp_accept);
|
||||
} else {
|
||||
tcp_arg(sock->tcp_pcb, NULL);
|
||||
tcp_recv(sock->tcp_pcb, NULL);
|
||||
tcp_close(sock->tcp_pcb);
|
||||
sock->tcp_pcb = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*bound_addr = l_listen;
|
||||
return err ? 0 : 1;
|
||||
}
|
||||
|
||||
int
|
||||
coap_socket_accept_tcp(coap_socket_t *server,
|
||||
coap_socket_t *new_client,
|
||||
coap_address_t *local_addr,
|
||||
coap_address_t *remote_addr) {
|
||||
coap_address_t *remote_addr,
|
||||
void *extra) {
|
||||
struct tcp_pcb *tcp_pcb = (struct tcp_pcb *)extra;
|
||||
|
||||
(void)server;
|
||||
(void)new_client;
|
||||
(void)local_addr;
|
||||
(void)remote_addr;
|
||||
|
||||
new_client->tcp_pcb = tcp_pcb;
|
||||
local_addr->addr = tcp_pcb->local_ip;
|
||||
local_addr->port = tcp_pcb->local_port;
|
||||
remote_addr->addr = tcp_pcb->remote_ip;
|
||||
remote_addr->port = tcp_pcb->remote_port;
|
||||
return 1;
|
||||
}
|
||||
#endif /* COAP_SERVER_SUPPORT */
|
||||
|
||||
/*
|
||||
* strm
|
||||
* return +ve Number of bytes written.
|
||||
* -1 Error error in errno).
|
||||
*/
|
||||
ssize_t
|
||||
coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
|
||||
struct pbuf *pbuf;
|
||||
int err;
|
||||
|
||||
pbuf = pbuf_alloc(PBUF_TRANSPORT, data_len, PBUF_RAM);
|
||||
if (pbuf == NULL)
|
||||
return -1;
|
||||
memcpy(pbuf->payload, data, data_len);
|
||||
|
||||
LOCK_TCPIP_CORE();
|
||||
|
||||
err = tcp_write(sock->tcp_pcb, pbuf->payload, pbuf->len, 1);
|
||||
|
||||
UNLOCK_TCPIP_CORE();
|
||||
|
||||
pbuf_free(pbuf);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
return data_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* strm
|
||||
* return >=0 Number of bytes read.
|
||||
* -1 Error error in errno).
|
||||
*/
|
||||
ssize_t
|
||||
coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
|
||||
if (sock->p) {
|
||||
if (data_len < sock->p->len) {
|
||||
uint8_t *ptr = (uint8_t *)sock->p->payload;
|
||||
|
||||
/* Handle partial read of data request */
|
||||
memcpy(data, sock->p->payload, data_len);
|
||||
sock->p->payload = &ptr[data_len];
|
||||
sock->p->len -= data_len;
|
||||
return data_len;
|
||||
} else {
|
||||
data_len = sock->p->len;
|
||||
memcpy(data, sock->p->payload, sock->p->len);
|
||||
pbuf_free(sock->p);
|
||||
sock->p = NULL;
|
||||
return data_len;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* !COAP_DISABLE_TCP */
|
||||
|
||||
ssize_t
|
||||
coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
|
||||
(void)sock;
|
||||
(void)data;
|
||||
(void)data_len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
|
||||
(void)sock;
|
||||
(void)data;
|
||||
(void)data_len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
coap_socket_close(coap_socket_t *sock) {
|
||||
if (sock->pcb) {
|
||||
if (sock->udp_pcb) {
|
||||
LOCK_TCPIP_CORE();
|
||||
udp_remove(sock->pcb);
|
||||
udp_remove(sock->udp_pcb);
|
||||
UNLOCK_TCPIP_CORE();
|
||||
sock->udp_pcb = NULL;
|
||||
}
|
||||
sock->pcb = NULL;
|
||||
#if ! COAP_DISABLE_TCP
|
||||
if (sock->tcp_pcb) {
|
||||
tcp_arg(sock->tcp_pcb, NULL);
|
||||
#if COAP_SERVER_SUPPORT
|
||||
if (!sock->endpoint)
|
||||
#endif /* COAP_SERVER_SUPPORT */
|
||||
tcp_recv(sock->tcp_pcb, NULL);
|
||||
tcp_close(sock->tcp_pcb);
|
||||
sock->tcp_pcb = NULL;
|
||||
}
|
||||
#endif /* !COAP_DISABLE_TCP */
|
||||
return;
|
||||
}
|
||||
+6
-6
@@ -1761,7 +1761,7 @@ coap_handle_dgram_for_proto(coap_context_t *ctx, coap_session_t *session, coap_p
|
||||
}
|
||||
|
||||
#if COAP_CLIENT_SUPPORT
|
||||
static void
|
||||
void
|
||||
coap_connect_session(coap_session_t *session, coap_tick_t now) {
|
||||
#if COAP_DISABLE_TCP
|
||||
(void)now;
|
||||
@@ -1808,7 +1808,7 @@ coap_write_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
coap_read_session(coap_context_t *ctx, coap_session_t *session, coap_tick_t now) {
|
||||
#if COAP_CONSTRAINED_STACK
|
||||
/* payload and packet protected by mutex m_read_session */
|
||||
@@ -2061,8 +2061,8 @@ coap_write_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint, coap_tick_t
|
||||
#if !COAP_DISABLE_TCP
|
||||
static int
|
||||
coap_accept_endpoint(coap_context_t *ctx, coap_endpoint_t *endpoint,
|
||||
coap_tick_t now) {
|
||||
coap_session_t *session = coap_new_server_session(ctx, endpoint);
|
||||
coap_tick_t now, void *extra) {
|
||||
coap_session_t *session = coap_new_server_session(ctx, endpoint, extra);
|
||||
if (session)
|
||||
session->last_rx_tx = now;
|
||||
return session != NULL;
|
||||
@@ -2088,7 +2088,7 @@ coap_io_do_io(coap_context_t *ctx, coap_tick_t now) {
|
||||
coap_write_endpoint(ctx, ep, now);
|
||||
#if !COAP_DISABLE_TCP
|
||||
if ((ep->sock.flags & COAP_SOCKET_CAN_ACCEPT) != 0)
|
||||
coap_accept_endpoint(ctx, ep, now);
|
||||
coap_accept_endpoint(ctx, ep, now, NULL);
|
||||
#endif /* !COAP_DISABLE_TCP */
|
||||
SESSIONS_ITER_SAFE(ep->sessions, s, rtmp) {
|
||||
/* Make sure the session object is not deleted in one of the callbacks */
|
||||
@@ -2168,7 +2168,7 @@ coap_io_do_epoll(coap_context_t *ctx, struct epoll_event *events, size_t nevents
|
||||
if ((sock->flags & COAP_SOCKET_WANT_ACCEPT) &&
|
||||
(events[j].events & EPOLLIN)) {
|
||||
sock->flags |= COAP_SOCKET_CAN_ACCEPT;
|
||||
coap_accept_endpoint(endpoint->context, endpoint, now);
|
||||
coap_accept_endpoint(endpoint->context, endpoint, now, NULL);
|
||||
}
|
||||
#endif /* !COAP_DISABLE_TCP */
|
||||
|
||||
|
||||
+2
-2
@@ -167,10 +167,10 @@ coap_netif_strm_listen(coap_endpoint_t *endpoint,
|
||||
}
|
||||
|
||||
int
|
||||
coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session) {
|
||||
coap_netif_strm_accept(coap_endpoint_t *endpoint, coap_session_t *session, void *extra) {
|
||||
if (!coap_socket_accept_tcp(&endpoint->sock, &session->sock,
|
||||
&session->addr_info.local,
|
||||
&session->addr_info.remote)) {
|
||||
&session->addr_info.remote, extra)) {
|
||||
return 0;
|
||||
}
|
||||
session->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_CONNECTED |
|
||||
|
||||
+4
-3
@@ -492,7 +492,8 @@ coap_session_mfree(coap_session_t *session) {
|
||||
|
||||
if (session->partial_pdu)
|
||||
coap_delete_pdu(session->partial_pdu);
|
||||
session->sock.lfunc[COAP_LAYER_SESSION].l_close(session);
|
||||
if (session->sock.lfunc[COAP_LAYER_SESSION].l_close)
|
||||
session->sock.lfunc[COAP_LAYER_SESSION].l_close(session);
|
||||
if (session->psk_identity)
|
||||
coap_delete_bin_const(session->psk_identity);
|
||||
if (session->psk_key)
|
||||
@@ -1529,7 +1530,7 @@ coap_new_client_session_pki(coap_context_t *ctx,
|
||||
#if COAP_SERVER_SUPPORT
|
||||
#if !COAP_DISABLE_TCP
|
||||
coap_session_t *
|
||||
coap_new_server_session(coap_context_t *ctx, coap_endpoint_t *ep) {
|
||||
coap_new_server_session(coap_context_t *ctx, coap_endpoint_t *ep, void *extra) {
|
||||
coap_session_t *session;
|
||||
session = coap_make_session(ep->proto, COAP_SESSION_TYPE_SERVER,
|
||||
NULL, NULL, NULL, 0, ctx, ep);
|
||||
@@ -1537,7 +1538,7 @@ coap_new_server_session(coap_context_t *ctx, coap_endpoint_t *ep) {
|
||||
goto error;
|
||||
|
||||
memcpy(session->sock.lfunc, ep->sock.lfunc, sizeof(session->sock.lfunc));
|
||||
if (!coap_netif_strm_accept(ep, session))
|
||||
if (!coap_netif_strm_accept(ep, session, extra))
|
||||
goto error;
|
||||
|
||||
coap_make_addr_hash(&session->addr_hash, session->proto, &session->addr_info);
|
||||
|
||||
+6
-4
@@ -38,7 +38,7 @@ coap_tcp_is_supported(void) {
|
||||
return !COAP_DISABLE_TCP;
|
||||
}
|
||||
|
||||
#if !COAP_DISABLE_TCP
|
||||
#if !COAP_DISABLE_TCP && !defined(WITH_LWIP)
|
||||
int
|
||||
coap_socket_connect_tcp1(coap_socket_t *sock,
|
||||
const coap_address_t *local_if,
|
||||
@@ -176,12 +176,12 @@ coap_socket_connect_tcp2(coap_socket_t *sock,
|
||||
|
||||
if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, OPTVAL_GT(&error),
|
||||
&optlen) == COAP_SOCKET_ERROR) {
|
||||
coap_log_warn("coap_socket_finish_connect_tcp: getsockopt: %s\n",
|
||||
coap_log_warn("coap_socket_connect_tcp2: getsockopt: %s\n",
|
||||
coap_socket_strerror());
|
||||
}
|
||||
|
||||
if (error) {
|
||||
coap_log_warn("coap_socket_finish_connect_tcp: connect failed: %s\n",
|
||||
coap_log_warn("coap_socket_connect_tcp2: connect failed: %s\n",
|
||||
coap_socket_format_errno(error));
|
||||
coap_socket_close(sock);
|
||||
return 0;
|
||||
@@ -299,7 +299,8 @@ int
|
||||
coap_socket_accept_tcp(coap_socket_t *server,
|
||||
coap_socket_t *new_client,
|
||||
coap_address_t *local_addr,
|
||||
coap_address_t *remote_addr) {
|
||||
coap_address_t *remote_addr,
|
||||
void *extra) {
|
||||
#ifndef RIOT_VERSION
|
||||
#ifdef _WIN32
|
||||
u_long u_on = 1;
|
||||
@@ -307,6 +308,7 @@ coap_socket_accept_tcp(coap_socket_t *server,
|
||||
int on = 1;
|
||||
#endif
|
||||
#endif /* RIOT_VERSION */
|
||||
(void)extra;
|
||||
|
||||
server->flags &= ~COAP_SOCKET_CAN_ACCEPT;
|
||||
|
||||
|
||||
Reference in new issue
Block a user