/*---------------------------------------------------------------------------*/ static int event(struct dtls_context_t *ctx, session_t *session, dtls_alert_level_t level, unsigned short code) { coap_context_t *coap_ctx; coap_ctx = dtls_get_app_data(ctx); if(coap_ctx == COAP_CONTEXT_NONE || coap_ctx->is_used == 0) { /* The context is no longer in use */ } else if(code == DTLS_EVENT_CONNECTED) { coap_ctx->status = STATUS_CONNECTED; PRINTF("coap-context: DTLS CLIENT CONNECTED!\n"); process_post(coap_ctx->process, coap_context_event, coap_ctx); } else if(code == DTLS_EVENT_CONNECT || code == DTLS_EVENT_RENEGOTIATE) { coap_ctx->status = STATUS_CONNECTING; PRINTF("coap-context: DTLS CLIENT NOT CONNECTED!\n"); process_post(coap_ctx->process, coap_context_event, coap_ctx); } else if(level == DTLS_ALERT_LEVEL_FATAL && code < 256) { /* Fatal alert */ if (coap_ctx && coap_ctx->buf) { ip_buf_unref(coap_ctx->buf); coap_ctx->buf = NULL; } coap_ctx->status = STATUS_ALERT; PRINTF("coap-context: DTLS CLIENT ALERT %u!\n", code); process_post(coap_ctx->process, coap_context_event, coap_ctx); } return 0; }
int dtls_handle_read(struct dtls_context_t *ctx) { int fd; session_t session; #define MAX_READ_BUF 2000 static uint8 buf[MAX_READ_BUF]; int len; fd = *(int *)dtls_get_app_data(ctx); if (!fd) return -1; memset(&session, 0, sizeof(session_t)); session.size = sizeof(session.addr); len = recvfrom(fd, buf, MAX_READ_BUF, 0, &session.addr.sa, &session.size); if (len < 0) { perror("recvfrom"); return -1; } else { unsigned char addrbuf[72]; dsrv_print_addr(&session, addrbuf, sizeof(addrbuf)); dsrv_log(LOG_DEBUG, "got %d bytes from %s\n", len, (char *)addrbuf); dump((unsigned char *)&session, sizeof(session_t)); PRINTF("\n"); dump(buf, len); PRINTF("\n"); } return dtls_handle_message(ctx, &session, buf, len); }
/*---------------------------------------------------------------------------*/ static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { int ret = 0; coap_context_t *coap_ctx; coap_ctx = dtls_get_app_data(ctx); PRINTF("%s(): ctx %p session %p data %p len %d\n", __FUNCTION__, ctx, session, data, len); if(coap_ctx != COAP_CONTEXT_NONE && coap_ctx->is_used && session != NULL) { ret = prepare_and_send_buf(coap_ctx, session, data, len); if (ret < 0) { PRINTF("%s(): cannot send data, msg discarded\n", __FUNCTION__); } } else { PRINTF("%s(): msg discarded ctx %p is_used %d buf %p udp %p session %p\n", __FUNCTION__, coap_ctx, coap_ctx ? coap_ctx->is_used : 0, coap_ctx->buf, coap_ctx ? (coap_ctx->buf ? uip_udp_conn(coap_ctx->buf) : NULL) : NULL, session); ret = -EINVAL; } return ret; }
static int dtls_handle_read(struct dtls_context_t *ctx) { int *fd; session_t session; static uint8 buf[DTLS_MAX_BUF]; int len; fd = dtls_get_app_data(ctx); assert(fd); memset(&session, 0, sizeof(session_t)); session.size = sizeof(session.addr); len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC, &session.addr.sa, &session.size); if (len < 0) { perror("recvfrom"); return -1; } else { dtls_debug("got %d bytes from port %d\n", len, ntohs(session.addr.sin6.sin6_port)); if (sizeof(buf) < len) { dtls_warn("packet was truncated (%d bytes lost)\n", len - sizeof(buf)); } } return dtls_handle_message(ctx, &session, buf, len); }
int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { int fd = *(int *)dtls_get_app_data(ctx); return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size); }
/*---------------------------------------------------------------------------*/ static int get_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { coap_context_t *coap_ctx; coap_ctx = dtls_get_app_data(ctx); if(coap_ctx != COAP_CONTEXT_NONE && coap_ctx->is_used) { uip_len(coap_ctx->buf) = len; memmove(uip_appdata(coap_ctx->buf), data, len); coap_engine_receive(coap_ctx); } return 0; }
int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx); uip_ipaddr_copy(&conn->ripaddr, &session->addr); conn->rport = session->port; uip_udp_packet_send(conn, data, len); /* Restore server connection to allow data from any node */ memset(&conn->ripaddr, 0, sizeof(conn->ripaddr)); memset(&conn->rport, 0, sizeof(conn->rport)); return len; }
static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx); uip_ipaddr_copy(&conn->ripaddr, &session->addr); conn->rport = session->port; PRINTF("send to "); PRINT6ADDR(&conn->ripaddr); PRINTF(":%u\n", uip_ntohs(conn->rport)); uip_udp_packet_send(conn, data, len); /* Restore server connection to allow data from any node */ /* FIXME: do we want this at all? */ memset(&conn->ripaddr, 0, sizeof(conn->ripaddr)); memset(&conn->rport, 0, sizeof(conn->rport)); return len; }
static int get_key(struct dtls_context_t *ctx, const session_t *session, const unsigned char *id, size_t id_len, const dtls_key_t **result) { static const dtls_key_t psk = { .type = DTLS_KEY_PSK, .key.psk.id = (unsigned char *)DTLS_IDENTITY_HINT, .key.psk.id_length = DTLS_IDENTITY_HINT_LENGTH, .key.psk.key = (unsigned char *)DTLS_PSK_KEY, .key.psk.key_length = DTLS_PSK_KEY_LENGTH }; *result = &psk; return 0; } #else static int get_psk_key(struct dtls_context_t *ctx, const session_t *session, const unsigned char *id, size_t id_len, const dtls_psk_key_t **result) { static const dtls_psk_key_t psk = { .id = (unsigned char *)DTLS_IDENTITY_HINT, .id_length = DTLS_IDENTITY_HINT_LENGTH, .key = (unsigned char *)DTLS_PSK_KEY, .key_length = DTLS_PSK_KEY_LENGTH }; *result = &psk; return 0; } #endif /*-----------------------------------------------------------------------------------*/ void coap_init_communication_layer(uint16_t port) { static dtls_handler_t cb = { .write = send_to_peer, .read = read_from_peer, .event = NULL, #if DTLS_VERSION_0_4_0 .get_key = get_key #else .get_psk_key = get_psk_key, .get_ecdsa_key = NULL, .verify_ecdsa_key = NULL #endif }; server_conn = udp_new(NULL, 0, NULL); udp_bind(server_conn, port); dtls_set_log_level(LOG_DEBUG); dtls_context = dtls_new_context(server_conn); if (dtls_context) dtls_set_handler(dtls_context, &cb); /* new connection with remote host */ printf("COAP-DTLS listening on port %u\n", uip_ntohs(server_conn->lport)); } /*-----------------------------------------------------------------------------------*/ static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx); uip_ipaddr_copy(&conn->ripaddr, &session->addr); conn->rport = session->port; uip_udp_packet_send(conn, data, len); /* Restore server connection to allow data from any node */ memset(&conn->ripaddr, 0, sizeof(conn->ripaddr)); memset(&conn->rport, 0, sizeof(conn->rport)); return len; } /*-----------------------------------------------------------------------------------*/ void coap_send_message(context_t * ctx, uip_ipaddr_t *addr, uint16_t port, uint8_t *data, uint16_t length) { session_t session; dtls_session_init(&session); uip_ipaddr_copy(&session.addr, addr); session.port = port; dtls_write(ctx, &session, data, length); } /*-----------------------------------------------------------------------------------*/ static int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { uip_len = len; memmove(uip_appdata, data, len); coap_receive(ctx); return 0; } /*-----------------------------------------------------------------------------------*/ void coap_handle_receive() { session_t session; if(uip_newdata()) { dtls_session_init(&session); uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr); session.port = UIP_UDP_BUF->srcport; dtls_handle_message(dtls_context, &session, uip_appdata, uip_datalen()); } }