diff --git a/examples/gcoap/client.c b/examples/gcoap/client.c index 52b2203489..acf670697a 100644 --- a/examples/gcoap/client.c +++ b/examples/gcoap/client.c @@ -174,7 +174,7 @@ static gcoap_socket_type_t _get_tl(const char *uri) static ssize_t _send(uint8_t *buf, size_t len, const sock_udp_ep_t *remote, void *ctx, gcoap_socket_type_t tl) { - ssize_t bytes_sent = gcoap_req_send(buf, len, remote, _resp_handler, ctx, tl); + ssize_t bytes_sent = gcoap_req_send(buf, len, remote, NULL, _resp_handler, ctx, tl); if (bytes_sent > 0) { req_count++; } diff --git a/sys/include/net/gcoap.h b/sys/include/net/gcoap.h index 4cd99178b9..b9b4afebdd 100644 --- a/sys/include/net/gcoap.h +++ b/sys/include/net/gcoap.h @@ -330,7 +330,7 @@ * coap_opt_add_proxy_uri(&pdu, uri); * unsigned len = coap_opt_finish(&pdu, COAP_OPT_FINISH_NONE); * - * gcoap_req_send((uint8_t *) pdu->hdr, len, proxy_remote, _resp_handler, NULL, + * gcoap_req_send((uint8_t *) pdu->hdr, len, proxy_remote, NULL, _resp_handler, NULL, * GCOAP_SOCKET_TYPE_UNDEF); * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -964,6 +964,7 @@ static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len, * @param[in] buf Buffer containing the PDU * @param[in] len Length of the buffer * @param[in] remote Destination for the packet + * @param[in] local Local endpoint to send from, may be NULL * @param[in] resp_handler Callback when response received, may be NULL * @param[in] context User defined context passed to the response handler * @param[in] tl_type The transport type to use for send. When @@ -980,7 +981,7 @@ static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len, * @return 0 if cannot send */ ssize_t gcoap_req_send(const uint8_t *buf, size_t len, - const sock_udp_ep_t *remote, + const sock_udp_ep_t *remote, const sock_udp_ep_t *local, gcoap_resp_handler_t resp_handler, void *context, gcoap_socket_type_t tl_type); @@ -1009,7 +1010,7 @@ static inline ssize_t gcoap_req_send_tl(const uint8_t *buf, size_t len, gcoap_resp_handler_t resp_handler, void *context, gcoap_socket_type_t tl_type) { - return gcoap_req_send(buf, len, remote, resp_handler, context, tl_type); + return gcoap_req_send(buf, len, remote, NULL, resp_handler, context, tl_type); } /** diff --git a/sys/include/net/gcoap/forward_proxy.h b/sys/include/net/gcoap/forward_proxy.h index dc82116322..dc59848d30 100644 --- a/sys/include/net/gcoap/forward_proxy.h +++ b/sys/include/net/gcoap/forward_proxy.h @@ -59,6 +59,7 @@ void gcoap_forward_proxy_init(void); * * @param[in] pkt Packet to parse * @param[in] client Endpoint of the client + * @param[in] local Local endpoint * * @return 0 if parsing was successful * @return -ENOTSUP if the forward proxy is not compiled in @@ -66,7 +67,7 @@ void gcoap_forward_proxy_init(void); * @return -EINVAL if Proxy-Uri is malformed */ int gcoap_forward_proxy_request_process(coap_pkt_t *pkt, - const sock_udp_ep_t *client); + const sock_udp_ep_t *client, const sock_udp_ep_t *local); /** * @brief Finds the memo for an outstanding request within the diff --git a/sys/include/net/nanocoap.h b/sys/include/net/nanocoap.h index a9cfa2743e..044ea13433 100644 --- a/sys/include/net/nanocoap.h +++ b/sys/include/net/nanocoap.h @@ -390,6 +390,16 @@ uint32_t coap_request_ctx_get_tl_type(const coap_request_ctx_t *ctx); */ const sock_udp_ep_t *coap_request_ctx_get_remote_udp(const coap_request_ctx_t *ctx); +/** + * @brief Get the local endpoint on which the request has been received + * + * @param[in] ctx The request context + * + * @return Local endpoint to which the request has been received + * @return NULL The request was not received via UDP + */ +const sock_udp_ep_t *coap_request_ctx_get_local_udp(const coap_request_ctx_t *ctx); + /** * @brief Block1 helper struct */ diff --git a/sys/net/application_layer/cord/ep/cord_ep.c b/sys/net/application_layer/cord/ep/cord_ep.c index b9148d9b2b..42e47a77c9 100644 --- a/sys/net/application_layer/cord/ep/cord_ep.c +++ b/sys/net/application_layer/cord/ep/cord_ep.c @@ -151,7 +151,8 @@ static int _update_remove(unsigned code, gcoap_resp_handler_t handle) ssize_t pkt_len = coap_opt_finish(&pkt, COAP_OPT_FINISH_NONE); /* send request */ - ssize_t send_len = gcoap_req_send(buf, pkt_len, &_rd_remote, handle, NULL, GCOAP_SOCKET_TYPE_UNDEF); + ssize_t send_len = gcoap_req_send(buf, pkt_len, &_rd_remote, NULL, + handle, NULL, GCOAP_SOCKET_TYPE_UNDEF); if (send_len <= 0) { return CORD_EP_ERR; } @@ -225,7 +226,7 @@ static int _discover_internal(const sock_udp_ep_t *remote, coap_hdr_set_type(pkt.hdr, COAP_TYPE_CON); coap_opt_add_uri_query(&pkt, "rt", "core.rd"); size_t pkt_len = coap_opt_finish(&pkt, COAP_OPT_FINISH_NONE); - res = gcoap_req_send(buf, pkt_len, remote, _on_discover, NULL, GCOAP_SOCKET_TYPE_UNDEF); + res = gcoap_req_send(buf, pkt_len, remote, NULL, _on_discover, NULL, GCOAP_SOCKET_TYPE_UNDEF); if (res <= 0) { return CORD_EP_ERR; } @@ -296,7 +297,7 @@ int cord_ep_register(const sock_udp_ep_t *remote, const char *regif) pkt_len += res; /* send out the request */ - res = gcoap_req_send(buf, pkt_len, remote, _on_register, NULL, GCOAP_SOCKET_TYPE_UNDEF); + res = gcoap_req_send(buf, pkt_len, remote, NULL, _on_register, NULL, GCOAP_SOCKET_TYPE_UNDEF); if (res <= 0) { retval = CORD_EP_ERR; goto end; diff --git a/sys/net/application_layer/cord/epsim/cord_epsim.c b/sys/net/application_layer/cord/epsim/cord_epsim.c index 9c739c106f..0f24d4b91a 100644 --- a/sys/net/application_layer/cord/epsim/cord_epsim.c +++ b/sys/net/application_layer/cord/epsim/cord_epsim.c @@ -67,7 +67,7 @@ int cord_epsim_register(const sock_udp_ep_t *rd_ep) /* finish, we don't have any payload */ ssize_t len = coap_opt_finish(&pkt, COAP_OPT_FINISH_NONE); _state = CORD_EPSIM_BUSY; - if (gcoap_req_send(buf, len, rd_ep, _req_handler, NULL, GCOAP_SOCKET_TYPE_UNDEF) == 0) { + if (gcoap_req_send(buf, len, rd_ep, NULL, _req_handler, NULL, GCOAP_SOCKET_TYPE_UNDEF) == 0) { return CORD_EPSIM_ERROR; } diff --git a/sys/net/application_layer/cord/lc/cord_lc.c b/sys/net/application_layer/cord/lc/cord_lc.c index eddda2f7e7..72d8fd9f0e 100644 --- a/sys/net/application_layer/cord/lc/cord_lc.c +++ b/sys/net/application_layer/cord/lc/cord_lc.c @@ -190,7 +190,8 @@ static ssize_t _lookup_raw(const cord_lc_rd_t *rd, unsigned content_format, if (pkt_len < 0) { return CORD_LC_ERR; } - res = gcoap_req_send(reqbuf, pkt_len, rd->remote, _on_lookup, NULL, GCOAP_SOCKET_TYPE_UNDEF); + res = gcoap_req_send(reqbuf, pkt_len, rd->remote, NULL, + _on_lookup, NULL, GCOAP_SOCKET_TYPE_UNDEF); if (res < 0) { return CORD_LC_ERR; } @@ -259,7 +260,7 @@ static int _send_rd_init_req(coap_pkt_t *pkt, const sock_udp_ep_t *remote, return CORD_LC_ERR; } - if (!gcoap_req_send(buf, pkt_len, remote, _on_rd_init, NULL, GCOAP_SOCKET_TYPE_UNDEF)) { + if (!gcoap_req_send(buf, pkt_len, remote, NULL, _on_rd_init, NULL, GCOAP_SOCKET_TYPE_UNDEF)) { DEBUG("cord_lc: error gcoap_req_send()\n"); return CORD_LC_ERR; } diff --git a/sys/net/application_layer/gcoap/dns.c b/sys/net/application_layer/gcoap/dns.c index 600acf4feb..7273ac1193 100644 --- a/sys/net/application_layer/gcoap/dns.c +++ b/sys/net/application_layer/gcoap/dns.c @@ -762,6 +762,6 @@ static ssize_t _send(const void *buf, size_t len, const sock_udp_ep_t *remote, if (lock_resp_wait) { mutex_lock(&context->resp_wait); } - return gcoap_req_send(buf, len, remote, _resp_handler, context, tl_type); + return gcoap_req_send(buf, len, remote, NULL, _resp_handler, context, tl_type); } /** @} */ diff --git a/sys/net/application_layer/gcoap/forward_proxy.c b/sys/net/application_layer/gcoap/forward_proxy.c index ddb95b59c0..550439c77e 100644 --- a/sys/net/application_layer/gcoap/forward_proxy.c +++ b/sys/net/application_layer/gcoap/forward_proxy.c @@ -142,8 +142,9 @@ static ssize_t _forward_proxy_handler(coap_pkt_t *pdu, uint8_t *buf, { int pdu_len; const sock_udp_ep_t *remote = coap_request_ctx_get_remote_udp(ctx); + const sock_udp_ep_t *local = coap_request_ctx_get_local_udp(ctx); - pdu_len = gcoap_forward_proxy_request_process(pdu, remote); + pdu_len = gcoap_forward_proxy_request_process(pdu, remote, local); /* Out of memory, reply with 5.00 */ if (pdu_len == -ENOMEM) { @@ -226,12 +227,13 @@ static bool _parse_endpoint(sock_udp_ep_t *remote, return true; } -static ssize_t _dispatch_msg(const void *buf, size_t len, sock_udp_ep_t *remote) +static ssize_t _dispatch_msg(const void *buf, size_t len, sock_udp_ep_t *remote, + const sock_udp_ep_t *local) { /* Yes it's not a request -- but turns out there is nothing in * gcoap_req_send that is actually request specific, especially if we * don't assign a callback. */ - ssize_t res = gcoap_req_send(buf, len, remote, NULL, NULL, + ssize_t res = gcoap_req_send(buf, len, remote, local, NULL, NULL, GCOAP_SOCKET_TYPE_UDP); if (res <= 0) { DEBUG("gcoap_forward_proxy: unable to dispatch message: %d\n", -res); @@ -252,7 +254,7 @@ static void _send_empty_ack(event_t *event) /* Flipping byte order as unlike in the other places where mid is * used, coap_build_hdr would actually flip it back */ coap_build_hdr(&buf, COAP_TYPE_ACK, NULL, 0, 0, ntohs(cep->mid)); - _dispatch_msg(&buf, sizeof(buf), &cep->ep); + _dispatch_msg(&buf, sizeof(buf), &cep->ep, &cep->proxy_ep); } static void _set_response_type(coap_pkt_t *pdu, uint8_t resp_type) @@ -316,7 +318,7 @@ static void _forward_resp_handler(const gcoap_request_memo_t *memo, } _set_response_type(pdu, _cep_get_response_type(cep)); /* don't use buf_len here, in case the above `gcoap_resp_init`s changed `pdu` */ - _dispatch_msg(pdu->hdr, coap_get_total_len(pdu), &cep->ep); + _dispatch_msg(pdu->hdr, coap_get_total_len(pdu), &cep->ep, &cep->proxy_ep); _free_client_ep(cep); } @@ -398,6 +400,7 @@ static int _gcoap_forward_proxy_copy_options(coap_pkt_t *pkt, /* copy payload from client_pkt to pkt */ memcpy(pkt->payload, client_pkt->payload, client_pkt->payload_len); + pkt->payload_len = client_pkt->payload_len; len += client_pkt->payload_len; return len; @@ -407,7 +410,7 @@ int gcoap_forward_proxy_req_send(client_ep_t *cep) { int len; if ((len = gcoap_req_send((uint8_t *)cep->pdu.hdr, coap_get_total_len(&cep->pdu), - &cep->server_ep, _forward_resp_handler, cep, + &cep->server_ep, NULL, _forward_resp_handler, cep, GCOAP_SOCKET_TYPE_UNDEF)) <= 0) { DEBUG("gcoap_forward_proxy_req_send(): gcoap_req_send failed %d\n", len); _free_client_ep(cep); @@ -458,7 +461,7 @@ static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt, /* copy all options from client_pkt to pkt */ len = _gcoap_forward_proxy_copy_options(&client_ep->pdu, client_pkt, client_ep, urip); - if (len == -EINVAL) { + if (len < 0) { _free_client_ep(client_ep); return -EINVAL; } @@ -479,13 +482,13 @@ static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt, } int gcoap_forward_proxy_request_process(coap_pkt_t *pkt, - const sock_udp_ep_t *client) { + const sock_udp_ep_t *client, const sock_udp_ep_t *local) { char *uri; uri_parser_result_t urip; ssize_t optlen = 0; client_ep_t *cep = _allocate_client_ep(client); - + cep->proxy_ep = local ? *local : (sock_udp_ep_t){ 0 }; if (!cep) { return -ENOMEM; } diff --git a/sys/net/application_layer/gcoap/gcoap.c b/sys/net/application_layer/gcoap/gcoap.c index e6fc5d91ff..3c7da0da84 100644 --- a/sys/net/application_layer/gcoap/gcoap.c +++ b/sys/net/application_layer/gcoap/gcoap.c @@ -66,7 +66,7 @@ static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t le coap_request_ctx_t *ctx); static void _cease_retransmission(gcoap_request_memo_t *memo); static size_t _handle_req(gcoap_socket_t *sock, coap_pkt_t *pdu, uint8_t *buf, - size_t len, sock_udp_ep_t *remote); + size_t len, sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux); static void _expire_request(gcoap_request_memo_t *memo); static gcoap_request_memo_t* _find_req_memo_by_mid(const sock_udp_ep_t *remote, uint16_t mid); @@ -453,7 +453,7 @@ static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote, sock_ COAP_CODE_REQUEST_ENTITY_TOO_LARGE); } else { pdu_len = _handle_req(sock, &pdu, _listen_buf, - sizeof(_listen_buf), remote); + sizeof(_listen_buf), remote, aux); } if (pdu_len > 0) { @@ -652,7 +652,7 @@ static void _cease_retransmission(gcoap_request_memo_t *memo) { * return length of response pdu, or < 0 if can't handle */ static size_t _handle_req(gcoap_socket_t *sock, coap_pkt_t *pdu, uint8_t *buf, - size_t len, sock_udp_ep_t *remote) + size_t len, sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux) { const coap_resource_t *resource = NULL; gcoap_listener_t *listener = NULL; @@ -760,6 +760,7 @@ static size_t _handle_req(gcoap_socket_t *sock, coap_pkt_t *pdu, uint8_t *buf, .resource = resource, .tl_type = (uint32_t)sock->type, .remote = remote, + .local = aux ? &aux->local : NULL, }; pdu_len = resource->handler(pdu, buf, len, &ctx); @@ -1613,7 +1614,7 @@ int gcoap_obs_req_forget(const sock_udp_ep_t *remote, const uint8_t *token, } ssize_t gcoap_req_send(const uint8_t *buf, size_t len, - const sock_udp_ep_t *remote, + const sock_udp_ep_t *remote, const sock_udp_ep_t *local, gcoap_resp_handler_t resp_handler, void *context, gcoap_socket_type_t tl_type) { @@ -1743,7 +1744,12 @@ ssize_t gcoap_req_send(const uint8_t *buf, size_t len, } if (res == 0) { - res = _tl_send(&socket, buf, len, remote, NULL); + sock_udp_aux_tx_t aux = { 0 }; + if (local) { + memcpy(&aux.local, local, sizeof(sock_udp_ep_t)); + aux.flags = SOCK_AUX_SET_LOCAL; + } + res = _tl_send(&socket, buf, len, remote, &aux); } if (res <= 0) { if (memo != NULL) { diff --git a/sys/net/application_layer/gcoap/include/forward_proxy_internal.h b/sys/net/application_layer/gcoap/include/forward_proxy_internal.h index dbeb93fbf5..8831c19d88 100644 --- a/sys/net/application_layer/gcoap/include/forward_proxy_internal.h +++ b/sys/net/application_layer/gcoap/include/forward_proxy_internal.h @@ -40,6 +40,7 @@ typedef struct { coap_pkt_t pdu; /**< forward CoAP PDU */ sock_udp_ep_t server_ep; /**< forward Server endpoint */ sock_udp_ep_t ep; /**< client endpoint */ + sock_udp_ep_t proxy_ep; /**< proxy endpoint */ uint16_t mid; /**< message ID */ uint8_t flags; /**< client flags */ #if IS_USED(MODULE_NANOCOAP_CACHE) diff --git a/sys/net/application_layer/nanocoap/nanocoap.c b/sys/net/application_layer/nanocoap/nanocoap.c index f7e92cc3fd..08af915cd0 100644 --- a/sys/net/application_layer/nanocoap/nanocoap.c +++ b/sys/net/application_layer/nanocoap/nanocoap.c @@ -1464,3 +1464,13 @@ const sock_udp_ep_t *coap_request_ctx_get_remote_udp(const coap_request_ctx_t *c { return ctx->remote; } + +const sock_udp_ep_t *coap_request_ctx_get_local_udp(const coap_request_ctx_t *ctx) +{ +#if defined(MODULE_SOCK_AUX_LOCAL) + return ctx->local; +#else + (void)ctx; + return NULL; +#endif +}