67 #define LOG_MODULE "coap-uip" 68 #define LOG_LEVEL LOG_LEVEL_COAP 76 #if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN) 77 #error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE" 80 #define SERVER_LISTEN_PORT UIP_HTONS(COAP_DEFAULT_PORT) 81 #define SERVER_LISTEN_SECURE_PORT UIP_HTONS(COAP_DEFAULT_SECURE_PORT) 84 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 85 #if NETSTACK_CONF_WITH_IPV6 86 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 88 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) 92 static dtls_handler_t cb;
93 static dtls_context_t *dtls_context = NULL;
99 PROCESS(coap_engine,
"CoAP Engine");
108 LOG_OUTPUT(
"(NULL EP)");
112 LOG_OUTPUT(
"coaps://[");
114 LOG_OUTPUT(
"coap://[");
117 LOG_OUTPUT(
"]:%u", uip_ntohs(ep->port));
133 printf(
"]:%u", uip_ntohs(ep->port));
140 if(buf == NULL || size == 0) {
144 n = snprintf(buf, size - 1,
"(NULL EP)");
147 n = snprintf(buf, size - 1,
"coaps://[");
149 n = snprintf(buf, size - 1,
"coap://[");
155 n += snprintf(&buf[n], size -n - 1,
"]:%u", uip_ntohs(ep->port));
159 buf[size - 1] =
'\0';
166 const coap_endpoint_t *from)
169 destination->port = from->port;
170 destination->secure = from->secure;
176 if(!uip_ipaddr_cmp(&e1->ipaddr, &e2->ipaddr)) {
179 return e1->port == e2->port && e1->secure == e2->secure;
183 index_of(
const char *data,
int offset,
int len, uint8_t c)
188 for(; offset < len; offset++) {
189 if(data[offset] == c) {
197 get_port(
const char *inbuf,
size_t len, uint32_t *value)
201 for(i = 0; i < len; i++) {
202 if(inbuf[i] >=
'0' && inbuf[i] <=
'9') {
203 *value = *value * 10 + (inbuf[i] -
'0');
215 int start = index_of(text, 0, size,
'[');
216 int end = index_of(text, start, size,
']');
219 ep->secure = strncmp(text,
"coaps:", 6) == 0;
220 if(start >= 0 && end > start &&
222 if(text[end + 1] ==
':' &&
223 get_port(text + end + 2, size - end - 2, &port)) {
225 }
else if(ep->secure) {
227 ep->port = SERVER_LISTEN_SECURE_PORT;
229 ep->port = SERVER_LISTEN_PORT;
232 }
else if(size < UIPLIB_IPV6_MAX_STR_LEN) {
233 char buf[UIPLIB_IPV6_MAX_STR_LEN];
234 memcpy(buf, text, size);
237 ep->port = SERVER_LISTEN_PORT;
244 static const coap_endpoint_t *
245 get_src_endpoint(uint8_t secure)
247 static coap_endpoint_t src;
249 src.port = UIP_UDP_BUF->srcport;
263 #if UIP_CONF_IPV6_RPL 264 #ifndef CONTIKI_TARGET_NATIVE 272 if(ep != NULL && ep->secure != 0) {
274 if(dtls_context == NULL) {
277 peer = dtls_get_peer(dtls_context, ep);
280 LOG_DBG(
"DTLS peer state for ");
282 LOG_DBG_(
" is %d (%sconnected)\n", peer->state,
283 dtls_peer_is_connected(peer) ?
"" :
"not ");
284 return dtls_peer_is_connected(peer);
286 LOG_DBG(
"DTLS did not find peer ");
301 if(ep->secure == 0) {
302 LOG_DBG(
"connect to ");
309 LOG_DBG(
"DTLS connect to ");
315 dtls_connect(dtls_context, ep);
327 if(ep && ep->secure && dtls_context) {
328 dtls_close(dtls_context, ep);
346 #if COAP_DTLS_KEYSTORE_CONF_WITH_SIMPLE 355 process_secure_data(
void)
357 LOG_INFO(
"receiving secure UDP datagram from [");
359 LOG_INFO_(
"]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport));
363 dtls_handle_message(dtls_context, (coap_endpoint_t *)get_src_endpoint(1),
372 LOG_INFO(
"receiving UDP datagram from [");
374 LOG_INFO_(
"]:%u\n", uip_ntohs(UIP_UDP_BUF->srcport));
381 coap_sendto(
const coap_endpoint_t *ep,
const uint8_t *data, uint16_t length)
384 LOG_WARN(
"failed to send - no endpoint\n");
389 LOG_WARN(
"endpoint ");
390 LOG_WARN_COAP_EP(ep);
391 LOG_WARN_(
" not connected - dropping packet\n");
400 ret = dtls_write(dtls_context, (session_t *)ep, (uint8_t *)data, length);
401 LOG_INFO(
"sent DTLS to ");
402 LOG_INFO_COAP_EP(ep);
404 LOG_INFO_(
" - error %d\n", ret);
406 LOG_INFO_(
" %d/%u bytes\n", ret, length);
410 LOG_WARN(
"no DTLS context\n");
416 uip_udp_packet_sendto(udp_conn, data, length, &ep->ipaddr, ep->port);
417 LOG_INFO(
"sent to ");
418 LOG_INFO_COAP_EP(ep);
419 LOG_INFO_(
" %u bytes\n", length);
428 udp_conn =
udp_new(NULL, 0, NULL);
429 udp_bind(udp_conn, SERVER_LISTEN_PORT);
430 LOG_INFO(
"Listening on port %u\n", uip_ntohs(udp_conn->
lport));
434 dtls_conn =
udp_new(NULL, 0, NULL);
435 if(dtls_conn != NULL) {
436 udp_bind(dtls_conn, SERVER_LISTEN_SECURE_PORT);
437 LOG_INFO(
"DTLS listening on port %u\n", uip_ntohs(dtls_conn->
lport));
438 dtls_context = dtls_new_context(dtls_conn);
441 LOG_WARN(
"DTLS: cannot create context\n");
443 dtls_set_handler(dtls_context, &cb);
454 process_secure_data();
473 input_from_peer(
struct dtls_context_t *ctx,
474 session_t *session, uint8_t *data,
size_t len)
478 if(LOG_DBG_ENABLED) {
479 LOG_DBG(
"received DTLS data:");
480 for(i = 0; i < len; i++) {
481 LOG_DBG_(
"%c", data[i]);
485 for(i = 0; i < len; i++) {
486 LOG_DBG_(
"%02x", data[i]);
494 coap_receive(session, data, len);
501 output_to_peer(
struct dtls_context_t *ctx,
502 session_t *session, uint8_t *data,
size_t len)
504 struct uip_udp_conn *udp_connection = dtls_get_app_data(ctx);
505 LOG_DBG(
"output_to DTLS peer [");
506 LOG_DBG_6ADDR(&session->ipaddr);
507 LOG_DBG_(
"]:%u %ld bytes\n", uip_ntohs(session->port), (
long)len);
508 uip_udp_packet_sendto(udp_connection, data, len,
509 &session->ipaddr, session->port);
517 dtls_keystore = keystore;
524 get_psk_info(
struct dtls_context_t *ctx,
525 const session_t *session,
526 dtls_credentials_type_t type,
527 const unsigned char *
id,
size_t id_len,
528 unsigned char *result,
size_t result_length)
532 if(dtls_keystore == NULL) {
533 LOG_DBG(
"--- No key store available ---\n");
537 memset(&ks, 0,
sizeof(ks));
538 LOG_DBG(
"---===>>> Getting the Key or ID <<<===---\n");
540 case DTLS_PSK_IDENTITY:
542 ks.identity_hint = id;
543 ks.identity_hint_len = id_len;
544 LOG_DBG(
"got psk_identity_hint: '");
545 LOG_DBG_COAP_STRING((
const char *)
id, id_len);
549 if(dtls_keystore->coap_get_psk_info) {
551 dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks);
553 if(ks.identity == NULL || ks.identity_len == 0) {
554 LOG_DBG(
"no psk_identity found\n");
558 if(result_length < ks.identity_len) {
559 LOG_DBG(
"cannot return psk_identity -- buffer too small\n");
560 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
562 memcpy(result, ks.identity, ks.identity_len);
563 LOG_DBG(
"psk_identity with %u bytes found\n", ks.identity_len);
564 return ks.identity_len;
567 if(dtls_keystore->coap_get_psk_info) {
569 ks.identity_len = id_len;
571 dtls_keystore->coap_get_psk_info((coap_endpoint_t *)session, &ks);
573 if(ks.key == NULL || ks.key_len == 0) {
574 LOG_DBG(
"PSK for unknown id requested, exiting\n");
575 return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER);
578 if(result_length < ks.key_len) {
579 LOG_DBG(
"cannot return psk -- buffer too small\n");
580 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
582 memcpy(result, ks.key, ks.key_len);
583 LOG_DBG(
"psk with %u bytes found\n", ks.key_len);
587 LOG_WARN(
"unsupported key store request type: %d\n", type);
590 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
594 static dtls_handler_t cb = {
595 .write = output_to_peer,
596 .read = input_from_peer,
599 .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
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.
rpl_dag_t * rpl_get_any_dag(void)
Returns pointer to any DAG (for compatibility with legagy RPL code)
#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 udp_bind(conn, port)
Bind a UDP connection to a local port.
void * uip_appdata
Pointer to the application data in the packet buffer.
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.