64 #define LOG_MODULE "coap-uip" 65 #define LOG_LEVEL LOG_LEVEL_COAP 73 #if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN) 74 #error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE" 77 #define SERVER_LISTEN_PORT UIP_HTONS(COAP_DEFAULT_PORT) 78 #define SERVER_LISTEN_SECURE_PORT UIP_HTONS(COAP_DEFAULT_SECURE_PORT) 81 static dtls_handler_t cb;
82 static dtls_context_t *dtls_context = NULL;
88 PROCESS(coap_engine,
"CoAP Engine");
97 LOG_OUTPUT(
"(NULL EP)");
101 LOG_OUTPUT(
"coaps://[");
103 LOG_OUTPUT(
"coap://[");
106 LOG_OUTPUT(
"]:%u", uip_ntohs(ep->port));
122 printf(
"]:%u", uip_ntohs(ep->port));
129 if(buf == NULL || size == 0) {
133 n = snprintf(buf, size - 1,
"(NULL EP)");
136 n = snprintf(buf, size - 1,
"coaps://[");
138 n = snprintf(buf, size - 1,
"coap://[");
144 n += snprintf(&buf[n], size -n - 1,
"]:%u", uip_ntohs(ep->port));
148 buf[size - 1] =
'\0';
155 const coap_endpoint_t *from)
158 destination->port = from->port;
159 destination->secure = from->secure;
165 if(!uip_ipaddr_cmp(&e1->ipaddr, &e2->ipaddr)) {
168 return e1->port == e2->port && e1->secure == e2->secure;
172 index_of(
const char *data,
int offset,
int len, uint8_t c)
177 for(; offset < len; offset++) {
178 if(data[offset] == c) {
186 get_port(
const char *inbuf,
size_t len, uint32_t *value)
190 for(i = 0; i < len; i++) {
191 if(inbuf[i] >=
'0' && inbuf[i] <=
'9') {
192 *value = *value * 10 + (inbuf[i] -
'0');
204 int start = index_of(text, 0, size,
'[');
205 int end = index_of(text, start, size,
']');
208 ep->secure = strncmp(text,
"coaps:", 6) == 0;
209 if(start >= 0 && end > start &&
211 if(text[end + 1] ==
':' &&
212 get_port(text + end + 2, size - end - 2, &port)) {
214 }
else if(ep->secure) {
216 ep->port = SERVER_LISTEN_SECURE_PORT;
218 ep->port = SERVER_LISTEN_PORT;
221 }
else if(size < UIPLIB_IPV6_MAX_STR_LEN) {
222 char buf[UIPLIB_IPV6_MAX_STR_LEN];
223 memcpy(buf, text, size);
226 ep->port = SERVER_LISTEN_PORT;
233 static const coap_endpoint_t *
234 get_src_endpoint(uint8_t secure)
236 static coap_endpoint_t src;
238 src.port = UIP_UDP_BUF->srcport;
252 #ifndef CONTIKI_TARGET_NATIVE 260 if(ep != NULL && ep->secure != 0) {
262 if(dtls_context == NULL) {
265 peer = dtls_get_peer(dtls_context, ep);
268 LOG_DBG(
"DTLS peer state for ");
270 LOG_DBG_(
" is %d (%sconnected)\n", peer->state,
271 dtls_peer_is_connected(peer) ?
"" :
"not ");
272 return dtls_peer_is_connected(peer);
274 LOG_DBG(
"DTLS did not find peer ");
289 if(ep->secure == 0) {
290 LOG_DBG(
"connect to ");
297 LOG_DBG(
"DTLS connect to ");
303 dtls_connect(dtls_context, ep);
315 if(ep && ep->secure && dtls_context) {
316 dtls_close(dtls_context, ep);
334 #if COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE 343 process_secure_data(
void)
345 LOG_INFO(
"receiving secure UDP datagram from [");
347 LOG_INFO_(
"]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport));
351 dtls_handle_message(dtls_context, (coap_endpoint_t *)get_src_endpoint(1),
360 LOG_INFO(
"receiving UDP datagram from [");
362 LOG_INFO_(
"]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport));
369 coap_sendto(
const coap_endpoint_t *ep,
const uint8_t *data, uint16_t length)
372 LOG_WARN(
"failed to send - no endpoint\n");
377 LOG_WARN(
"endpoint ");
378 LOG_WARN_COAP_EP(ep);
379 LOG_WARN_(
" not connected - dropping packet\n");
388 ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length);
389 LOG_INFO(
"sent DTLS to ");
390 LOG_INFO_COAP_EP(ep);
392 LOG_INFO_(
" - error %d\n", ret);
394 LOG_INFO_(
" %d/%u bytes\n", ret, length);
398 LOG_WARN(
"no DTLS context\n");
404 uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port);
405 LOG_INFO(
"sent to ");
406 LOG_INFO_COAP_EP(ep);
407 LOG_INFO_(
" %u bytes\n", length);
416 udp_conn =
udp_new(NULL, 0, NULL);
417 udp_bind(udp_conn, SERVER_LISTEN_PORT);
418 LOG_INFO(
"Listening on port %u\n", uip_ntohs(udp_conn->
lport));
422 dtls_conn =
udp_new(NULL, 0, NULL);
423 if(dtls_conn != NULL) {
424 udp_bind(dtls_conn, SERVER_LISTEN_SECURE_PORT);
425 LOG_INFO(
"DTLS listening on port %u\n", uip_ntohs(dtls_conn->
lport));
426 dtls_context = dtls_new_context(dtls_conn);
429 LOG_WARN(
"DTLS: cannot create context\n");
431 dtls_set_handler(dtls_context, &cb);
442 process_secure_data();
461 input_from_peer(
struct dtls_context_t *ctx,
462 session_t *session, uint8_t *data,
size_t len)
466 if(LOG_DBG_ENABLED) {
467 LOG_DBG(
"received DTLS data:");
468 for(i = 0; i < len; i++) {
469 LOG_DBG_(
"%c", data[i]);
473 for(i = 0; i < len; i++) {
474 LOG_DBG_(
"%02x", data[i]);
482 coap_receive(session, data, len);
489 output_to_peer(
struct dtls_context_t *ctx,
490 session_t *session, uint8_t *data,
size_t len)
492 struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx);
493 LOG_DBG(
"output_to DTLS peer [");
494 LOG_DBG_6ADDR(&session->ipaddr);
495 LOG_DBG_(
"]:%u %ld bytes\n", uip_ntohs(session->port), (
long)len);
496 uip_udp_packet_sendto(udp_connection, data, len,
497 &session->ipaddr, session->port);
505 dtls_keystore = keystore;
512 get_psk_info(
struct dtls_context_t *ctx,
513 const session_t *session,
514 dtls_credentials_type_t type,
515 const unsigned char *
id,
size_t id_len,
516 unsigned char *result,
size_t result_length)
520 if(dtls_keystore == NULL) {
521 LOG_DBG(
"--- No key store available ---\n");
525 memset(&ks, 0,
sizeof(ks));
526 LOG_DBG(
"---===>>> Getting the Key or ID <<<===---\n");
528 case DTLS_PSK_IDENTITY:
530 ks.identity_hint = id;
531 ks.identity_hint_len = id_len;
532 LOG_DBG(
"got psk_identity_hint: '");
533 LOG_DBG_COAP_STRING((
const char *)
id, id_len);
537 if(dtls_keystore->coap_get_psk_info) {
539 dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks);
541 if(ks.identity == NULL || ks.identity_len == 0) {
542 LOG_DBG(
"no psk_identity found\n");
546 if(result_length < ks.identity_len) {
547 LOG_DBG(
"cannot return psk_identity -- buffer too small\n");
548 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
550 memcpy(result, ks.identity, ks.identity_len);
551 LOG_DBG(
"psk_identity with %u bytes found\n", ks.identity_len);
552 return ks.identity_len;
555 if(dtls_keystore->coap_get_psk_info) {
557 ks.identity_len = id_len;
559 dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks);
561 if(ks.key == NULL || ks.key_len == 0) {
562 LOG_DBG(
"PSK for unknown id requested, exiting\n");
563 return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER);
566 if(result_length < ks.key_len) {
567 LOG_DBG(
"cannot return psk -- buffer too small\n");
568 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
570 memcpy(result, ks.key, ks.key_len);
571 LOG_DBG(
"psk with %u bytes found\n", ks.key_len);
575 LOG_WARN(
"unsupported key store request type: %d\n", type);
578 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
582 static dtls_handler_t cb = {
583 .write = output_to_peer,
584 .read = input_from_peer,
587 .get_psk_info = get_psk_info,
int coap_endpoint_connect(coap_endpoint_t *ep)
Request a connection to a CoAP endpoint.
#define UIP_IP_BUF
Direct access to IPv6 header.
void coap_endpoint_print(const coap_endpoint_t *ep)
Print a CoAP endpoint.
#define PROCESS(name, strname)
Declare a process.
void coap_endpoint_log(const coap_endpoint_t *ep)
Print a CoAP endpoint via the logging module.
void coap_endpoint_copy(coap_endpoint_t *destination, const coap_endpoint_t *from)
Copy a CoAP endpoint from one memory area to another.
API to address CoAP endpoints
A simple keystore with fixed credentials.
#define PROCESS_BEGIN()
Define the beginning of a process.
CoAP engine implementation.
#define PROCESS_END()
Define the end of a process.
process_event_t tcpip_event
The uIP event.
int coap_endpoint_snprint(char *buf, size_t size, const coap_endpoint_t *ep)
Print a CoAP endpoint to a string.
Header file for module for sending UDP packets through uIP.
uint16_t lport
The local port number in network byte order.
static void start(void)
Start measurement.
int coap_endpoint_is_connected(const coap_endpoint_t *ep)
Check if a CoAP endpoint is connected.
Header file for the IP address manipulation library.
#define uip_newdata()
Is new incoming data available?
The structure of a CoAP keystore.
void coap_set_keystore(const coap_keystore_t *keystore)
Set the CoAP keystore to use by CoAP.
struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
int coap_sendto(const coap_endpoint_t *ep, const uint8_t *data, uint16_t length)
Send a message to the specified CoAP endpoint.
Routing driver header file
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
int coap_endpoint_parse(const char *text, size_t size, coap_endpoint_t *ep)
Parse a CoAP endpoint.
uint8_t * coap_databuf(void)
Returns a common data buffer that can be used when generating CoAP messages for transmission.
#define PROCESS_YIELD()
Yield the currently running process.
void coap_transport_init(void)
Initialize the CoAP transport.
The structure of a CoAP pre-shared key info.
void log_6addr(const uip_ipaddr_t *ipaddr)
Logs an IPv6 address.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
int coap_endpoint_cmp(const coap_endpoint_t *e1, const coap_endpoint_t *e2)
Compare two CoAP endpoints.
void coap_endpoint_disconnect(coap_endpoint_t *ep)
Request that any connection to a CoAP endpoint is discontinued.
int coap_endpoint_is_secure(const coap_endpoint_t *ep)
Check if a CoAP endpoint is secure (encrypted).
void coap_keystore_simple_init(void)
Registers a simple CoAP DTLS keystore with fixed pre-shared key credentials.
void uiplib_ipaddr_print(const uip_ipaddr_t *addr)
Print an IP address using printf().
CoAP module for reliable transport
An implementation of the Constrained Application Protocol (RFC 7252).
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
#define uiplib_ipaddrconv
Convert a textual representation of an IP address to a numerical representation.
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
void * uip_appdata
Pointer to the application data in the packet buffer.
int(* node_is_reachable)(void)
Tells whether the node is currently reachable as part of the network.
Collection of constants specified in the CoAP standard.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
void process_start(struct process *p, process_data_t data)
Start a process.
Representation of a uIP UDP connection.
int uiplib_ipaddr_snprint(char *buf, size_t size, const uip_ipaddr_t *addr)
Write at most size - 1 characters of the IP address to the output string.