diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h index 46420853..01a8a5ea 100644 --- a/src/include/microhttpd2.h +++ b/src/include/microhttpd2.h @@ -9464,14 +9464,25 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_ConnectionInfoFixedType { /** - * Obtain IP address of the client. - * The result is placed in @a vs_sa member. + * Get the network address of the client. + * If the connection does not have known remote address (was not provided + * by the system or by the application in case of externally added + * connection) then error code #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is + * returned if connection is IP type or unknown type or error code + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if connection type is non-IP. + * The @a sa pointer is never NULL if the function succeed (#MHD_SC_OK + * returned). + * The result is placed in @a v_sa_info member. * @ingroup request */ MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS = 1 , /** - * Request the file descriptor for the connection socket. + * Get the file descriptor for the connection socket. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling send() or recv(), closing it etc.) will lead to undefined + * behaviour. * The result is placed in @a v_fd member. * @ingroup request */ @@ -9493,6 +9504,18 @@ enum MHD_ConnectionInfoFixedType MHD_CONNECTION_INFO_FIXED_SENTINEL = 65535 }; +struct MHD_ConnInfoFixedSockAddr +{ + /** + * The size of the @a sa + */ + size_t sa_size; + + /** + * Socket Address type + */ + const struct sockaddr *sa; +}; /** * Information about a connection. @@ -9503,7 +9526,7 @@ union MHD_ConnectionInfoFixedData /** * Socket Address type */ - const struct sockaddr *vs_sa; + struct MHD_ConnInfoFixedSockAddr v_sa_info; /** * Socket type @@ -9524,23 +9547,34 @@ union MHD_ConnectionInfoFixedData * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error code in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_connection_get_info_fixed_sz ( struct MHD_Connection *connection, enum MHD_ConnectionInfoFixedType info_type, - union MHD_ConnectionInfoFixedData *return_value, - size_t return_value_size) + union MHD_ConnectionInfoFixedData *output_buf, + size_t output_buf_size) MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -9549,16 +9583,26 @@ MHD_FN_PURE_; * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error code in case of other errors * @ingroup specialized */ -#define MHD_connection_get_info_fixed(connection,info_type,return_value) \ - MHD_connection_get_info_fixed_sz ((connection),(info_type),(return_value \ - ), \ - sizeof(*(return_value))) +#define MHD_connection_get_info_fixed(connection,info_type,output_buf) \ + MHD_connection_get_info_fixed_sz ((connection),(info_type), \ + (output_buf), sizeof(*(output_buf))) /** diff --git a/src/include/microhttpd2_main.h.in b/src/include/microhttpd2_main.h.in index 24b0c244..b1ba7d91 100644 --- a/src/include/microhttpd2_main.h.in +++ b/src/include/microhttpd2_main.h.in @@ -4842,14 +4842,25 @@ MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); enum MHD_ConnectionInfoFixedType { /** - * Obtain IP address of the client. - * The result is placed in @a vs_sa member. + * Get the network address of the client. + * If the connection does not have known remote address (was not provided + * by the system or by the application in case of externally added + * connection) then error code #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE is + * returned if connection is IP type or unknown type or error code + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if connection type is non-IP. + * The @a sa pointer is never NULL if the function succeed (#MHD_SC_OK + * returned). + * The result is placed in @a v_sa_info member. * @ingroup request */ MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS = 1 , /** - * Request the file descriptor for the connection socket. + * Get the file descriptor for the connection socket. + * The provided socket must be used as 'read-only': only select() or similar + * functions should be used. Any modifications (changing socket attributes, + * calling send() or recv(), closing it etc.) will lead to undefined + * behaviour. * The result is placed in @a v_fd member. * @ingroup request */ @@ -4871,6 +4882,18 @@ enum MHD_ConnectionInfoFixedType MHD_CONNECTION_INFO_FIXED_SENTINEL = 65535 }; +struct MHD_ConnInfoFixedSockAddr +{ + /** + * The size of the @a sa + */ + size_t sa_size; + + /** + * Socket Address type + */ + const struct sockaddr *sa; +}; /** * Information about a connection. @@ -4881,7 +4904,7 @@ union MHD_ConnectionInfoFixedData /** * Socket Address type */ - const struct sockaddr *vs_sa; + struct MHD_ConnInfoFixedSockAddr v_sa_info; /** * Socket type @@ -4902,23 +4925,34 @@ union MHD_ConnectionInfoFixedData * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored - * @param return_value_size the size of the memory area pointed - by @a return_data, in bytes + * @param[out] output_buf the pointer to union to be set to the requested + * information + * @param output_buf_size the size of the memory area pointed by @a output_buf + * (provided by the caller for storing the requested + * information), in bytes * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error code in case of other errors * @ingroup specialized */ MHD_EXTERN_ enum MHD_StatusCode MHD_connection_get_info_fixed_sz ( struct MHD_Connection *connection, enum MHD_ConnectionInfoFixedType info_type, - union MHD_ConnectionInfoFixedData *return_value, - size_t return_value_size) + union MHD_ConnectionInfoFixedData *output_buf, + size_t output_buf_size) MHD_FN_PAR_NONNULL_ (1) -MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) -MHD_FN_PURE_; +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3); /** @@ -4927,16 +4961,26 @@ MHD_FN_PURE_; * * @param connection the connection to get information about * @param info_type the type of information requested - * @param[out] return_value pointer to union where requested information will - * be stored + * @param[out] output_buf the pointer to union to be set to the requested + * information * @return #MHD_SC_OK if succeed, - * error code otherwise + * #MHD_SC_INFO_GET_TYPE_UNKNOWN if @a info_type value is unknown, + * #MHD_SC_INFO_GET_BUFF_TOO_SMALL if @a output_buf_size is too small, + * #MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE if the requested information + * is not available for this + * connection due to the connection + * configuration/mode, + * #MHD_SC_INFO_GET_TYPE_UNOBTAINABLE if the requested information + * should be available for + * the connection, but cannot be + * provided due to some error or + * other reasons, + * other error code in case of other errors * @ingroup specialized */ -#define MHD_connection_get_info_fixed(connection,info_type,return_value) \ - MHD_connection_get_info_fixed_sz ((connection),(info_type),(return_value \ - ), \ - sizeof(*(return_value))) +#define MHD_connection_get_info_fixed(connection,info_type,output_buf) \ + MHD_connection_get_info_fixed_sz ((connection),(info_type), \ + (output_buf), sizeof(*(output_buf))) /** diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am index 5855b6f2..af402a3f 100644 --- a/src/mhd2/Makefile.am +++ b/src/mhd2/Makefile.am @@ -79,6 +79,7 @@ libmicrohttpd2_la_SOURCES = \ conn_data_recv.c conn_data_recv.h \ conn_data_send.c conn_data_send.h \ conn_mark_ready.h \ + conn_get_info.c \ request_funcs.c request_funcs.h \ request_get_value.c request_get_value.h \ respond_with_error.c respond_with_error.h \ diff --git a/src/mhd2/conn_get_info.c b/src/mhd2/conn_get_info.c new file mode 100644 index 00000000..d072706a --- /dev/null +++ b/src/mhd2/conn_get_info.c @@ -0,0 +1,83 @@ +/* + This file is part of GNU libmicrohttpd + Copyright (C) 2025 Evgeny Grin (Karlson2k) + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +/** + * @file src/mhd2/conn_get_info.c + * @brief The implementation of MHD_connection_get_info_*() functions + * @author Karlson2k (Evgeny Grin) + */ + +#include "mhd_sys_options.h" + +#include "mhd_unreachable.h" + +#include "mhd_connection.h" + +#include "daemon_funcs.h" +#ifdef MHD_SUPPORT_HTTPS +# include "mhd_tls_funcs.h" +#endif + +#include "mhd_public_api.h" + +MHD_EXTERN_ +MHD_FN_PAR_NONNULL_ (1) +MHD_FN_PAR_NONNULL_ (3) MHD_FN_PAR_OUT_ (3) enum MHD_StatusCode +MHD_connection_get_info_fixed_sz ( + struct MHD_Connection *connection, + enum MHD_ConnectionInfoFixedType info_type, + union MHD_ConnectionInfoFixedData *output_buf, + size_t output_buf_size) +{ + switch (info_type) + { + case MHD_CONNECTION_INFO_FIXED_CLIENT_ADDRESS: + if (NULL == connection->sk.addr.data) + { + if (mhd_T_IS_NOT_YES (connection->sk.props.is_nonip)) + return MHD_SC_INFO_GET_TYPE_UNOBTAINABLE; + else + return MHD_SC_INFO_GET_TYPE_NOT_APPLICABLE; + } + mhd_assert (0 != connection->sk.addr.size); + if (sizeof(output_buf->v_sa_info) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_sa_info.sa_size = connection->sk.addr.size; + output_buf->v_sa_info.sa = + (const struct sockaddr*) connection->sk.addr.data; + return MHD_SC_OK; + case MHD_CONNECTION_INFO_FIXED_CONNECTION_FD: + if (sizeof(output_buf->v_fd) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + mhd_assert (MHD_INVALID_SOCKET != connection->sk.fd); + output_buf->v_fd = connection->sk.fd; + return MHD_SC_OK; + case MHD_CONNECTION_INFO_FIXED_DAEMON: + if (sizeof(output_buf->v_daemon) > output_buf_size) + return MHD_SC_INFO_GET_BUFF_TOO_SMALL; + output_buf->v_daemon = mhd_daemon_get_master_daemon (connection->daemon); + return MHD_SC_OK; + + case MHD_CONNECTION_INFO_FIXED_SENTINEL: + default: + break; + } + return MHD_SC_INFO_GET_TYPE_UNKNOWN; +}