mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
Robert Gronenberg wrote:
I am using libmicrohttpd in a multithreaded application in the thread-per-connection mode. In order to maintain statistics and such on the various clients, the application should be notified about connections being started and stopped. Something like the MHD_OPTION_NOTIFY_COMPLETED for requests, but then for connections. As far as I could find libmicrohttpd does not (yet) provide that functionality. Attached is a patch that does add this functionality by registering a connection notification callback function: MHD_OPTION_NOTIFY_CONNECTION (inspired by the MHD_OPTION_NOTIFY_COMPLETED option). Could this be included in libmicrohttpd? => The patch was only working for multithreaded apps, so I adjusted it to cover other threading models, fixed a merge issue and added the ability to associate a void* with the callbacks (and obtain it via MHD connection info). And I updated the manual & ChangeLog. Now I think it can be included ;-).
This commit is contained in:
@@ -51,6 +51,7 @@ Luke-Jr <luke@dashjr.org>
|
||||
Sree Harsha Totakura <sreeharsha@totakura.in>
|
||||
Hani Benhabiles <kroosec@gmail.com>
|
||||
Guy Martin <gmsoft@tuxicoman.be>
|
||||
Robert Groenenberg <robert.groenenberg@broadforward.com>
|
||||
|
||||
|
||||
Documentation contributions also came from:
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
Tue Mar 31 10:28:26 CEST 2015
|
||||
Adding MHD_OPTION_NOTIFY_CONNECTION,
|
||||
MHD_CONNECTION_NOTIFY_STARTED,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED and
|
||||
MHD_CONNECTION_INFO_SOCKET_CONTEXT to allow
|
||||
applications to trigger operations when TCP
|
||||
connections start or end, instead of just
|
||||
exposing HTTP requests starting and ending. -RG/CG
|
||||
|
||||
Thu Feb 26 09:55:43 CET 2015
|
||||
Fixing bug that prevented MHD_OPTION_HTTPS_MEM_DHPARAMS
|
||||
from working within a MHD_OPTION_ARRAY. -DD
|
||||
|
||||
@@ -631,6 +631,25 @@ pointer to a function of type @code{MHD_RequestCompletedCallback()}
|
||||
and second a pointer to a closure to pass to the request completed
|
||||
callback. The second pointer maybe @code{NULL}.
|
||||
|
||||
@item MHD_OPTION_NOTIFY_CONNECTION
|
||||
Register a function that should be called when the TCP connection to a
|
||||
client is opened or closed. Note that
|
||||
@code{MHD_OPTION_NOTIFY_COMPLETED} and the @code{con_cls} argument to
|
||||
the @code{MHD_AccessHandlerCallback} are per HTTP request (and there
|
||||
can be multiple HTTP requests per TCP connection). The registered
|
||||
callback is called twice per TCP connection, with
|
||||
@code{MHD_CONNECTION_NOTIFY_STARTED} and
|
||||
@code{MHD_CONNECTION_NOTIFY_CLOSED} respectively. An additional
|
||||
argument can be used to store TCP connection specific information,
|
||||
which can be retrieved using @code{MHD_CONNECTION_INFO_SOCKET_CONTEXT}
|
||||
during the lifetime of the TCP connection. The respective location is
|
||||
not the same as the HTTP-request-specific @code{con_cls} from the
|
||||
@code{MHD_AccessHandlerCallback}.
|
||||
|
||||
This option should be followed by @strong{TWO} pointers. First a
|
||||
pointer to a function of type @code{MHD_NotifyConnectionCallback()}
|
||||
and second a pointer to a closure to pass to the request completed
|
||||
callback. The second pointer maybe @code{NULL}.
|
||||
|
||||
@item MHD_OPTION_PER_IP_CONNECTION_LIMIT
|
||||
Limit on the number of (concurrent) connections made to the
|
||||
@@ -2579,6 +2598,14 @@ automatically (if the platform supports it). As the connection
|
||||
callbacks are invoked in between, those might be used to set different
|
||||
values for TCP-CORK and TCP-NODELAY in the meantime.
|
||||
|
||||
@item MHD_CONNECTION_INFO_SOCKET_CONTEXT
|
||||
Returns the client-specific pointer to a @code{void *} that was
|
||||
(possibly) set during a @code{MHD_NotifyConnectionCallback} when the
|
||||
socket was first accepted. Note that this is NOT the same as the
|
||||
@code{con_cls} argument of the @code{MHD_AccessHandlerCallback}. The
|
||||
@code{con_cls} is fresh for each HTTP request, while the
|
||||
@code{socket_context} is fresh for each socket.
|
||||
|
||||
@end table
|
||||
@end deftp
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ typedef intptr_t ssize_t;
|
||||
* Current version of the library.
|
||||
* 0x01093001 = 1.9.30-1.
|
||||
*/
|
||||
#define MHD_VERSION 0x00093903
|
||||
#define MHD_VERSION 0x00093904
|
||||
|
||||
/**
|
||||
* MHD-internal return code for "YES".
|
||||
@@ -871,7 +871,19 @@ enum MHD_OPTION
|
||||
* `const char *` argument.
|
||||
* This should be used in conjunction with #MHD_OPTION_HTTPS_MEM_KEY.
|
||||
*/
|
||||
MHD_OPTION_HTTPS_KEY_PASSWORD = 26
|
||||
MHD_OPTION_HTTPS_KEY_PASSWORD = 26,
|
||||
|
||||
/**
|
||||
* Register a function that should be called whenever a connection is
|
||||
* started or closed.
|
||||
*
|
||||
* This option should be followed by TWO pointers. First a pointer
|
||||
* to a function of type #MHD_NotifyConnectionCallback and second a
|
||||
* pointer to a closure to pass to the request completed callback.
|
||||
* The second pointer maybe NULL.
|
||||
*/
|
||||
MHD_OPTION_NOTIFY_CONNECTION = 27
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1005,6 +1017,29 @@ enum MHD_RequestTerminationCode
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The `enum MHD_ConnectionNotificationCode` specifies types
|
||||
* of connection notifications.
|
||||
* @ingroup request
|
||||
*/
|
||||
enum MHD_ConnectionNotificationCode
|
||||
{
|
||||
|
||||
/**
|
||||
* A new connection has been started.
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_CONNECTION_NOTIFY_STARTED = 0,
|
||||
|
||||
/**
|
||||
* A connection is closed.
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_CONNECTION_NOTIFY_CLOSED = 1
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Information about a connection.
|
||||
*/
|
||||
@@ -1046,6 +1081,12 @@ union MHD_ConnectionInfo
|
||||
* daemons running).
|
||||
*/
|
||||
struct MHD_Daemon *daemon;
|
||||
|
||||
/**
|
||||
* Socket-specific client context. Points to the same address as
|
||||
* the "socket_context" of the #MHD_NotifyConnectionCallback.
|
||||
*/
|
||||
void **socket_context;
|
||||
};
|
||||
|
||||
|
||||
@@ -1104,7 +1145,17 @@ enum MHD_ConnectionInfoType
|
||||
* No extra arguments should be passed.
|
||||
* @ingroup request
|
||||
*/
|
||||
MHD_CONNECTION_INFO_CONNECTION_FD
|
||||
MHD_CONNECTION_INFO_CONNECTION_FD,
|
||||
|
||||
/**
|
||||
* Returns the client-specific pointer to a `void *` that was (possibly)
|
||||
* set during a #MHD_NotifyConnectionCallback when the socket was
|
||||
* first accepted. Note that this is NOT the same as the "con_cls"
|
||||
* argument of the #MHD_AccessHandlerCallback. The "con_cls" is
|
||||
* fresh for each HTTP request, while the "socket_context" is fresh
|
||||
* for each socket.
|
||||
*/
|
||||
MHD_CONNECTION_INFO_SOCKET_CONTEXT
|
||||
|
||||
};
|
||||
|
||||
@@ -1243,6 +1294,31 @@ typedef void
|
||||
void **con_cls,
|
||||
enum MHD_RequestTerminationCode toe);
|
||||
|
||||
/**
|
||||
* Signature of the callback used by MHD to notify the
|
||||
* application about started/stopped connections
|
||||
*
|
||||
* @param cls client-defined closure
|
||||
* @param connection connection handle
|
||||
* @param socket_context socket-specific pointer where the
|
||||
* client can associate some state specific
|
||||
* to the TCP connection; note that this is
|
||||
* different from the "con_cls" which is per
|
||||
* HTTP request. The client can initialize
|
||||
* during #MHD_CONNECTION_NOTIFY_STARTED and
|
||||
* cleanup during #MHD_CONNECTION_NOTIFY_CLOSED
|
||||
* and access in the meantime using
|
||||
* #MHD_CONNECTION_INFO_SOCKET_CONTEXT.
|
||||
* @param toe reason for connection notification
|
||||
* @see #MHD_OPTION_NOTIFY_CONNECTION
|
||||
* @ingroup request
|
||||
*/
|
||||
typedef void
|
||||
(*MHD_NotifyConnectionCallback) (void *cls,
|
||||
struct MHD_Connection *connection,
|
||||
void **socket_context,
|
||||
enum MHD_ConnectionNotificationCode toe);
|
||||
|
||||
|
||||
/**
|
||||
* Iterator over key-value pairs. This iterator
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of libmicrohttpd
|
||||
Copyright (C) 2007-2013 Daniel Pittman and Christian Grothoff
|
||||
Copyright (C) 2007-2015 Daniel Pittman and Christian Grothoff
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
||||
+39
-7
@@ -796,6 +796,7 @@ MHD_handle_connection (void *data)
|
||||
struct pollfd p[1];
|
||||
#endif
|
||||
|
||||
|
||||
timeout = con->daemon->connection_timeout;
|
||||
while ( (MHD_YES != con->daemon->shutdown) &&
|
||||
(MHD_CONNECTION_CLOSED != con->state) )
|
||||
@@ -958,6 +959,13 @@ exit:
|
||||
MHD_destroy_response (con->response);
|
||||
con->response = NULL;
|
||||
}
|
||||
|
||||
if (NULL != con->daemon->notify_connection)
|
||||
con->daemon->notify_connection (con->daemon->notify_connection_cls,
|
||||
con,
|
||||
&con->socket_context,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
|
||||
return (MHD_THRD_RTRN_TYPE_)0;
|
||||
}
|
||||
|
||||
@@ -1301,7 +1309,9 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
errno = eno;
|
||||
return MHD_NO;
|
||||
}
|
||||
memset (connection, 0, sizeof (struct MHD_Connection));
|
||||
memset (connection,
|
||||
0,
|
||||
sizeof (struct MHD_Connection));
|
||||
connection->pool = MHD_pool_create (daemon->pool_size);
|
||||
if (NULL == connection->pool)
|
||||
{
|
||||
@@ -1445,11 +1455,19 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
(MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) )
|
||||
MHD_PANIC ("Failed to release cleanup mutex\n");
|
||||
|
||||
if (NULL != daemon->notify_connection)
|
||||
daemon->notify_connection (daemon->notify_connection_cls,
|
||||
connection,
|
||||
&connection->socket_context,
|
||||
MHD_CONNECTION_NOTIFY_STARTED);
|
||||
|
||||
/* attempt to create handler thread */
|
||||
if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
|
||||
{
|
||||
res_thread_create = create_thread (&connection->pid, daemon,
|
||||
&MHD_handle_connection, connection);
|
||||
res_thread_create = create_thread (&connection->pid,
|
||||
daemon,
|
||||
&MHD_handle_connection,
|
||||
connection);
|
||||
if (0 != res_thread_create)
|
||||
{
|
||||
eno = errno;
|
||||
@@ -1508,6 +1526,11 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
||||
daemon->connections++;
|
||||
return MHD_YES;
|
||||
cleanup:
|
||||
if (NULL != daemon->notify_connection)
|
||||
daemon->notify_connection (daemon->notify_connection_cls,
|
||||
connection,
|
||||
&connection->socket_context,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
if (0 != MHD_socket_close_ (client_socket))
|
||||
MHD_PANIC ("close failed\n");
|
||||
MHD_ip_limit_del (daemon, addr, addrlen);
|
||||
@@ -1921,12 +1944,15 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon)
|
||||
}
|
||||
MHD_pool_destroy (pos->pool);
|
||||
#if HTTPS_SUPPORT
|
||||
if (pos->tls_session != NULL)
|
||||
if (NULL != pos->tls_session)
|
||||
gnutls_deinit (pos->tls_session);
|
||||
#endif
|
||||
MHD_ip_limit_del (daemon,
|
||||
(struct sockaddr *) pos->addr,
|
||||
pos->addr_len);
|
||||
if (NULL != daemon->notify_connection)
|
||||
daemon->notify_connection (daemon->notify_connection_cls,
|
||||
pos,
|
||||
&pos->socket_context,
|
||||
MHD_CONNECTION_NOTIFY_CLOSED);
|
||||
MHD_ip_limit_del (daemon, pos->addr, pos->addr_len);
|
||||
#if EPOLL_SUPPORT
|
||||
if (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
|
||||
{
|
||||
@@ -2993,6 +3019,11 @@ parse_options_va (struct MHD_Daemon *daemon,
|
||||
va_arg (ap, MHD_RequestCompletedCallback);
|
||||
daemon->notify_completed_cls = va_arg (ap, void *);
|
||||
break;
|
||||
case MHD_OPTION_NOTIFY_CONNECTION:
|
||||
daemon->notify_connection =
|
||||
va_arg (ap, MHD_NotifyConnectionCallback);
|
||||
daemon->notify_connection_cls = va_arg (ap, void *);
|
||||
break;
|
||||
case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
|
||||
daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
|
||||
break;
|
||||
@@ -3234,6 +3265,7 @@ parse_options_va (struct MHD_Daemon *daemon,
|
||||
break;
|
||||
/* all options taking two pointers */
|
||||
case MHD_OPTION_NOTIFY_COMPLETED:
|
||||
case MHD_OPTION_NOTIFY_CONNECTION:
|
||||
case MHD_OPTION_URI_LOG_CALLBACK:
|
||||
case MHD_OPTION_EXTERNAL_LOGGER:
|
||||
case MHD_OPTION_UNESCAPE_CALLBACK:
|
||||
|
||||
+51
-23
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of libmicrohttpd
|
||||
Copyright (C) 2007-2013 Daniel Pittman and Christian Grothoff
|
||||
Copyright (C) 2007-2015 Daniel Pittman and Christian Grothoff
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -487,8 +487,10 @@ MHD_state_to_string (enum MHD_CONNECTION_STATE state);
|
||||
* @param max_bytes maximum number of bytes to receive
|
||||
* @return number of bytes written to write_to
|
||||
*/
|
||||
typedef ssize_t (*ReceiveCallback) (struct MHD_Connection * conn,
|
||||
void *write_to, size_t max_bytes);
|
||||
typedef ssize_t
|
||||
(*ReceiveCallback) (struct MHD_Connection *conn,
|
||||
void *write_to,
|
||||
size_t max_bytes);
|
||||
|
||||
|
||||
/**
|
||||
@@ -499,8 +501,10 @@ typedef ssize_t (*ReceiveCallback) (struct MHD_Connection * conn,
|
||||
* @param max_bytes maximum number of bytes to transmit
|
||||
* @return number of bytes transmitted
|
||||
*/
|
||||
typedef ssize_t (*TransmitCallback) (struct MHD_Connection * conn,
|
||||
const void *write_to, size_t max_bytes);
|
||||
typedef ssize_t
|
||||
(*TransmitCallback) (struct MHD_Connection *conn,
|
||||
const void *write_to,
|
||||
size_t max_bytes);
|
||||
|
||||
|
||||
/**
|
||||
@@ -578,13 +582,22 @@ struct MHD_Connection
|
||||
struct MemoryPool *pool;
|
||||
|
||||
/**
|
||||
* We allow the main application to associate some
|
||||
* pointer with the connection. Here is where we
|
||||
* store it. (MHD does not know or care what it
|
||||
* is).
|
||||
* We allow the main application to associate some pointer with the
|
||||
* HTTP request, which is passed to each #MHD_AccessHandlerCallback
|
||||
* and some other API calls. Here is where we store it. (MHD does
|
||||
* not know or care what it is).
|
||||
*/
|
||||
void *client_context;
|
||||
|
||||
/**
|
||||
* We allow the main application to associate some pointer with the
|
||||
* TCP connection (which may span multiple HTTP requests). Here is
|
||||
* where we store it. (MHD does not know or care what it is).
|
||||
* The location is given to the #MHD_NotifyConnectionCallback and
|
||||
* also accessible via #MHD_CONNECTION_INFO_SOCKET_CONTEXT.
|
||||
*/
|
||||
void *socket_context;
|
||||
|
||||
/**
|
||||
* Request method. Should be GET/POST/etc. Allocated
|
||||
* in pool.
|
||||
@@ -606,7 +619,7 @@ struct MHD_Connection
|
||||
/**
|
||||
* Buffer for reading requests. Allocated
|
||||
* in pool. Actually one byte larger than
|
||||
* read_buffer_size (if non-NULL) to allow for
|
||||
* @e read_buffer_size (if non-NULL) to allow for
|
||||
* 0-termination.
|
||||
*/
|
||||
char *read_buffer;
|
||||
@@ -620,7 +633,8 @@ struct MHD_Connection
|
||||
/**
|
||||
* Last incomplete header line during parsing of headers.
|
||||
* Allocated in pool. Only valid if state is
|
||||
* either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
|
||||
* either #MHD_CONNECTION_HEADER_PART_RECEIVED or
|
||||
* #MHD_CONNECTION_FOOTER_PART_RECEIVED.
|
||||
*/
|
||||
char *last;
|
||||
|
||||
@@ -628,12 +642,13 @@ struct MHD_Connection
|
||||
* Position after the colon on the last incomplete header
|
||||
* line during parsing of headers.
|
||||
* Allocated in pool. Only valid if state is
|
||||
* either HEADER_PART_RECEIVED or FOOTER_PART_RECEIVED.
|
||||
* either #MHD_CONNECTION_HEADER_PART_RECEIVED or
|
||||
* #MHD_CONNECTION_FOOTER_PART_RECEIVED.
|
||||
*/
|
||||
char *colon;
|
||||
|
||||
/**
|
||||
* Foreign address (of length addr_len). MALLOCED (not
|
||||
* Foreign address (of length @e addr_len). MALLOCED (not
|
||||
* in pool!).
|
||||
*/
|
||||
struct sockaddr *addr;
|
||||
@@ -676,7 +691,7 @@ struct MHD_Connection
|
||||
|
||||
/**
|
||||
* How many more bytes of the body do we expect
|
||||
* to read? MHD_SIZE_UNKNOWN for unknown.
|
||||
* to read? #MHD_SIZE_UNKNOWN for unknown.
|
||||
*/
|
||||
uint64_t remaining_upload_size;
|
||||
|
||||
@@ -800,17 +815,17 @@ struct MHD_Connection
|
||||
/**
|
||||
* Handler used for processing read connection operations
|
||||
*/
|
||||
int (*read_handler) (struct MHD_Connection * connection);
|
||||
int (*read_handler) (struct MHD_Connection *connection);
|
||||
|
||||
/**
|
||||
* Handler used for processing write connection operations
|
||||
*/
|
||||
int (*write_handler) (struct MHD_Connection * connection);
|
||||
int (*write_handler) (struct MHD_Connection *connection);
|
||||
|
||||
/**
|
||||
* Handler used for processing idle connection operations
|
||||
*/
|
||||
int (*idle_handler) (struct MHD_Connection * connection);
|
||||
int (*idle_handler) (struct MHD_Connection *connection);
|
||||
|
||||
/**
|
||||
* Function used for reading HTTP request stream.
|
||||
@@ -864,9 +879,10 @@ struct MHD_Connection
|
||||
* @param con connection handle
|
||||
* @return new closure
|
||||
*/
|
||||
typedef void * (*LogCallback)(void * cls,
|
||||
const char * uri,
|
||||
struct MHD_Connection *con);
|
||||
typedef void *
|
||||
(*LogCallback)(void * cls,
|
||||
const char * uri,
|
||||
struct MHD_Connection *con);
|
||||
|
||||
/**
|
||||
* Signature of function called to unescape URIs. See also
|
||||
@@ -877,9 +893,10 @@ typedef void * (*LogCallback)(void * cls,
|
||||
* @param uri 0-terminated string to unescape (should be updated)
|
||||
* @return length of the resulting string
|
||||
*/
|
||||
typedef size_t (*UnescapeCallback)(void *cls,
|
||||
struct MHD_Connection *conn,
|
||||
char *uri);
|
||||
typedef size_t
|
||||
(*UnescapeCallback)(void *cls,
|
||||
struct MHD_Connection *conn,
|
||||
char *uri);
|
||||
|
||||
|
||||
/**
|
||||
@@ -999,6 +1016,17 @@ struct MHD_Daemon
|
||||
*/
|
||||
void *notify_completed_cls;
|
||||
|
||||
/**
|
||||
* Function to call when we are starting/stopping
|
||||
* a connection. May be NULL.
|
||||
*/
|
||||
MHD_NotifyConnectionCallback notify_connection;
|
||||
|
||||
/**
|
||||
* Closure argument to notify_connection.
|
||||
*/
|
||||
void *notify_connection_cls;
|
||||
|
||||
/**
|
||||
* Function to call with the full URI at the
|
||||
* beginning of request processing. May be NULL.
|
||||
|
||||
Reference in New Issue
Block a user