64 #define LOG_MODULE "coap-uip" 65 #define LOG_LEVEL LOG_LEVEL_COAP 73 #if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - 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 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 82 #if NETSTACK_CONF_WITH_IPV6 83 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 85 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) 89 static dtls_handler_t cb;
90 static dtls_context_t *dtls_context = NULL;
96 PROCESS(coap_engine,
"CoAP Engine");
105 LOG_OUTPUT(
"(NULL EP)");
109 LOG_OUTPUT(
"coaps://[");
111 LOG_OUTPUT(
"coap://[");
114 LOG_OUTPUT(
"]:%u", uip_ntohs(ep->port));
130 printf(
"]:%u", uip_ntohs(ep->port));
137 if(buf == NULL || size == 0) {
141 n = snprintf(buf, size - 1,
"(NULL EP)");
144 n = snprintf(buf, size - 1,
"coaps://[");
146 n = snprintf(buf, size - 1,
"coap://[");
152 n += snprintf(&buf[n], size -n - 1,
"]:%u", uip_ntohs(ep->port));
156 buf[size - 1] =
'\0';
163 const coap_endpoint_t *from)
166 destination->port = from->port;
167 destination->secure = from->secure;
173 if(!uip_ipaddr_cmp(&e1->ipaddr, &e2->ipaddr)) {
176 return e1->port == e2->port && e1->secure == e2->secure;
180 index_of(
const char *data,
int offset,
int len, uint8_t c)
185 for(; offset < len; offset++) {
186 if(data[offset] == c) {
194 get_port(
const char *inbuf,
size_t len, uint32_t *value)
198 for(i = 0; i < len; i++) {
199 if(inbuf[i] >=
'0' && inbuf[i] <=
'9') {
200 *value = *value * 10 + (inbuf[i] -
'0');
212 int start = index_of(text, 0, size,
'[');
213 int end = index_of(text, start, size,
']');
216 ep->secure = strncmp(text,
"coaps:", 6) == 0;
217 if(start >= 0 && end > start &&
219 if(text[end + 1] ==
':' &&
220 get_port(text + end + 2, size - end - 2, &port)) {
222 }
else if(ep->secure) {
224 ep->port = SERVER_LISTEN_SECURE_PORT;
226 ep->port = SERVER_LISTEN_PORT;
229 }
else if(size < UIPLIB_IPV6_MAX_STR_LEN) {
230 char buf[UIPLIB_IPV6_MAX_STR_LEN];
231 memcpy(buf, text, size);
234 ep->port = SERVER_LISTEN_PORT;
241 static const coap_endpoint_t *
242 get_src_endpoint(uint8_t secure)
244 static coap_endpoint_t src;
246 src.port = UIP_UDP_BUF->srcport;
260 #ifndef CONTIKI_TARGET_NATIVE 268 if(ep != NULL && ep->secure != 0) {
270 if(dtls_context == NULL) {
273 peer = dtls_get_peer(dtls_context, ep);
276 LOG_DBG(
"DTLS peer state for ");
278 LOG_DBG_(
" is %d (%sconnected)\n", peer->state,
279 dtls_peer_is_connected(peer) ?
"" :
"not ");
280 return dtls_peer_is_connected(peer);
282 LOG_DBG(
"DTLS did not find peer ");
297 if(ep->secure == 0) {
298 LOG_DBG(
"connect to ");
305 LOG_DBG(
"DTLS connect to ");
311 dtls_connect(dtls_context, ep);
323 if(ep && ep->secure && dtls_context) {
324 dtls_close(dtls_context, ep);
342 #if COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE 351 process_secure_data(
void)
353 LOG_INFO(
"receiving secure UDP datagram from [");
355 LOG_INFO_(
"]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport));
359 dtls_handle_message(dtls_context, (coap_endpoint_t *)get_src_endpoint(1),
368 LOG_INFO(
"receiving UDP datagram from [");
370 LOG_INFO_(
"]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport));
377 coap_sendto(
const coap_endpoint_t *ep,
const uint8_t *data, uint16_t length)
380 LOG_WARN(
"failed to send - no endpoint\n");
385 LOG_WARN(
"endpoint ");
386 LOG_WARN_COAP_EP(ep);
387 LOG_WARN_(
" not connected - dropping packet\n");
396 ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length);
397 LOG_INFO(
"sent DTLS to ");
398 LOG_INFO_COAP_EP(ep);
400 LOG_INFO_(
" - error %d\n", ret);
402 LOG_INFO_(
" %d/%u bytes\n", ret, length);
406 LOG_WARN(
"no DTLS context\n");
412 uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port);
413 LOG_INFO(
"sent to ");
414 LOG_INFO_COAP_EP(ep);
415 LOG_INFO_(
" %u bytes\n", length);
424 udp_conn =
udp_new(NULL, 0, NULL);
425 udp_bind(udp_conn, SERVER_LISTEN_PORT);
426 LOG_INFO(
"Listening on port %u\n", uip_ntohs(udp_conn->
lport));
430 dtls_conn =
udp_new(NULL, 0, NULL);
431 if(dtls_conn != NULL) {
432 udp_bind(dtls_conn, SERVER_LISTEN_SECURE_PORT);
433 LOG_INFO(
"DTLS listening on port %u\n", uip_ntohs(dtls_conn->
lport));
434 dtls_context = dtls_new_context(dtls_conn);
437 LOG_WARN(
"DTLS: cannot create context\n");
439 dtls_set_handler(dtls_context, &cb);
450 process_secure_data();
469 input_from_peer(
struct dtls_context_t *ctx,
470 session_t *session, uint8_t *data,
size_t len)
474 if(LOG_DBG_ENABLED) {
475 LOG_DBG(
"received DTLS data:");
476 for(i = 0; i < len; i++) {
477 LOG_DBG_(
"%c", data[i]);
481 for(i = 0; i < len; i++) {
482 LOG_DBG_(
"%02x", data[i]);
490 coap_receive(session, data, len);
497 output_to_peer(
struct dtls_context_t *ctx,
498 session_t *session, uint8_t *data,
size_t len)
500 struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx);
501 LOG_DBG(
"output_to DTLS peer [");
502 LOG_DBG_6ADDR(&session->ipaddr);
503 LOG_DBG_(
"]:%u %ld bytes\n", uip_ntohs(session->port), (
long)len);
504 uip_udp_packet_sendto(udp_connection, data, len,
505 &session->ipaddr, session->port);
513 dtls_keystore = keystore;
520 get_psk_info(
struct dtls_context_t *ctx,
521 const session_t *session,
522 dtls_credentials_type_t type,
523 const unsigned char *
id,
size_t id_len,
524 unsigned char *result,
size_t result_length)
528 if(dtls_keystore == NULL) {
529 LOG_DBG(
"--- No key store available ---\n");
533 memset(&ks, 0,
sizeof(ks));
534 LOG_DBG(
"---===>>> Getting the Key or ID <<<===---\n");
536 case DTLS_PSK_IDENTITY:
538 ks.identity_hint = id;
539 ks.identity_hint_len = id_len;
540 LOG_DBG(
"got psk_identity_hint: '");
541 LOG_DBG_COAP_STRING((
const char *)
id, id_len);
545 if(dtls_keystore->coap_get_psk_info) {
547 dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks);
549 if(ks.identity == NULL || ks.identity_len == 0) {
550 LOG_DBG(
"no psk_identity found\n");
554 if(result_length < ks.identity_len) {
555 LOG_DBG(
"cannot return psk_identity -- buffer too small\n");
556 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
558 memcpy(result, ks.identity, ks.identity_len);
559 LOG_DBG(
"psk_identity with %u bytes found\n", ks.identity_len);
560 return ks.identity_len;
563 if(dtls_keystore->coap_get_psk_info) {
565 ks.identity_len = id_len;
567 dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks);
569 if(ks.key == NULL || ks.key_len == 0) {
570 LOG_DBG(
"PSK for unknown id requested, exiting\n");
571 return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER);
574 if(result_length < ks.key_len) {
575 LOG_DBG(
"cannot return psk -- buffer too small\n");
576 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
578 memcpy(result, ks.key, ks.key_len);
579 LOG_DBG(
"psk with %u bytes found\n", ks.key_len);
583 LOG_WARN(
"unsupported key store request type: %d\n", type);
586 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
590 static dtls_handler_t cb = {
591 .write = output_to_peer,
592 .read = input_from_peer,
595 .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
Pointer to IP 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
static bool start(void)
Start measurement.
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.
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.