'\" t
.\" Title: coap_endpoint_client
.\" Author: [see the "AUTHORS" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot
.\" Date: 04/07/2024
.\" Manual: libcoap Manual
.\" Source: coap_endpoint_client 4.3.4
.\" Language: English
.\"
.TH "COAP_ENDPOINT_CLIENT" "3" "04/07/2024" "coap_endpoint_client 4\&.3\&.4" "libcoap Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\" http://bugs.debian.org/507673
.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
.\" -----------------------------------------------------------------
.\" * MAIN CONTENT STARTS HERE *
.\" -----------------------------------------------------------------
.SH "NAME"
coap_endpoint_client, coap_new_client_session, coap_new_client_session_psk2, coap_new_client_session_pki, coap_session_set_mtu, coap_session_max_pdu_size \- Work with CoAP client endpoints
.SH "SYNOPSIS"
.sp
\fB#include \fR
.sp
\fBcoap_session_t *coap_new_client_session(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, const coap_address_t *\fR\fB\fIlocal_if\fR\fR\fB, const coap_address_t *\fR\fB\fIserver\fR\fR\fB, coap_proto_t \fR\fB\fIproto\fR\fR\fB);\fR
.sp
\fBcoap_session_t *coap_new_client_session_psk2(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, const coap_address_t *\fR\fB\fIlocal_if\fR\fR\fB, const coap_address_t *\fR\fB\fIserver\fR\fR\fB, coap_proto_t \fR\fB\fIproto\fR\fR\fB, coap_dtls_cpsk_t *\fR\fB\fIsetup_data\fR\fR\fB);\fR
.sp
\fBcoap_session_t *coap_new_client_session_pki(coap_context_t *\fR\fB\fIcontext\fR\fR\fB, const coap_address_t *\fR\fB\fIlocal_if\fR\fR\fB, const coap_address_t *\fR\fB\fIserver\fR\fR\fB, coap_proto_t \fR\fB\fIproto\fR\fR\fB, coap_dtls_pki_t *\fR\fB\fIsetup_data\fR\fR\fB);\fR
.sp
\fBvoid coap_session_set_mtu(coap_session_t *\fR\fB\fIsession\fR\fR\fB, unsigned \fR\fB\fImtu\fR\fR\fB);\fR
.sp
\fBsize_t coap_session_max_pdu_size(const coap_session_t *\fR\fB\fIsession\fR\fR\fB);\fR
.sp
For specific (D)TLS library support, link with \fB\-lcoap\-3\-notls\fR, \fB\-lcoap\-3\-gnutls\fR, \fB\-lcoap\-3\-openssl\fR, \fB\-lcoap\-3\-mbedtls\fR or \fB\-lcoap\-3\-tinydtls\fR\&. Otherwise, link with \fB\-lcoap\-3\fR to get the default (D)TLS library support\&.
.SH "DESCRIPTION"
.sp
This man page focuses on the setting up of a CoAP client endpoint and hence creation of a CoAP \fIsession\fR used to connect to a server\&. For a CoAP server endpoint, see \fBcoap_endpoint_server\fR(3)\&. There is no need to call \fBcoap_new_endpoint\fR(3) for a client as well as one of the \fBcoap_new_client_server\fR*() functions\&.
.sp
The CoAP stack\(cqs global state is stored in a coap_context_t \fIcontext\fR object\&. Resources, Endpoints and Sessions are associated with this \fIcontext\fR object\&. There can be more than one coap_context_t object per application, it is up to the application to manage each one accordingly\&.
.sp
A CoAP \fIsession\fR maintains the state of an ongoing connection between a Client and Server which is stored in a coap_session_t \fIsession\fR object\&. A CoAP \fIsession\fR is tracked by local port, CoAP protocol, remote IP address and remote port, or in the case of Unix Domain sockets, the local path and the remote path\&.
.sp
The \fIsession\fR network traffic can be encrypted or un\-encrypted if there is an underlying TLS library\&.
.sp
If (D)TLS is going to be used for encrypting the network traffic, then the (D)TLS information for Pre\-Shared Keys (PSK) or Public Key Infrastructure (PKI) needs to be configured before any network traffic starts to flow\&. For Clients, this is done during the Client \fIsession\fR set up\&.
.sp
For Clients, all the encryption information can be held at the (D)TLS context and CoAP \fIcontext\fR levels, or at the (D)TLS session and CoAP \fIsession\fR levels\&. If defined at the \fIcontext\fR level, then when a \fIsession\fR is created, it will inherit the \fIcontext\fR definitions, unless they have separately been defined for the \fIsession\fR level, in which case the \fIsession\fR version will get used\&. Typically the information will be configured at the \fIsession\fR level for Clients\&.
.sp
In principle the set\-up sequence for CoAP client endpoints looks like
.sp
.if n \{\
.RS 4
.\}
.nf
coap_new_context()
coap_context_set_pki_root_cas() \- if the root CAs need to be updated and using PKI
coap_new_client_session(), coap_new_client_session_pki() or coap_new_client_session_psk2()
.fi
.if n \{\
.RE
.\}
.sp
Multiple client endpoints and hence sessions are supported per \fIcontext\fR\&.
.sp
Different CoAP protocols can be defined for \fIproto\fR \- the current supported list is:
.sp
.if n \{\
.RS 4
.\}
.nf
COAP_PROTO_UDP
COAP_PROTO_DTLS
COAP_PROTO_TCP
COAP_PROTO_TLS
COAP_PROTO_WS
COAP_PROTO_WSS
.fi
.if n \{\
.RE
.\}
.sp
\fBcoap_tcp_is_supported\fR(3), \fBcoap_dtls_is_supported\fR(3), \fBcoap_tls_is_supported\fR(3), \fBcoap_ws_is_supported\fR(3) and \fBcoap_wss_is_supported\fR(3) can be used for checking whether the underlying TCP, (D)TLS or WebSocket protocol support is available\&. See \fBcoap_tls_library(3)\fR for further information on the types of (D)TLS sessions supported\&.
.sp
Libcoap supports 3 different socket types:
.sp
.if n \{\
.RS 4
.\}
.nf
AF_INET IPv4 IP addresses and ports
AF_INET6 IPv6 IP addresses and ports and can be dual IPv4/IPv6 stacked
AF_UNIX Unix Domain using file path names
.fi
.if n \{\
.RE
.\}
.sp
For AF_INET and AF_INET6, the client does not need to specify a local IP address and/or port as default values will get filled in\&. However for AF_UNIX, the local pathname must be provided and must be unique per client session\&. This unique local pathname will get deleted on the session being properly closed at application exit\&.
.sp
The client must specify IP and port when defining the \fBcoap_address_t\fR (see \fBcoap_address_t\fR(3)) for the remote end of the session if AF_INET or AF_INET6\&. If port is 0, then the default CoAP port is used instead\&. If AF_UNIX, the unix domain path to connect to must be specified\&.
.SH "FUNCTIONS"
.sp
\fBFunction: coap_new_client_session()\fR
.sp
The \fBcoap_new_client_session\fR() function creates a client endpoint for a specific \fIcontext\fR and initiates a new client session to the specified \fIserver\fR using the CoAP protocol \fIproto\fR as defined above\&. If the port is set to 0 in \fIserver\fR (for AF_INET or AF_INET6), then the default CoAP port is used\&.
.sp
Normally \fIlocal_if\fR would be set to NULL, but by specifying \fIlocal_if\fR the source of the network session can be bound to a specific IP address or port\&. For AF_UNIX, \fIlocal_if\fR must be specified pointing to an appropriate \fBcoap_address_t\fR\&. If \fIlocal_if\fR is defined, the address families for \fIlocal_if\fR and \fIserver\fR must be identical\&. The session will initially have a reference count of 1\&.
.sp
To stop using a client session, the reference count must be decremented to 0 by calling \fBcoap_session_release\fR(3)\&. See \fBcoap_session\fR(3)\&. This will remove the client endpoint\(cqs \fIsession\fR and all its associated information\&.
.sp
\fBFunction: coap_new_client_session_pki()\fR
.sp
The \fBcoap_new_client_session_pki\fR() function, for a specific \fIcontext\fR, is used to configure the (D)TLS context using the \fIsetup_data\fR variables as defined in the coap_dtls_pki_t structure in the newly created endpoint session \- see \fBcoap_encryption\fR(3)\&. The connection is to the specified \fIserver\fR using the CoAP protocol \fIproto\fR as defined above\&. If the port is set to 0 in \fIserver\fR (for AF_INET or AF_INET6), then the default CoAP port is used\&.
.sp
Normally \fIlocal_if\fR would be set to NULL, but by specifying \fIlocal_if\fR the source of the network session can be bound to a specific IP address or port\&. For AF_UNIX, \fIlocal_if\fR must be specified pointing to an appropriate \fBcoap_address_t\fR\&. If \fIlocal_if\fR is defined, the address families for \fIlocal_if\fR and \fIserver\fR must be identical\&. The session will initially have a reference count of 1\&.
.sp
To stop using a client session, the reference count must be decremented to 0 by calling \fBcoap_session_release\fR(3)\&. See \fBcoap_session\fR(3)\&. This will remove the client endpoint\(cqs \fIsession\fR and all its associated information\&.
.sp
\fBFunction: coap_new_client_session_psk2()\fR
.sp
The \fBcoap_new_client_session_psk2\fR() function, for a specific \fIcontext\fR, is used to configure the (D)TLS context using the \fIsetup_data\fR variables as defined in the coap_dtls_cpsk_t structure in the newly created endpoint session \- see \fBcoap_encryption\fR(3)\&. The connection is to the specified \fIserver\fR using the CoAP protocol \fIproto\fR as defined above\&. If the port is set to 0 in \fIserver\fR (for AF_INET or AF_INET6), then the default CoAP port is used\&.
.sp
Normally \fIlocal_if\fR would be set to NULL, but by specifying \fIlocal_if\fR the source of the network session can be bound to a specific IP address or port\&. For AF_UNIX, \fIlocal_if\fR must be specified pointing to an appropriate \fBcoap_address_t\fR\&. If \fIlocal_if\fR is defined, the address families for \fIlocal_if\fR and \fIserver\fR must be identical\&. The session will initially have a reference count of 1\&.
.sp
To stop using a client session, the reference count must be decremented to 0 by calling \fBcoap_session_release\fR(3)\&. See \fBcoap_session\fR(3)\&. This will remove the client endpoint\(cqs \fIsession\fR and all its associated information\&.
.sp
\fBFunction: coap_session_set_mtu()\fR
.sp
The \fBcoap_session_set_mtu\fR() function is used to set the MTU size (the maximum message size) of the data in a packet, excluding any IP or TCP/UDP overhead to \fImtu\fR for the client endpoint\(cqs \fIsession\fR\&. The default MTU is 1152\&.
.sp
\fBFunction: coap_session_max_pdu_size()\fR
.sp
The \fBcoap_session_max_pdu_size\fR() function is used to get the maximum MTU size of the data for the client endpoint\(cqs \fIsession\fR\&.
.SH "RETURN VALUES"
.sp
\fBcoap_new_client_session\fR(), \fBcoap_new_client_session_psk2\fR(), \fBcoap_new_client_session_pki\fR() return a newly created client\&. session or NULL if there is a creation failure\&.
.sp
\fBcoap_session_max_pdu_size\fR() returns the MTU size\&.
.SH "EXAMPLES"
.sp
\fBCoAP Client Non\-Encrypted Setup\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include
#include
static coap_session_t *
setup_client_session (struct in_addr ip_address) {
coap_session_t *session;
coap_address_t server;
/* See coap_context(3) */
coap_context_t *context = coap_new_context(NULL);
if (!context)
return NULL;
/* See coap_block(3) */
coap_context_set_block_mode(context,
COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
/* See coap_address(3) */
coap_address_init(&server);
server\&.addr\&.sa\&.sa_family = AF_INET;
server\&.addr\&.sin\&.sin_addr = ip_address;
server\&.addr\&.sin\&.sin_port = htons (5683);
session = coap_new_client_session(context, NULL, &server, COAP_PROTO_UDP);
if (!session) {
coap_free_context(context);
return NULL;
}
/* The context is in session\->context */
return session;
}
.fi
.if n \{\
.RE
.\}
.sp
\fBCoAP Client Non\-Encrypted Unix Domain Setup\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include
#include
#include
#include
static coap_session_t *
setup_client_session (const char *server_ud) {
coap_session_t *session;
coap_address_t server;
coap_address_t local;
/* See coap_context(3) */
coap_context_t *context = coap_new_context(NULL);
if (!context)
return NULL;
/* See coap_block(3) */
coap_context_set_block_mode(context,
COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
/* See coap_address(3) */
coap_address_init(&server);
server\&.addr\&.sa\&.sa_family = AF_UNIX;
snprintf(server\&.addr\&.cun\&.sun_path, sizeof(server\&.addr\&.cun\&.sun_path),
"%s", server_ud);
/* Need to have a uniquely named local address */
coap_address_init(&local);
local\&.addr\&.sa\&.sa_family = AF_UNIX;
snprintf(local\&.addr\&.cun\&.sun_path, sizeof(server\&.addr\&.cun\&.sun_path),
"/tmp/client\&.%d", getpid());
/* Only do this if you know it is safe to do so */
unlink(local\&.addr\&.cun\&.sun_path);
session = coap_new_client_session(context, &local, &server, COAP_PROTO_UDP);
if (!session) {
coap_free_context(context);
return NULL;
}
/* The context is in session\->context */
return session;
}
.fi
.if n \{\
.RE
.\}
.sp
\fBCoAP Client PKI Setup\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include
#include
static int
verify_cn_callback(const char *cn,
const uint8_t *asn1_public_cert,
size_t asn1_length,
coap_session_t *c_session,
unsigned int depth,
int validated,
void *arg
) {
/* Remove (void) definition if variable is used */
(void)cn;
(void)asn1_public_cert;
(void)asn1_length;
(void)c_session;
(void)depth;
(void)validated;
(void)arg;
/* Check that the CN is valid */
/* \&.\&.\&. */
return 1;
}
static coap_session_t *
setup_client_session_pki (struct in_addr ip_address,
const char *public_cert_file,
const char *private_key_file,
const char *ca_file
) {
coap_session_t *session;
coap_address_t server;
coap_dtls_pki_t dtls_pki;
/* See coap_context(3) */
coap_context_t *context = coap_new_context(NULL);
if (!context)
return NULL;
/* See coap_block(3) */
coap_context_set_block_mode(context,
COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
/* See coap_address(3) */
coap_address_init(&server);
server\&.addr\&.sa\&.sa_family = AF_INET;
server\&.addr\&.sin\&.sin_addr = ip_address;
server\&.addr\&.sin\&.sin_port = htons (5684);
memset (&dtls_pki, 0, sizeof (dtls_pki));
/* See coap_encryption(3) */
dtls_pki\&.version = COAP_DTLS_PKI_SETUP_VERSION;
dtls_pki\&.verify_peer_cert = 1;
dtls_pki\&.check_common_ca = 1;
dtls_pki\&.allow_self_signed = 1;
dtls_pki\&.allow_expired_certs = 1;
dtls_pki\&.cert_chain_validation = 1;
dtls_pki\&.cert_chain_verify_depth = 1;
dtls_pki\&.check_cert_revocation = 1;
dtls_pki\&.allow_no_crl = 1;
dtls_pki\&.allow_expired_crl = 1;
dtls_pki\&.allow_bad_md_hash = 0;
dtls_pki\&.allow_short_rsa_length = 0;
dtls_pki\&.is_rpk_not_cert = 0; /* Set to 1 if RPK */
dtls_pki\&.validate_cn_call_back = verify_cn_callback;
dtls_pki\&.cn_call_back_arg = NULL;
dtls_pki\&.validate_sni_call_back = NULL;
dtls_pki\&.sni_call_back_arg = NULL;
dtls_pki\&.additional_tls_setup_call_back = NULL;
dtls_pki\&.client_sni = NULL;
dtls_pki\&.pki_key\&.key_type = COAP_PKI_KEY_PEM;
dtls_pki\&.pki_key\&.key\&.pem\&.ca_file = ca_file;
dtls_pki\&.pki_key\&.key\&.pem\&.public_cert = public_cert_file;
dtls_pki\&.pki_key\&.key\&.pem\&.private_key = private_key_file;
session = coap_new_client_session_pki(context, NULL, &server,
COAP_PROTO_DTLS, &dtls_pki);
if (!session) {
coap_free_context(context);
return NULL;
}
/* The context is in session\->context */
return session;
}
.fi
.if n \{\
.RE
.\}
.sp
\fBCoAP Client PSK Setup\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include
#include
#include
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
static const coap_dtls_cpsk_info_t *
verify_ih_callback(coap_str_const_t *hint,
coap_session_t *c_session,
void *arg
) {
coap_dtls_cpsk_info_t *psk_info = (coap_dtls_cpsk_info_t *)arg;
/* Remove (void) definition if variable is used */
(void)c_session;
coap_log_info("Identity Hint \*(Aq%\&.*s\*(Aq provided\en", (int)hint\->length, hint\->s);
/* Just use the defined information for now as passed in by arg */
return psk_info;
}
static coap_dtls_cpsk_t dtls_psk;
static char client_sni[256];
static coap_session_t *
setup_client_session_psk (const char *uri,
struct in_addr ip_address,
const uint8_t *identity,
unsigned int identity_len,
const uint8_t *key,
unsigned int key_len
) {
coap_session_t *session;
coap_address_t server;
/* See coap_context(3) */
coap_context_t *context = coap_new_context(NULL);
if (!context)
return NULL;
/* See coap_block(3) */
coap_context_set_block_mode(context,
COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
/* See coap_address(3) */
coap_address_init(&server);
server\&.addr\&.sa\&.sa_family = AF_INET;
server\&.addr\&.sin\&.sin_addr = ip_address;
server\&.addr\&.sin\&.sin_port = htons (5684);
/* See coap_encryption(3) */
memset (&dtls_psk, 0, sizeof(dtls_psk));
dtls_psk\&.version = COAP_DTLS_CPSK_SETUP_VERSION;
dtls_psk\&.validate_ih_call_back = verify_ih_callback;
dtls_psk\&.ih_call_back_arg = &dtls_psk\&.psk_info;
if (uri)
memcpy(client_sni, uri, min(strlen(uri), sizeof(client_sni)\-1));
else
memcpy(client_sni, "localhost", 9);
dtls_psk\&.client_sni = client_sni;
dtls_psk\&.psk_info\&.identity\&.s = identity;
dtls_psk\&.psk_info\&.identity\&.length = identity_len;
dtls_psk\&.psk_info\&.key\&.s = key;
dtls_psk\&.psk_info\&.key\&.length = key_len;
session = coap_new_client_session_psk2(context, NULL, &server,
COAP_PROTO_DTLS, &dtls_psk);
if (!session) {
coap_free_context(context);
return NULL;
}
/* The context is in session\->context */
return session;
}
.fi
.if n \{\
.RE
.\}
.sp
\fBCoAP Client Anonymous PKI Setup\fR
.sp
.if n \{\
.RS 4
.\}
.nf
#include
#include
static coap_session_t *
setup_client_session_dtls (struct in_addr ip_address) {
coap_session_t *session;
coap_address_t server;
/* See coap_context(3) */
coap_context_t *context = coap_new_context(NULL);
if (!context)
return NULL;
/* See coap_block(3) */
coap_context_set_block_mode(context,
COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);
/* See coap_address(3) */
coap_address_init(&server);
server\&.addr\&.sa\&.sa_family = AF_INET;
server\&.addr\&.sin\&.sin_addr = ip_address;
server\&.addr\&.sin\&.sin_port = htons (5683);
session = coap_new_client_session(context, NULL, &server,
COAP_PROTO_DTLS);
if (!session) {
coap_free_context(context);
return NULL;
}
/* The context is in session\->context */
return session;
}
.fi
.if n \{\
.RE
.\}
.SH "SEE ALSO"
.sp
\fBcoap_address\fR(3), \fBcoap_block\fR(3), \fBcoap_context\fR(3), \fBcoap_encryption\fR(3), \fBcoap_endpoint_server\fR(3), \fBcoap_resource\fR(3), \fBcoap_session\fR(3) and \fBcoap_tls_library\fR(3)
.SH "FURTHER INFORMATION"
.sp
See
.sp
"RFC7252: The Constrained Application Protocol (CoAP)"
.sp
"RFC8323: CoAP (Constrained Application Protocol) over TCP, TLS, and WebSockets"
.sp
for further information\&.
.SH "BUGS"
.sp
Please report bugs on the mailing list for libcoap: libcoap\-developers@lists\&.sourceforge\&.net or raise an issue on GitHub at https://github\&.com/obgm/libcoap/issues
.SH "AUTHORS"
.sp
The libcoap project