|
libcoap 4.3.5-develop-e78a250
|
coap_call_home, coap_session_set_type_client, coap_session_set_type_server, coap_call_home_stop_reconnecting - Work with CoAP Call-Home
#include <coap3/coap.h>
int coap_session_set_type_client(coap_session_t *session);
int coap_session_set_type_server(coap_session_t *session);
void coap_call_home_stop_reconnecting(coap_session_t *session);
For specific (D)TLS library support, link with -lcoap-3-notls, -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls, -lcoap-3-wolfssl or -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default (D)TLS library support.
This man page focuses on the CoAP Call-Home support where a CoAP-Server initiates a session connection to a CoAP-Client, and the CoAP-Client on receipt of a new connection then starts issuing requests to the CoAP-Server.
The CoAP-Client sets up an new listening endpoint using coap_new_endpoint(3) and waits for a new incoming connection. Once the session is established (i.e. (D)TLS has completed the handshakes) then the session needs to be converted from type Server to type Client (using coap_session_set_type_client()) before making any CoAP requests.
The Coap-Server initiates a new client connection to the CoAP-Client, on success the session needs to be converted from type Client to type Server (using coap_session_set_type_server()) to handle the incoming requests from CoAP-Client.
If coap_context_set_session_reconnect_time2(3) has been called, then the CoAP-Server will continue trying to reconnect to the CoAP-Client at the specified intervals if there is a session failure for the defined retry count.
Function: coap_session_set_type_client()
The coap_session_set_type_client() function is used to convert the session from a session endpoint type of Server to Client. This typically is used in a Call-Home type environment where the roles have to change following the establishment of a session on an listening endpoint. The reference count is incremented by 1 so that the now type Client session does not expire until a coap_session_release() is done.
NOTE: This function will fail for a DTLS server type session if done before the ClientHello is seen. It should be called on receipt of event COAP_EVENT_SERVER_SESSION_CONNECTED in the event handler.
Function: coap_session_set_type_server()
The coap_session_set_type_server() function is used to convert the session from a session endpoint (as initiated by CoAP-Server) type of Client to Server. This typically is used in a Call-Home type environment where the roles have to change following the establishment of a session. The reference count is decremented by 1 so that the now type Server _session acts as a normal server, timing out when idle etc. This function should be immediately called after a successful coap_new_client_session(3) type of function.
NOTE: Although the now server session may have timed out, this does not mean that the CoAP-Server will exit even all Call-Homes have completed and it is not listening on any endpoint.
NOTE: If coap_context_set_session_reconnect_time2(3) has been used, then the Call-Home session will get re-used for trying a new connection and so will not time out like a normal server session until the retry count is reached (or for ever if retry count is 0)..
Function: coap_call_home_stop_reconnecting()
The coap_call_home_stop_reconnecting() function is used to stop a CoAP-Server trying to reconnect to a CoAP-Client if coap_context_set_session_reconnect_time2(3) is in use for session. This session will then time out when idle.
coap_session_set_type_client() and coap_session_set_type_server() return 1 on success, otherwise 0.
CoAP-Client Set Up*
#include <coap3/coap.h>
static coap_session_t *call_home_session = NULL;
static int quit = 0;
static int
event_handler(coap_session_t *session COAP_UNUSED,
const coap_event_t event) {
switch (event) {
case COAP_EVENT_TCP_CLOSED:
case COAP_EVENT_DTLS_CLOSED:
case COAP_EVENT_SESSION_CLOSED:
case COAP_EVENT_OSCORE_DECRYPTION_FAILURE:
case COAP_EVENT_OSCORE_NOT_ENABLED:
case COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD:
case COAP_EVENT_OSCORE_NO_SECURITY:
case COAP_EVENT_OSCORE_INTERNAL_ERROR:
case COAP_EVENT_OSCORE_DECODE_ERROR:
case COAP_EVENT_WS_PACKET_SIZE:
case COAP_EVENT_WS_CLOSED:
case COAP_EVENT_BAD_PACKET:
case COAP_EVENT_RECONNECT_NO_MORE:
quit = 1;
break;
case COAP_EVENT_SERVER_SESSION_CONNECTED:
call_home_session = session;
coap_session_set_type_client(session);
break;
case COAP_EVENT_DTLS_CONNECTED:
case COAP_EVENT_DTLS_RENEGOTIATE:
case COAP_EVENT_DTLS_ERROR:
case COAP_EVENT_TCP_CONNECTED:
case COAP_EVENT_TCP_FAILED:
case COAP_EVENT_SESSION_CONNECTED:
case COAP_EVENT_SESSION_FAILED:
case COAP_EVENT_PARTIAL_BLOCK:
case COAP_EVENT_XMIT_BLOCK_FAIL:
case COAP_EVENT_SERVER_SESSION_NEW:
case COAP_EVENT_SERVER_SESSION_DEL:
case COAP_EVENT_MSG_RETRANSMITTED:
case COAP_EVENT_WS_CONNECTED:
case COAP_EVENT_KEEPALIVE_FAILURE:
case COAP_EVENT_RECONNECT_FAILED:
case COAP_EVENT_RECONNECT_SUCCESS:
case COAP_EVENT_RECONNECT_STARTED:
default:
break;
}
return 0;
}
static coap_session_t *
get_call_home_session(coap_context_t *context) {
coap_endpoint_t *endpoint;
coap_address_t listen_addr;
/* See coap_address(3) */
coap_address_init(&listen_addr);
listen_addr.addr.sa.sa_family = AF_INET;
listen_addr.addr.sin.sin_port = htons(5683);
endpoint = coap_new_endpoint(context, &listen_addr, COAP_PROTO_UDP);
if (!endpoint) {
return NULL;
}
/* Need to wait for a session to come in */
while (!quit && !call_home_session) {
coap_io_process(context, 1000);
}
return call_home_session;
}
int
main(int argc, char **argv) {
coap_context_t *context;
coap_session_t *session;
(void)argc;
(void)argv;
coap_startup();
/* Other initialization code */
context = coap_new_context(NULL);
/* Other initialization code */
coap_register_event_handler(context, event_handler);
session = get_call_home_session(context);
if (!session)
return 1;
/* Other stuff - e.g. create PDUs and send them */
/* Clean up library usage */
coap_session_release(session);
coap_free_context(context);
coap_cleanup();
return 0;
}CoAP-Server Set Up*
#include <coap3/coap.h>
#include <stdio.h>
static int
do_call_home(coap_context_t *ctx, coap_str_const_t host, uint16_t port, coap_uri_scheme_t scheme) {
coap_address_t dst;
coap_addr_info_t *info_list = NULL;
coap_session_t *session = NULL;
coap_proto_t proto;
/* resolve destination address where call-home should be sent */
info_list = coap_resolve_address_info(&host, port, port, port, port,
0,
1 << scheme,
COAP_RESOLVE_TYPE_REMOTE);
if (info_list == NULL) {
return 0;
}
proto = info_list->proto;
memcpy(&dst, &info_list->addr, sizeof(dst));
coap_free_address_info(info_list);
switch (scheme) {
case COAP_URI_SCHEME_COAP:
case COAP_URI_SCHEME_COAP_TCP:
case COAP_URI_SCHEME_COAP_WS:
session = coap_new_client_session(ctx, NULL, &dst, proto);
break;
case COAP_URI_SCHEME_COAPS:
case COAP_URI_SCHEME_COAPS_TCP:
case COAP_URI_SCHEME_COAPS_WS:
/* Do the (D)TLS PKI/PSK setup */
break;
case COAP_URI_SCHEME_HTTP:
case COAP_URI_SCHEME_HTTPS:
case COAP_URI_SCHEME_LAST:
default:
assert(0);
break;
}
if (!session) {
return 0;
}
coap_session_set_type_server(session);
return 1;
}
int
main(int argc, char **argv) {
coap_context_t *context;
coap_uri_t call_home_uri;
(void)argc;
(void)argv;
coap_startup();
/* Other initialization code */
context = coap_new_context(NULL);
/* Initialize resources - See coap_resource(3) init_resources() example */
if (coap_split_uri((uint8_t *)argv[1], strlen(argv[1]), &call_home_uri) < 0 ||
call_home_uri.path.length != 0 || call_home_uri.query.length != 0) {
fprintf(stderr, "invalid CoAP URI '%s'\n", argv[1]);
exit(1);
}
/*
* Use coap_context_set_session_reconnect_time2(3) if you want this session to retry
* connecting if the CoAP-Client stops working.
*/
do_call_home(context, call_home_uri.host, call_home_uri.port, call_home_uri.scheme);
/* Other initialization code */
/* coap_io_process(3) loop */
/* Clean up library usage */
coap_free_context(context);
coap_cleanup();
}See
"RFC7252: The Constrained Application Protocol (CoAP)"
for further information.
Please raise an issue on GitHub at https://github.com/obgm/libcoap/issues to report any bugs.
Please raise a Pull Request at https://github.com/obgm/libcoap/pulls for any fixes.