27 #include <microhttpd.h>
35 #define GNUNET_REST_SERVICE_PORT 7776
41 #define MAX_HTTP_URI_LENGTH 2048
51 #define HTTPS_PORT 443
56 #define MHD_CACHE_TIMEOUT \
57 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
59 #define GN_REST_STATE_INIT 0
60 #define GN_REST_STATE_PROCESSING 1
174 struct MHD_Connection *
con;
180 struct MHD_PostProcessor *
pp;
270 MHD_resume_connection (
handle->con);
285 if (NULL !=
handle->response)
286 MHD_destroy_response (
handle->response);
287 if (NULL !=
handle->data_handle)
289 if (NULL !=
handle->data_handle->header_param_map)
296 handle->data_handle->header_param_map);
298 if (NULL !=
handle->data_handle->url_param_map)
304 handle->data_handle->url_param_map);
333 enum MHD_ValueKind kind,
353 "Could not load add header `%s'=%s\n",
364 enum MHD_ValueKind kind,
381 "Could not load add url param `%s'=%s\n",
391 enum MHD_ValueKind kind,
394 const char *content_type,
395 const char *transfer_encoding,
404 if (MHD_POSTDATA_KIND != kind)
420 "Could not add url param '%s'\n",
457 struct MHD_Connection *con,
461 const char *upload_data,
462 size_t *upload_data_size,
483 con_handle->
con = con;
492 rest_conndata_handle->
method = meth;
493 rest_conndata_handle->
url = url;
494 rest_conndata_handle->
data = upload_data;
495 rest_conndata_handle->
data_size = *upload_data_size;
501 MHD_get_connection_values (con,
502 MHD_GET_ARGUMENT_KIND,
504 rest_conndata_handle);
505 MHD_get_connection_values (con,
508 rest_conndata_handle);
510 con_handle->
pp = MHD_create_post_processor (con,
513 rest_conndata_handle);
514 if (*upload_data_size)
516 MHD_post_process (con_handle->
pp, upload_data, *upload_data_size);
518 MHD_destroy_post_processor (con_handle->
pp);
533 *upload_data_size = 0;
540 MHD_suspend_connection (con_handle->
con);
545 "Queueing response from plugin with MHD\n");
559 strncmp (
"moz-extension://", origin, strlen (
"moz-extension://"))) ||
560 (0 == strncmp (
"chrome-extension://",
562 strlen (
"chrome-extension://"))))
564 MHD_add_response_header (con_handle->
response,
565 MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
572 char *allow_origin = strtok (tmp,
",");
573 while (NULL != allow_origin)
575 if (0 == strncmp (allow_origin, origin, strlen (allow_origin)))
577 MHD_add_response_header (con_handle->
response,
578 MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN,
582 allow_origin = strtok (NULL,
",");
589 MHD_add_response_header (con_handle->
response,
590 "Access-Control-Allow-Credentials",
595 MHD_add_response_header (con_handle->
response,
596 "Access-Control-Allow-Headers",
621 MHD_stop_daemon (
httpd);
670 MHD_UNSIGNED_LONG_LONG
timeout;
677 if (MHD_YES != MHD_get_fdset (
httpd, &rs, &ws, &es, &
max))
683 if (MHD_YES == haveto)
704 if ((MHD_YES == haveto) || (-1 !=
max))
735 struct MHD_Connection *connection)
738 const union MHD_ConnectionInfo *ci;
740 ci = MHD_get_connection_info (connection,
741 MHD_CONNECTION_INFO_SOCKET_CONTEXT);
748 ar = ci->socket_context;
765 struct MHD_Connection *connection,
767 enum MHD_RequestTerminationCode toe)
770 if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
772 "MHD encountered error handling request: %d\n",
796 struct MHD_Connection *connection,
798 enum MHD_ConnectionNotificationCode cnc)
801 const union MHD_ConnectionInfo *ci;
806 case MHD_CONNECTION_NOTIFY_STARTED:
808 ci = MHD_get_connection_info (connection,
809 MHD_CONNECTION_INFO_CONNECTION_FD);
815 sock = ci->connect_fd;
828 case MHD_CONNECTION_NOTIFY_CLOSED:
830 "Connection closed... cleaning up\n");
835 "Connection stale!\n");
875 const struct sockaddr *addr;
898 if (NULL == ar->
sock)
905 "Got an inbound connection, waiting for data\n");
912 if (MHD_YES != MHD_add_connection (
httpd, fd, addr,
len))
917 _ (
"Failed to pass client to MHD\n"));
960 struct sockaddr_in sa4;
963 memset (&sa4, 0,
sizeof(sa4));
964 sa4.sin_family = AF_INET;
965 sa4.sin_port = htons (
port);
967 #if HAVE_SOCKADDR_IN_SIN_LEN
968 sa4.sin_len =
sizeof(sa4);
974 (
const struct sockaddr *) &sa4,
995 struct sockaddr_in6 sa6;
998 memset (&sa6, 0,
sizeof(sa6));
999 sa6.sin6_family = AF_INET6;
1000 sa6.sin6_port = htons (
port);
1002 #if HAVE_SOCKADDR_IN_SIN_LEN
1003 sa6.sin6_len =
sizeof(sa6);
1009 (
const struct sockaddr *) &sa6,
1034 if (NULL == lib_ret)
1037 "Could not load plugin `%s'\n",
1064 const char *cfgfile,
1090 if (1 != inet_pton (AF_INET, addr_str, &
address))
1093 "Unable to parse address %s\n",
1111 if (1 != inet_pton (AF_INET6, addr_str, &
address6))
1114 "Unable to parse IPv6 address %s\n",
1127 "REST_ECHO_ORIGIN_WEBEXT");
1131 "REST_ALLOW_ORIGIN",
1135 "No CORS Access-Control-Allow-Origin header will be sent...\n");
1140 "REST_ALLOW_CREDENTIALS",
1145 "No CORS Credential Header will be sent...\n");
1150 "REST_ALLOW_HEADERS",
1155 "No CORS Access-Control-Allow-Headers Header will be sent...\n");
1207 httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET
1208 | MHD_ALLOW_SUSPEND_RESUME,
1214 MHD_OPTION_CONNECTION_TIMEOUT,
1216 MHD_OPTION_NOTIFY_CONNECTION,
1219 MHD_OPTION_URI_LOG_CALLBACK,
1222 MHD_OPTION_NOTIFY_COMPLETED,
1233 "libgnunet_plugin_rest",
1255 static const char *err_page =
"{}";
1263 MHD_RESPMEM_PERSISTENT);
1266 "gnunet-rest-server",
1267 _ (
"GNUnet REST server"),
struct GNUNET_GETOPT_CommandLineOption GNUNET_GETOPT_OPTION_END
struct GNUNET_GETOPT_CommandLineOption options[]
static int ret
Return value of the commandline.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
struct Plugin * plugin
The process handle to the testbed service.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
uint32_t data
The data value.
uint16_t status
See PRISM_STATUS_*-constants.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * value
Value of the record to add/remove.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
static char * allow_origins
Allowed Origins (CORS)
static void plugin_callback(void *cls, struct MHD_Response *resp, int status)
Plugin result callback.
#define GNUNET_REST_SERVICE_PORT
Default Socks5 listen port.
static struct AcceptedRequest * req_list_head
AcceptedRequest list head.
static void * mhd_log_callback(void *cls, const char *url, struct MHD_Connection *connection)
Function called when MHD first processes an incoming connection.
static struct GNUNET_NETWORK_Handle * bind_v6()
Create an IPv6 listen socket bound to our port.
static void run_mhd_now()
Run MHD now, we have extra data ready for the callback.
static struct MHD_Daemon * httpd
Daemon for HTTP.
static MHD_RESULT post_data_iter(void *cls, enum MHD_ValueKind kind, const char *key, const char *filename, const char *content_type, const char *transfer_encoding, const char *data, uint64_t off, size_t size)
static struct GNUNET_NETWORK_Handle * lsock6
The listen socket of the service for IPv6.
#define GN_REST_STATE_INIT
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static char * allow_headers
Allowed Headers (CORS)
static MHD_RESULT create_response(void *cls, struct MHD_Connection *con, const char *url, const char *meth, const char *ver, const char *upload_data, size_t *upload_data_size, void **con_cls)
Main MHD callback for handling requests.
static struct GNUNET_NETWORK_Handle * lsock4
The listen socket of the service for IPv4.
static void kill_httpd()
Kill the MHD daemon.
static struct in6_addr address6
The IPv6 address to bind to.
static unsigned long long port
The port the service is running on (default 7776)
#define GN_REST_STATE_PROCESSING
static void do_shutdown(void *cls)
Task run on shutdown.
static void cleanup_ar(struct AcceptedRequest *ar)
static void mhd_completed_cb(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
Function called when MHD decides that we are done with a connection.
static int url_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
static int cleanup_url_map(void *cls, const struct GNUNET_HashCode *key, void *value)
static void run(void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
Main function that will be run.
static void do_httpd(void *cls)
Task run whenever HTTP server operations are pending.
static void do_accept(void *cls)
Accept new incoming connections.
static int header_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
static struct PluginListEntry * plugins_tail
Plugin list tail.
static struct GNUNET_SCHEDULER_Task * httpd_task
The task ID.
static int echo_origin
Echo request Origin in CORS.
static struct AcceptedRequest * req_list_tail
AcceptedRequest list tail.
static void load_plugin(void *cls, const char *libname, void *lib_ret)
Callback for plugin load.
int main(int argc, char *const *argv)
The main function for gnunet-rest-service.
static char * allow_credentials
Allowed Credentials (CORS)
static void schedule_httpd()
Schedule MHD.
static struct MHD_Response * failure_response
Response we return on failures.
static in_addr_t address
The address to bind to.
static void mhd_connection_cb(void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_ConnectionNotificationCode cnc)
Function called when MHD connection is opened or closed.
static struct PluginListEntry * plugins_head
Plugin list head.
static void cleanup_handle(struct MhdConnectionHandle *handle)
static struct GNUNET_SCHEDULER_Task * ltask6
The listen task ID for IPv6.
static struct GNUNET_SCHEDULER_Task * ltask4
The listen task ID for IPv4.
static struct GNUNET_NETWORK_Handle * bind_v4()
Create an IPv4 listen socket bound to our port.
#define GNUNET_log(kind,...)
@ GNUNET_SCHEDULER_PRIORITY_DEFAULT
Run with the default priority (normal P2P operations).
#define MHD_RESULT
Data type to use for functions return an "MHD result".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_free_nz(ptr)
Wrapper around free.
struct sockaddr * GNUNET_NETWORK_get_addr(const struct GNUNET_NETWORK_Handle *desc)
Return the sockaddr for this network handle.
struct GNUNET_NETWORK_FDSet * GNUNET_NETWORK_fdset_create(void)
Creates an fd set.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
void GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
Releases the associated memory of an fd set.
socklen_t GNUNET_NETWORK_get_addrlen(const struct GNUNET_NETWORK_Handle *desc)
Return sockaddr length for this network handle.
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
void GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to, const fd_set *from, int nfds)
Copy a native fd set into the GNUnet representation.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc, struct sockaddr *address, socklen_t *address_len)
Accept a new connection on a socket.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
void GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
Only free memory of a socket, keep the file descriptor untouched.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_default(void)
Return default project data used by 'libgnunetutil' for GNUnet.
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
void GNUNET_PLUGIN_load_all_in_context(const struct GNUNET_OS_ProjectData *ctx, const char *basename, void *arg, GNUNET_PLUGIN_LoaderCallback cb, void *cb_cls)
Load all compatible plugins with the given base name while inside the given context (i....
enum GNUNET_GenericReturnValue GNUNET_PROGRAM_run(int argc, char *const *argv, const char *binaryName, const char *binaryHelp, const struct GNUNET_GETOPT_CommandLineOption *options, GNUNET_PROGRAM_Main task, void *task_cls)
Run a standard GNUnet command startup sequence (initialize loggers and configuration,...
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_select(enum GNUNET_SCHEDULER_Priority prio, struct GNUNET_TIME_Relative delay, const struct GNUNET_NETWORK_FDSet *rs, const struct GNUNET_NETWORK_FDSet *ws, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when any of the specified file descriptor set...
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_get_utf8_args(int argc, char *const *argv, int *u8argc, char *const **u8argv)
Returns utf-8 encoded arguments.
enum GNUNET_GenericReturnValue GNUNET_STRINGS_utf8_tolower(const char *input, char *output)
Convert the utf-8 input string to lower case.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static unsigned int size
Size of the "table".
struct AcceptedRequest * prev
DLL.
int socket_with_mhd
State.
struct MhdConnectionHandle * con_handle
Connection.
struct GNUNET_NETWORK_Handle * sock
Socket.
struct AcceptedRequest * next
DLL.
Definition of a command line option.
collection of IO descriptors
struct returned by the initialization function of the plugin
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
struct GNUNET_CONTAINER_MultiHashMap * header_param_map
Map of headers.
const char * data
The POST data.
const char * url
The url as string.
const char * method
The HTTP method as MHD value (see microhttpd.h)
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
size_t data_size
The POST data size.
Entry in list of pending tasks.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
struct GNUNET_REST_RequestHandle * data_handle
struct MHD_PostProcessor * pp
struct MHD_Response * response
struct MHD_Connection * con
struct PluginListEntry * prev
struct GNUNET_REST_Plugin * plugin
The plugin.
char * libname
libname (to cleanup)
struct PluginListEntry * next