adding MHD_OPTION_ARRAY

This commit is contained in:
Christian Grothoff
2009-12-04 12:17:07 +00:00
parent 4856b2cf00
commit bf1d64a78d
3 changed files with 298 additions and 78 deletions
+39
View File
@@ -384,10 +384,49 @@ Note that MHD will not generate any log messages
if it was compiled without the "--enable-messages"
flag being set and the MHD_USE_DEBUG flag being set,
even if this argument is used.
@item MHD_OPTION_ARRAY
@cindex options
This option can be used for initializing MHD using options from an
array. A common use for this is writing an FFI for MHD. The actual
options given are in an array of 'struct MHD_OptionItem', so this
option requires a single argument of type 'struct MHD_OptionItem'.
The array must be terminated with an entry @code{MHD_OPTION_END}.
An example for code using MHD_OPTION_ARRAY is:
@example
struct MHD_OptionItem ops[] = @{
@{ MHD_OPTION_CONNECTION_LIMIT, 100, NULL @},
@{ MHD_OPTION_CONNECTION_TIMEOUT, 10, NULL @},
@{ MHD_OPTION_END, 0, NULL @}
@};
d = MHD_start_daemon(0, 8080, NULL, NULL, dh, NULL,
MHD_OPTION_ARRAY, ops,
MHD_OPTION_END);
@end example
For options that expect a single pointer argument, the
second member of the @code{struct MHD_OptionItem} is ignored.
For options that expect two pointer arguments, the first
argument must be cast to @code{intptr_t}.
@end table
@end deftp
@deftp {C Struct} MHD_OptionItem
Entry in an MHD_OPTION_ARRAY. See the @code{MHD_OPTION_ARRAY} option
argument for its use.
The @code{option} member is used to specify which option is specified
in the array. The other members specify the respective argument.
Note that for options taking only a single pointer, the
@code{ptr_value} member should be set. For options taking two pointer
arguments, the first pointer must be cast to @code{intptr_t} and both
the @code{value} and the @code{ptr_value} members should be used to
pass the two pointers.
@end deftp
@deftp {Enumeration} MHD_ValueKind
The @code{MHD_ValueKind} specifies the source of the key-value pairs in
the @http{} protocol.
+209 -77
View File
@@ -1141,6 +1141,212 @@ MHD_start_daemon (unsigned int options,
typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list);
/**
* Parse a list of options given as varargs.
*
* @param daemon the daemon to initialize
* @param ap the options
* @return MHD_YES on success, MHD_NO on error
*/
static int
parse_options_va (struct MHD_Daemon *daemon,
const struct sockaddr **servaddr,
va_list ap);
/**
* Parse a list of options given as varargs.
*
* @param daemon the daemon to initialize
* @param ... the options
* @return MHD_YES on success, MHD_NO on error
*/
static int
parse_options (struct MHD_Daemon *daemon,
const struct sockaddr **servaddr,
...)
{
va_list ap;
int ret;
va_start (ap, servaddr);
ret = parse_options_va (daemon, servaddr, ap);
va_end (ap);
return ret;
}
/**
* Parse a list of options given as varargs.
*
* @param daemon the daemon to initialize
* @param ap the options
* @return MHD_YES on success, MHD_NO on error
*/
static int
parse_options_va (struct MHD_Daemon *daemon,
const struct sockaddr **servaddr,
va_list ap)
{
enum MHD_OPTION opt;
struct MHD_OptionItem *oa;
unsigned int i;
while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
{
switch (opt)
{
case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
daemon->pool_size = va_arg (ap, size_t);
break;
case MHD_OPTION_CONNECTION_LIMIT:
daemon->max_connections = va_arg (ap, unsigned int);
break;
case MHD_OPTION_CONNECTION_TIMEOUT:
daemon->connection_timeout = va_arg (ap, unsigned int);
break;
case MHD_OPTION_NOTIFY_COMPLETED:
daemon->notify_completed =
va_arg (ap, MHD_RequestCompletedCallback);
daemon->notify_completed_cls = va_arg (ap, void *);
break;
case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
daemon->per_ip_connection_limit = va_arg (ap, unsigned int);
break;
case MHD_OPTION_SOCK_ADDR:
*servaddr = va_arg (ap, const struct sockaddr *);
break;
case MHD_OPTION_URI_LOG_CALLBACK:
daemon->uri_log_callback =
va_arg (ap, LogCallback);
daemon->uri_log_callback_cls = va_arg (ap, void *);
break;
case MHD_OPTION_THREAD_POOL_SIZE:
daemon->worker_pool_size = va_arg (ap, unsigned int);
break;
#if HTTPS_SUPPORT
case MHD_OPTION_PROTOCOL_VERSION:
_set_priority (&daemon->priority_cache->protocol,
va_arg (ap, const int *));
break;
case MHD_OPTION_HTTPS_MEM_KEY:
daemon->https_mem_key = va_arg (ap, const char *);
break;
case MHD_OPTION_HTTPS_MEM_CERT:
daemon->https_mem_cert = va_arg (ap, const char *);
break;
case MHD_OPTION_CIPHER_ALGORITHM:
_set_priority (&daemon->priority_cache->cipher,
va_arg (ap, const int *));
break;
#endif
case MHD_OPTION_EXTERNAL_LOGGER:
#if HAVE_MESSAGES
daemon->custom_error_log =
va_arg (ap, VfprintfFunctionPointerType);
daemon->custom_error_log_cls = va_arg (ap, void *);
#else
va_arg (ap, VfprintfFunctionPointerType);
va_arg (ap, void *);
#endif
break;
case MHD_OPTION_ARRAY:
oa = va_arg (ap, struct MHD_OptionItem*);
i = 0;
while (MHD_OPTION_END != (opt = oa[i].option))
{
switch (opt)
{
case MHD_OPTION_END:
abort ();
break;
/* all options taking 'size_t' */
case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
if (MHD_YES != parse_options (daemon,
servaddr,
opt,
(size_t) oa[i].value,
MHD_OPTION_END))
return MHD_NO;
break;
/* all options taking 'unsigned int' */
case MHD_OPTION_CONNECTION_LIMIT:
case MHD_OPTION_CONNECTION_TIMEOUT:
case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
case MHD_OPTION_THREAD_POOL_SIZE:
if (MHD_YES != parse_options (daemon,
servaddr,
opt,
(unsigned int) oa[i].value,
MHD_OPTION_END))
return MHD_NO;
break;
/* all options taking 'int' or 'enum' */
case MHD_OPTION_CRED_TYPE:
if (MHD_YES != parse_options (daemon,
servaddr,
opt,
(int) oa[i].value,
MHD_OPTION_END))
return MHD_NO;
break;
/* all options taking one pointer */
case MHD_OPTION_SOCK_ADDR:
case MHD_OPTION_HTTPS_MEM_KEY:
case MHD_OPTION_HTTPS_MEM_CERT:
case MHD_OPTION_PROTOCOL_VERSION:
case MHD_OPTION_CIPHER_ALGORITHM:
case MHD_OPTION_ARRAY:
if (MHD_YES != parse_options (daemon,
servaddr,
opt,
oa[i].ptr_value,
MHD_OPTION_END))
return MHD_NO;
break;
/* all options taking two pointers */
case MHD_OPTION_NOTIFY_COMPLETED:
case MHD_OPTION_URI_LOG_CALLBACK:
case MHD_OPTION_EXTERNAL_LOGGER:
if (MHD_YES != parse_options (daemon,
servaddr,
opt,
(void *) oa[i].value,
oa[i].ptr_value,
MHD_OPTION_END))
return MHD_NO;
break;
default:
return MHD_NO;
}
i++;
}
break;
default:
#if HAVE_MESSAGES
if ((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
(opt <= MHD_OPTION_CIPHER_ALGORITHM))
{
FPRINTF (stderr,
"MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
opt);
}
else
{
FPRINTF (stderr,
"Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
opt);
}
#endif
return MHD_NO;
}
}
return MHD_YES;
}
/**
* Start a webserver on the given port.
*
@@ -1168,7 +1374,6 @@ MHD_start_daemon_va (unsigned int options,
#endif
const struct sockaddr *servaddr = NULL;
socklen_t addrlen;
enum MHD_OPTION opt;
unsigned int i;
if ((port == 0) || (dh == NULL))
@@ -1215,83 +1420,10 @@ MHD_start_daemon_va (unsigned int options,
}
#endif
while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
if (MHD_YES != parse_options_va (retVal, &servaddr, ap))
{
switch (opt)
{
case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
retVal->pool_size = va_arg (ap, size_t);
break;
case MHD_OPTION_CONNECTION_LIMIT:
retVal->max_connections = va_arg (ap, unsigned int);
break;
case MHD_OPTION_CONNECTION_TIMEOUT:
retVal->connection_timeout = va_arg (ap, unsigned int);
break;
case MHD_OPTION_NOTIFY_COMPLETED:
retVal->notify_completed =
va_arg (ap, MHD_RequestCompletedCallback);
retVal->notify_completed_cls = va_arg (ap, void *);
break;
case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
retVal->per_ip_connection_limit = va_arg (ap, unsigned int);
break;
case MHD_OPTION_SOCK_ADDR:
servaddr = va_arg (ap, struct sockaddr *);
break;
case MHD_OPTION_URI_LOG_CALLBACK:
retVal->uri_log_callback =
va_arg (ap, LogCallback);
retVal->uri_log_callback_cls = va_arg (ap, void *);
break;
case MHD_OPTION_THREAD_POOL_SIZE:
retVal->worker_pool_size = va_arg (ap, unsigned int);
break;
#if HTTPS_SUPPORT
case MHD_OPTION_PROTOCOL_VERSION:
_set_priority (&retVal->priority_cache->protocol,
va_arg (ap, const int *));
break;
case MHD_OPTION_HTTPS_MEM_KEY:
retVal->https_mem_key = va_arg (ap, const char *);
break;
case MHD_OPTION_HTTPS_MEM_CERT:
retVal->https_mem_cert = va_arg (ap, const char *);
break;
case MHD_OPTION_CIPHER_ALGORITHM:
_set_priority (&retVal->priority_cache->cipher,
va_arg (ap, const int *));
break;
#endif
case MHD_OPTION_EXTERNAL_LOGGER:
#if HAVE_MESSAGES
retVal->custom_error_log =
va_arg (ap, VfprintfFunctionPointerType);
retVal->custom_error_log_cls = va_arg (ap, void *);
#else
va_arg (ap, VfprintfFunctionPointerType);
va_arg (ap, void *);
#endif
break;
default:
#if HAVE_MESSAGES
if ((opt >= MHD_OPTION_HTTPS_MEM_KEY) &&
(opt <= MHD_OPTION_CIPHER_ALGORITHM))
{
FPRINTF (stderr,
"MHD HTTPS option %d passed to MHD compiled without HTTPS support\n",
opt);
}
else
{
FPRINTF (stderr,
"Invalid option %d! (Did you terminate the list with MHD_OPTION_END?)\n",
opt);
}
#endif
free (retVal);
return NULL;
}
free (retVal);
return NULL;
}
/* poll support currently only works with MHD_USE_THREAD_PER_CONNECTION */
+50 -1
View File
@@ -453,9 +453,58 @@ enum MHD_OPTION
* (MHD_start_daemon returns NULL for an unsupported thread
* model).
*/
MHD_OPTION_THREAD_POOL_SIZE = 14
MHD_OPTION_THREAD_POOL_SIZE = 14,
/**
* Additional options given in an array of "struct MHD_OptionItem".
* The array must be terminated with an entry '{MHD_OPTION_END, 0, NULL}'.
* An example for code using MHD_OPTION_ARRAY is:
* <code>
* struct MHD_OptionItem ops[] = {
* { MHD_OPTION_CONNECTION_LIMIT, 100, NULL },
* { MHD_OPTION_CONNECTION_TIMEOUT, 10, NULL },
* { MHD_OPTION_END, 0, NULL }
* };
* d = MHD_start_daemon(0, 8080, NULL, NULL, dh, NULL,
* MHD_OPTION_ARRAY, ops,
* MHD_OPTION_END);
* </code>
* For options that expect a single pointer argument, the
* second member of the struct MHD_OptionItem is ignored.
* For options that expect two pointer arguments, the first
* argument must be cast to 'intptr_t'.
*/
MHD_OPTION_ARRAY = 15
};
/**
* Entry in an MHD_OPTION_ARRAY.
*/
struct MHD_OptionItem
{
/**
* Which option is being given. Use MHD_OPTION_END
* to terminate the array.
*/
enum MHD_OPTION option;
/**
* Option value (for integer arguments, and for options requiring
* two pointer arguments); should be 0 for options that take no
* arguments or only a single pointer argument.
*/
intptr_t value;
/**
* Pointer option value (use NULL for options taking no arguments
* or only an integer option).
*/
void *ptr_value;
};
/**
* The MHD_ValueKind specifies the source of
* the key-value pairs in the HTTP protocol.