/*---------------------------------------------------------------------------*/ void coap_context_close(coap_context_t *coap_ctx) { if(coap_ctx == NULL || coap_ctx->is_used == 0) { /* Not opened */ return; } if(coap_ctx->buf && uip_udp_conn(coap_ctx->buf) != NULL) { uip_udp_remove(uip_udp_conn(coap_ctx->buf)); } coap_ctx->is_used = 0; }
/*---------------------------------------------------------------------------*/ 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; }
/*---------------------------------------------------------------------------*/ coap_context_t * coap_context_new(uip_ipaddr_t *my_addr, uint16_t port) { coap_context_t *ctx = NULL; int i; for(i = 0; i < MAX_CONTEXTS; i++) { if(!coap_contexts[i].is_used) { ctx = &coap_contexts[i]; break; } } if(ctx == NULL) { PRINTF("coap-context: no free contexts\n"); return NULL; } memset(ctx, 0, sizeof(coap_context_t)); /* initialize context */ ctx->dtls_context = dtls_new_context(ctx); if(ctx->dtls_context == NULL) { PRINTF("coap-context: failed to get DTLS context\n"); uip_udp_remove(uip_udp_conn(ctx->buf)); return NULL; } ctx->dtls_handler.write = send_to_peer; ctx->dtls_handler.read = get_from_peer; ctx->dtls_handler.event = event; dtls_set_handler(ctx->dtls_context, &ctx->dtls_handler); #ifdef NETSTACK_CONF_WITH_IPV6 memcpy(&ctx->my_addr.in6_addr, my_addr, sizeof(ctx->my_addr.in6_addr)); #else memcpy(&ctx->my_addr.in_addr, my_addr, sizeof(ctx->my_addr.in_addr)); #endif ctx->my_port = port; ctx->process = PROCESS_CURRENT(); ctx->is_used = 1; PRINTF("Secure listening on port %u\n", port); return ctx; }
/*---------------------------------------------------------------------------*/ void tcpip_uipcall(struct net_buf *buf) { uip_udp_appstate_t *ts; #if UIP_UDP if(uip_conn(buf) != NULL) { ts = &uip_conn(buf)->appstate; } else { ts = &uip_udp_conn(buf)->appstate; } #else /* UIP_UDP */ ts = &uip_conn(buf)->appstate; #endif /* UIP_UDP */ #if UIP_TCP { static unsigned char i; struct listenport *l; /* If this is a connection request for a listening port, we must mark the connection with the right process ID. */ if(uip_connected()) { l = &s.listenports[0]; for(i = 0; i < UIP_LISTENPORTS; ++i) { if(l->port == uip_conn->lport && l->p != PROCESS_NONE) { ts->p = l->p; ts->state = NULL; break; } ++l; } /* Start the periodic polling, if it isn't already active. */ start_periodic_tcp_timer(); } } #endif /* UIP_TCP */ if(ts->p != NULL) { process_post_synch(ts->p, tcpip_event, ts->state, buf); } }
/* Application wants to send a reply */ int net_reply(struct net_context *context, struct net_buf *buf) { struct net_tuple *tuple; struct uip_udp_conn *udp; int ret = 0; if (!context || !buf) { return -EINVAL; } tuple = net_context_get_tuple(context); if (!tuple) { return -ENOENT; } switch (tuple->ip_proto) { case IPPROTO_UDP: udp = uip_udp_conn(buf); if (!udp) { NET_ERR("UDP connection missing\n"); return -ESRCH; } ret = udp_prepare_and_send(context, buf); break; case IPPROTO_TCP: NET_DBG("TCP not yet supported\n"); return -EINVAL; break; case IPPROTO_ICMPV6: NET_DBG("ICMPv6 not yet supported\n"); return -EINVAL; break; } return ret; }
/*---------------------------------------------------------------------------*/ int coap_context_send_message(coap_context_t *coap_ctx, uip_ipaddr_t *addr, uint16_t port, const uint8_t *data, uint16_t length) { int ret; if(coap_ctx == NULL || coap_ctx->is_used == 0) { PRINTF("coap-context: can not send on non-used context\n"); return 0; } ip_buf_appdatalen(coap_ctx->buf) = length; if (!uip_udp_conn(coap_ctx->buf)) { /* Normal send, not a reply */ ret = coap_context_send(coap_ctx, coap_ctx->buf); } else { /* We need to set the uIP buffer lengths in net_buf properly as * otherwise the final buffer length in * net_init.c:udp_prepare_and_send() will be usually incorrect * (uip_len() will be length of the received packet). So by setting * uip_len() to 0 here, we let the sending in net_init.c to * set the send buffer length correctly. */ uip_len(coap_ctx->buf) = 0; memcpy(ip_buf_appdata(coap_ctx->buf), data, length); ret = coap_context_reply(coap_ctx, coap_ctx->buf); } coap_ctx->buf = NULL; return ret; }