Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
civetweb.h File Reference
#include <stddef.h>
#include <stdio.h>

Go to the source code of this file.

Data Structures

struct  mg_header
 
struct  mg_request_info
 
struct  mg_response_info
 
struct  mg_client_cert
 
struct  mg_callbacks
 
struct  mg_websocket_subprotocols
 
struct  mg_option
 
struct  mg_server_port
 
struct  mg_form_data_handler
 
struct  mg_match_element
 
struct  mg_match_context
 
struct  mg_client_options
 
struct  mg_error_data
 
struct  mg_init_data
 

Macros

#define CIVETWEB_VERSION   "1.16"
 
#define CIVETWEB_VERSION_MAJOR   (1)
 
#define CIVETWEB_VERSION_MINOR   (16)
 
#define CIVETWEB_VERSION_PATCH   (0)
 
#define CIVETWEB_API
 
#define MG_MAX_HEADERS   (64)
 
#define mg_server_ports   mg_server_port
 
#define PRINTF_FORMAT_STRING(s)   s
 
#define PRINTF_ARGS(x, y)
 
#define MG_MATCH_CONTEXT_MAX_MATCHES   (32)
 

Typedefs

typedef int(* mg_request_handler) (struct mg_connection *conn, void *cbdata)
 
typedef int(* mg_websocket_connect_handler) (const struct mg_connection *, void *)
 
typedef void(* mg_websocket_ready_handler) (struct mg_connection *, void *)
 
typedef int(* mg_websocket_data_handler) (struct mg_connection *, int, char *, size_t, void *)
 
typedef void(* mg_websocket_close_handler) (const struct mg_connection *, void *)
 
typedef int(* mg_authorization_handler) (struct mg_connection *conn, void *cbdata)
 
typedef void *(* mg_thread_func_t) (void *)
 

Enumerations

enum  {
  MG_FEATURES_DEFAULT = 0x0u , MG_FEATURES_FILES = 0x1u , MG_FEATURES_TLS = 0x2u , MG_FEATURES_SSL = 0x2u ,
  MG_FEATURES_CGI = 0x4u , MG_FEATURES_IPV6 = 0x8u , MG_FEATURES_WEBSOCKET = 0x10u , MG_FEATURES_LUA = 0x20u ,
  MG_FEATURES_SSJS = 0x40u , MG_FEATURES_CACHE = 0x80u , MG_FEATURES_STATS = 0x100u , MG_FEATURES_COMPRESSION = 0x200u ,
  MG_FEATURES_HTTP2 = 0x400u , MG_FEATURES_X_DOMAIN_SOCKET = 0x800u , MG_FEATURES_ALL = 0xFFFFu
}
 
enum  {
  MG_CONFIG_TYPE_UNKNOWN = 0x0 , MG_CONFIG_TYPE_NUMBER = 0x1 , MG_CONFIG_TYPE_STRING = 0x2 , MG_CONFIG_TYPE_FILE = 0x3 ,
  MG_CONFIG_TYPE_DIRECTORY = 0x4 , MG_CONFIG_TYPE_BOOLEAN = 0x5 , MG_CONFIG_TYPE_EXT_PATTERN = 0x6 , MG_CONFIG_TYPE_STRING_LIST = 0x7 ,
  MG_CONFIG_TYPE_STRING_MULTILINE = 0x8 , MG_CONFIG_TYPE_YES_NO_OPTIONAL = 0x9
}
 
enum  {
  MG_WEBSOCKET_OPCODE_CONTINUATION = 0x0 , MG_WEBSOCKET_OPCODE_TEXT = 0x1 , MG_WEBSOCKET_OPCODE_BINARY = 0x2 , MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8 ,
  MG_WEBSOCKET_OPCODE_PING = 0x9 , MG_WEBSOCKET_OPCODE_PONG = 0xa
}
 
enum  { MG_FORM_FIELD_STORAGE_SKIP = 0x0 , MG_FORM_FIELD_STORAGE_GET = 0x1 , MG_FORM_FIELD_STORAGE_STORE = 0x2 , MG_FORM_FIELD_STORAGE_ABORT = 0x10 }
 
enum  { MG_FORM_FIELD_HANDLE_GET = 0x1 , MG_FORM_FIELD_HANDLE_NEXT = 0x8 , MG_FORM_FIELD_HANDLE_ABORT = 0x10 }
 
enum  { MG_TIMEOUT_INFINITE = -1 }
 
enum  {
  MG_ERROR_DATA_CODE_OK = 0u , MG_ERROR_DATA_CODE_INVALID_PARAM = 1u , MG_ERROR_DATA_CODE_INVALID_OPTION = 2u , MG_ERROR_DATA_CODE_INIT_TLS_FAILED = 3u ,
  MG_ERROR_DATA_CODE_MISSING_OPTION = 4u , MG_ERROR_DATA_CODE_DUPLICATE_DOMAIN = 5u , MG_ERROR_DATA_CODE_OUT_OF_MEMORY = 6u , MG_ERROR_DATA_CODE_SERVER_STOPPED = 7u ,
  MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED = 8u , MG_ERROR_DATA_CODE_OS_ERROR = 9u , MG_ERROR_DATA_CODE_INIT_PORTS_FAILED = 10u , MG_ERROR_DATA_CODE_INIT_USER_FAILED = 11u ,
  MG_ERROR_DATA_CODE_INIT_ACL_FAILED = 12u , MG_ERROR_DATA_CODE_INVALID_PASS_FILE = 13u , MG_ERROR_DATA_CODE_SCRIPT_ERROR = 14u , MG_ERROR_DATA_CODE_HOST_NOT_FOUND = 15u ,
  MG_ERROR_DATA_CODE_CONNECT_TIMEOUT = 16u , MG_ERROR_DATA_CODE_CONNECT_FAILED = 17u , MG_ERROR_DATA_CODE_TLS_CLIENT_CERT_ERROR = 18u , MG_ERROR_DATA_CODE_TLS_SERVER_CERT_ERROR = 19u ,
  MG_ERROR_DATA_CODE_TLS_CONNECT_ERROR = 20u
}
 

Functions

CIVETWEB_API unsigned mg_init_library (unsigned features)
 
CIVETWEB_API unsigned mg_exit_library (void)
 
CIVETWEB_API struct mg_contextmg_start (const struct mg_callbacks *callbacks, void *user_data, const char **configuration_options)
 
CIVETWEB_API void mg_stop (struct mg_context *)
 
CIVETWEB_API int mg_start_domain (struct mg_context *ctx, const char **configuration_options)
 
CIVETWEB_API void mg_set_request_handler (struct mg_context *ctx, const char *uri, mg_request_handler handler, void *cbdata)
 
CIVETWEB_API void mg_set_websocket_handler (struct mg_context *ctx, const char *uri, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
 
CIVETWEB_API void mg_set_websocket_handler_with_subprotocols (struct mg_context *ctx, const char *uri, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
 
CIVETWEB_API void mg_set_auth_handler (struct mg_context *ctx, const char *uri, mg_authorization_handler handler, void *cbdata)
 
CIVETWEB_API const char * mg_get_option (const struct mg_context *ctx, const char *name)
 
CIVETWEB_API struct mg_contextmg_get_context (const struct mg_connection *conn)
 
CIVETWEB_API void * mg_get_user_data (const struct mg_context *ctx)
 
CIVETWEB_API void * mg_get_user_context_data (const struct mg_connection *conn)
 
CIVETWEB_API void * mg_get_thread_pointer (const struct mg_connection *conn)
 
CIVETWEB_API void mg_set_user_connection_data (const struct mg_connection *conn, void *data)
 
CIVETWEB_API void * mg_get_user_connection_data (const struct mg_connection *conn)
 
CIVETWEB_API int mg_get_request_link (const struct mg_connection *conn, char *buf, size_t buflen)
 
CIVETWEB_API const struct mg_optionmg_get_valid_options (void)
 
CIVETWEB_API int mg_get_server_ports (const struct mg_context *ctx, int size, struct mg_server_port *ports)
 
CIVETWEB_API int mg_modify_passwords_file (const char *passwords_file_name, const char *realm, const char *user, const char *password)
 
CIVETWEB_API int mg_modify_passwords_file_ha1 (const char *passwords_file_name, const char *realm, const char *user, const char *ha1)
 
CIVETWEB_API const struct mg_request_infomg_get_request_info (const struct mg_connection *)
 
CIVETWEB_API const struct mg_response_infomg_get_response_info (const struct mg_connection *)
 
CIVETWEB_API int mg_write (struct mg_connection *, const void *buf, size_t len)
 
CIVETWEB_API int mg_websocket_write (struct mg_connection *conn, int opcode, const char *data, size_t data_len)
 
CIVETWEB_API int mg_websocket_client_write (struct mg_connection *conn, int opcode, const char *data, size_t data_len)
 
CIVETWEB_API void mg_lock_connection (struct mg_connection *conn)
 
CIVETWEB_API void mg_unlock_connection (struct mg_connection *conn)
 
CIVETWEB_API void mg_lock_context (struct mg_context *ctx)
 
CIVETWEB_API void mg_unlock_context (struct mg_context *ctx)
 
CIVETWEB_API int mg_printf (struct mg_connection *, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
 
CIVETWEB_API int CIVETWEB_API int mg_send_chunk (struct mg_connection *conn, const char *chunk, unsigned int chunk_len)
 
CIVETWEB_API void mg_send_file (struct mg_connection *conn, const char *path)
 
CIVETWEB_API int mg_send_file_body (struct mg_connection *conn, const char *path)
 
CIVETWEB_API int mg_send_http_error (struct mg_connection *conn, int status_code, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(3
 
CIVETWEB_API int CIVETWEB_API int mg_send_http_ok (struct mg_connection *conn, const char *mime_type, long long content_length)
 
CIVETWEB_API int mg_send_http_redirect (struct mg_connection *conn, const char *target_url, int redirect_code)
 
CIVETWEB_API int mg_send_digest_access_authentication_request (struct mg_connection *conn, const char *realm)
 
CIVETWEB_API int mg_check_digest_access_authentication (struct mg_connection *conn, const char *realm, const char *filename)
 
CIVETWEB_API void mg_send_mime_file (struct mg_connection *conn, const char *path, const char *mime_type)
 
CIVETWEB_API void mg_send_mime_file2 (struct mg_connection *conn, const char *path, const char *mime_type, const char *additional_headers)
 
CIVETWEB_API long long mg_store_body (struct mg_connection *conn, const char *path)
 
CIVETWEB_API int mg_read (struct mg_connection *, void *buf, size_t len)
 
CIVETWEB_API const char * mg_get_header (const struct mg_connection *, const char *name)
 
CIVETWEB_API int mg_get_var (const char *data, size_t data_len, const char *var_name, char *dst, size_t dst_len)
 
CIVETWEB_API int mg_get_var2 (const char *data, size_t data_len, const char *var_name, char *dst, size_t dst_len, size_t occurrence)
 
CIVETWEB_API int mg_split_form_urlencoded (char *data, struct mg_header *form_fields, unsigned num_form_fields)
 
CIVETWEB_API int mg_get_cookie (const char *cookie, const char *var_name, char *buf, size_t buf_len)
 
CIVETWEB_API struct mg_connectionmg_download (const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, PRINTF_FORMAT_STRING(const char *request_fmt),...) PRINTF_ARGS(6
 
CIVETWEB_API struct mg_connection CIVETWEB_API void mg_close_connection (struct mg_connection *conn)
 
CIVETWEB_API int mg_handle_form_request (struct mg_connection *conn, struct mg_form_data_handler *fdh)
 
CIVETWEB_API int mg_start_thread (mg_thread_func_t f, void *p)
 
CIVETWEB_API const char * mg_get_builtin_mime_type (const char *file_name)
 
CIVETWEB_API const char * mg_get_response_code_text (const struct mg_connection *conn, int response_code)
 
CIVETWEB_API const char * mg_version (void)
 
CIVETWEB_API int mg_url_decode (const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
 
CIVETWEB_API int mg_url_encode (const char *src, char *dst, size_t dst_len)
 
CIVETWEB_API int mg_base64_encode (const unsigned char *src, size_t src_len, char *dst, size_t *dst_len)
 
CIVETWEB_API int mg_base64_decode (const char *src, size_t src_len, unsigned char *dst, size_t *dst_len)
 
CIVETWEB_API char * mg_md5 (char buf[33],...)
 
CIVETWEB_API void mg_cry (const struct mg_connection *conn, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(2
 
CIVETWEB_API void CIVETWEB_API int mg_strcasecmp (const char *s1, const char *s2)
 
CIVETWEB_API int mg_strncasecmp (const char *s1, const char *s2, size_t len)
 
CIVETWEB_API struct mg_connectionmg_connect_websocket_client (const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data)
 
CIVETWEB_API struct mg_connectionmg_connect_websocket_client_extensions (const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data)
 
CIVETWEB_API struct mg_connectionmg_connect_client (const char *host, int port, int use_ssl, char *error_buffer, size_t error_buffer_size)
 
CIVETWEB_API struct mg_connectionmg_connect_client_secure (const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size)
 
CIVETWEB_API struct mg_connectionmg_connect_websocket_client_secure (const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data)
 
CIVETWEB_API struct mg_connectionmg_connect_websocket_client_secure_extensions (const struct mg_client_options *client_options, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data)
 
CIVETWEB_API int mg_get_response (struct mg_connection *conn, char *ebuf, size_t ebuf_len, int timeout)
 
CIVETWEB_API int mg_response_header_start (struct mg_connection *conn, int status)
 
CIVETWEB_API int mg_response_header_add (struct mg_connection *conn, const char *header, const char *value, int value_len)
 
CIVETWEB_API int mg_response_header_add_lines (struct mg_connection *conn, const char *http1_headers)
 
CIVETWEB_API int mg_response_header_send (struct mg_connection *conn)
 
CIVETWEB_API unsigned mg_check_feature (unsigned feature)
 
CIVETWEB_API int mg_get_system_info (char *buffer, int buflen)
 
CIVETWEB_API int mg_get_context_info (const struct mg_context *ctx, char *buffer, int buflen)
 
CIVETWEB_API void mg_disable_connection_keep_alive (struct mg_connection *conn)
 
CIVETWEB_API struct mg_contextmg_start2 (struct mg_init_data *init, struct mg_error_data *error)
 
CIVETWEB_API int mg_start_domain2 (struct mg_context *ctx, const char **configuration_options, struct mg_error_data *error)
 

Macro Definition Documentation

◆ CIVETWEB_API

#define CIVETWEB_API

Definition at line 43 of file civetweb.h.

Referenced by connect_socket().

◆ CIVETWEB_VERSION

#define CIVETWEB_VERSION   "1.16"

Definition at line 26 of file civetweb.h.

Referenced by mg_version().

◆ CIVETWEB_VERSION_MAJOR

#define CIVETWEB_VERSION_MAJOR   (1)

Definition at line 27 of file civetweb.h.

◆ CIVETWEB_VERSION_MINOR

#define CIVETWEB_VERSION_MINOR   (16)

Definition at line 28 of file civetweb.h.

◆ CIVETWEB_VERSION_PATCH

#define CIVETWEB_VERSION_PATCH   (0)

Definition at line 29 of file civetweb.h.

◆ MG_MATCH_CONTEXT_MAX_MATCHES

#define MG_MATCH_CONTEXT_MAX_MATCHES   (32)

Definition at line 1370 of file civetweb.h.

◆ MG_MAX_HEADERS

#define MG_MAX_HEADERS   (64)

Definition at line 141 of file civetweb.h.

Referenced by parse_http_headers().

◆ mg_server_ports

#define mg_server_ports   mg_server_port

Definition at line 724 of file civetweb.h.

◆ PRINTF_ARGS

#define PRINTF_ARGS ( x,
y )

Definition at line 883 of file civetweb.h.

◆ PRINTF_FORMAT_STRING

#define PRINTF_FORMAT_STRING ( s)    s

Definition at line 877 of file civetweb.h.

Typedef Documentation

◆ mg_authorization_handler

typedef int(* mg_authorization_handler) (struct mg_connection *conn, void *cbdata)

Definition at line 606 of file civetweb.h.

◆ mg_request_handler

typedef int(* mg_request_handler) (struct mg_connection *conn, void *cbdata)

Definition at line 492 of file civetweb.h.

◆ mg_thread_func_t

typedef void *(* mg_thread_func_t) (void *)

Definition at line 1307 of file civetweb.h.

◆ mg_websocket_close_handler

typedef void(* mg_websocket_close_handler) (const struct mg_connection *, void *)

Definition at line 555 of file civetweb.h.

◆ mg_websocket_connect_handler

typedef int(* mg_websocket_connect_handler) (const struct mg_connection *, void *)

Definition at line 547 of file civetweb.h.

◆ mg_websocket_data_handler

typedef int(* mg_websocket_data_handler) (struct mg_connection *, int, char *, size_t, void *)

Definition at line 550 of file civetweb.h.

◆ mg_websocket_ready_handler

typedef void(* mg_websocket_ready_handler) (struct mg_connection *, void *)

Definition at line 549 of file civetweb.h.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
MG_FORM_FIELD_STORAGE_SKIP 
MG_FORM_FIELD_STORAGE_GET 
MG_FORM_FIELD_STORAGE_STORE 
MG_FORM_FIELD_STORAGE_ABORT 

Definition at line 1270 of file civetweb.h.

1270 {
1271 /* Skip this field (neither get nor store it). Continue with the
1272 * next field. */
1274 /* Get the field value. */
1276 /* Store the field value into a file. */
1278 /* Stop parsing this request. Skip the remaining fields. */
1280};
@ MG_FORM_FIELD_STORAGE_GET
Definition civetweb.h:1275
@ MG_FORM_FIELD_STORAGE_ABORT
Definition civetweb.h:1279
@ MG_FORM_FIELD_STORAGE_STORE
Definition civetweb.h:1277
@ MG_FORM_FIELD_STORAGE_SKIP
Definition civetweb.h:1273

◆ anonymous enum

anonymous enum
Enumerator
MG_FORM_FIELD_HANDLE_GET 
MG_FORM_FIELD_HANDLE_NEXT 
MG_FORM_FIELD_HANDLE_ABORT 

Definition at line 1283 of file civetweb.h.

1283 {
1284 /* Only "field_get": If there is more data in this field, get the next
1285 * chunk. Otherwise: handle the next field. */
1287 /* Handle the next field */
1289 /* Stop parsing this request */
1291};
@ MG_FORM_FIELD_HANDLE_NEXT
Definition civetweb.h:1288
@ MG_FORM_FIELD_HANDLE_GET
Definition civetweb.h:1286
@ MG_FORM_FIELD_HANDLE_ABORT
Definition civetweb.h:1290

◆ anonymous enum

anonymous enum
Enumerator
MG_TIMEOUT_INFINITE 

Definition at line 1524 of file civetweb.h.

1524{ MG_TIMEOUT_INFINITE = -1 };
@ MG_TIMEOUT_INFINITE
Definition civetweb.h:1524

◆ anonymous enum

anonymous enum
Enumerator
MG_ERROR_DATA_CODE_OK 
MG_ERROR_DATA_CODE_INVALID_PARAM 
MG_ERROR_DATA_CODE_INVALID_OPTION 
MG_ERROR_DATA_CODE_INIT_TLS_FAILED 
MG_ERROR_DATA_CODE_MISSING_OPTION 
MG_ERROR_DATA_CODE_DUPLICATE_DOMAIN 
MG_ERROR_DATA_CODE_OUT_OF_MEMORY 
MG_ERROR_DATA_CODE_SERVER_STOPPED 
MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED 
MG_ERROR_DATA_CODE_OS_ERROR 
MG_ERROR_DATA_CODE_INIT_PORTS_FAILED 
MG_ERROR_DATA_CODE_INIT_USER_FAILED 
MG_ERROR_DATA_CODE_INIT_ACL_FAILED 
MG_ERROR_DATA_CODE_INVALID_PASS_FILE 
MG_ERROR_DATA_CODE_SCRIPT_ERROR 
MG_ERROR_DATA_CODE_HOST_NOT_FOUND 
MG_ERROR_DATA_CODE_CONNECT_TIMEOUT 
MG_ERROR_DATA_CODE_CONNECT_FAILED 
MG_ERROR_DATA_CODE_TLS_CLIENT_CERT_ERROR 
MG_ERROR_DATA_CODE_TLS_SERVER_CERT_ERROR 
MG_ERROR_DATA_CODE_TLS_CONNECT_ERROR 

Definition at line 1732 of file civetweb.h.

1732 {
1733 /* No error */
1735
1736 /* Caller provided invalid parameter */
1738
1739 /* "configuration_option" contains invalid element */
1741
1742 /* Initializen TLS / SSL library failed */
1744
1745 /* Mandatory "configuration_option" missing */
1747
1748 /* Duplicate "authentication_domain" option */
1750
1751 /* Not enough memory */
1753
1754 /* Server already stopped */
1756
1757 /* mg_init_library must be called first */
1759
1760 /* Operating system function failed */
1762
1763 /* Failed to bind to server ports */
1765
1766 /* Failed to switch user (option "run_as_user") */
1768
1769 /* Access Control List error */
1771
1772 /* Global password file error */
1774
1775 /* Lua background script init error */
1777
1778 /* Client: Host not found, invalid IP to connect */
1780
1781 /* Client: TCP connect timeout */
1783
1784 /* Client: TCP connect failed */
1786
1787 /* Error using TLS client certificate */
1789
1790 /* Error setting trusted TLS server certificate for client connection */
1792
1793 /* Error establishing TLS connection to HTTPS server */
1795};
@ MG_ERROR_DATA_CODE_TLS_CONNECT_ERROR
Definition civetweb.h:1794
@ MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED
Definition civetweb.h:1758
@ MG_ERROR_DATA_CODE_OS_ERROR
Definition civetweb.h:1761
@ MG_ERROR_DATA_CODE_MISSING_OPTION
Definition civetweb.h:1746
@ MG_ERROR_DATA_CODE_CONNECT_FAILED
Definition civetweb.h:1785
@ MG_ERROR_DATA_CODE_OK
Definition civetweb.h:1734
@ MG_ERROR_DATA_CODE_DUPLICATE_DOMAIN
Definition civetweb.h:1749
@ MG_ERROR_DATA_CODE_INVALID_OPTION
Definition civetweb.h:1740
@ MG_ERROR_DATA_CODE_TLS_SERVER_CERT_ERROR
Definition civetweb.h:1791
@ MG_ERROR_DATA_CODE_INIT_ACL_FAILED
Definition civetweb.h:1770
@ MG_ERROR_DATA_CODE_SCRIPT_ERROR
Definition civetweb.h:1776
@ MG_ERROR_DATA_CODE_CONNECT_TIMEOUT
Definition civetweb.h:1782
@ MG_ERROR_DATA_CODE_INIT_PORTS_FAILED
Definition civetweb.h:1764
@ MG_ERROR_DATA_CODE_INVALID_PARAM
Definition civetweb.h:1737
@ MG_ERROR_DATA_CODE_OUT_OF_MEMORY
Definition civetweb.h:1752
@ MG_ERROR_DATA_CODE_HOST_NOT_FOUND
Definition civetweb.h:1779
@ MG_ERROR_DATA_CODE_INIT_TLS_FAILED
Definition civetweb.h:1743
@ MG_ERROR_DATA_CODE_INIT_USER_FAILED
Definition civetweb.h:1767
@ MG_ERROR_DATA_CODE_SERVER_STOPPED
Definition civetweb.h:1755
@ MG_ERROR_DATA_CODE_INVALID_PASS_FILE
Definition civetweb.h:1773
@ MG_ERROR_DATA_CODE_TLS_CLIENT_CERT_ERROR
Definition civetweb.h:1788

◆ anonymous enum

anonymous enum
Enumerator
MG_FEATURES_DEFAULT 
MG_FEATURES_FILES 
MG_FEATURES_TLS 
MG_FEATURES_SSL 
MG_FEATURES_CGI 
MG_FEATURES_IPV6 
MG_FEATURES_WEBSOCKET 
MG_FEATURES_LUA 
MG_FEATURES_SSJS 
MG_FEATURES_CACHE 
MG_FEATURES_STATS 
MG_FEATURES_COMPRESSION 
MG_FEATURES_HTTP2 
MG_FEATURES_X_DOMAIN_SOCKET 
MG_FEATURES_ALL 

Definition at line 56 of file civetweb.h.

56 {
58
59 /* Support files from local directories */
60 /* Will only work, if NO_FILES is not set. */
61 MG_FEATURES_FILES = 0x1u,
62
63 /* Support transport layer security (TLS). */
64 /* SSL is still often used synonymously for TLS. */
65 /* Will only work, if NO_SSL is not set. */
66 MG_FEATURES_TLS = 0x2u,
67 MG_FEATURES_SSL = 0x2u,
68
69 /* Support common gateway interface (CGI). */
70 /* Will only work, if NO_CGI is not set. */
71 MG_FEATURES_CGI = 0x4u,
72
73 /* Support IPv6. */
74 /* Will only work, if USE_IPV6 is set. */
75 MG_FEATURES_IPV6 = 0x8u,
76
77 /* Support WebSocket protocol. */
78 /* Will only work, if USE_WEBSOCKET is set. */
80
81 /* Support server side Lua scripting. */
82 /* Will only work, if USE_LUA is set. */
83 MG_FEATURES_LUA = 0x20u,
84
85 /* Support server side JavaScript scripting. */
86 /* Will only work, if USE_DUKTAPE is set. */
87 MG_FEATURES_SSJS = 0x40u,
88
89 /* Provide data required for caching files. */
90 /* Will only work, if NO_CACHING is not set. */
91 MG_FEATURES_CACHE = 0x80u,
92
93 /* Collect server status information. */
94 /* Will only work, if USE_SERVER_STATS is set. */
95 MG_FEATURES_STATS = 0x100u,
96
97 /* Support on-the-fly compression. */
98 /* Will only work, if USE_ZLIB is set. */
100
101 /* HTTP/2 support enabled. */
102 MG_FEATURES_HTTP2 = 0x400u,
103
104 /* Support unix domain sockets. */
106
107 /* Bit mask for all feature defines. */
108 MG_FEATURES_ALL = 0xFFFFu
109};
@ MG_FEATURES_HTTP2
Definition civetweb.h:102
@ MG_FEATURES_ALL
Definition civetweb.h:108
@ MG_FEATURES_STATS
Definition civetweb.h:95
@ MG_FEATURES_CACHE
Definition civetweb.h:91
@ MG_FEATURES_FILES
Definition civetweb.h:61
@ MG_FEATURES_CGI
Definition civetweb.h:71
@ MG_FEATURES_IPV6
Definition civetweb.h:75
@ MG_FEATURES_DEFAULT
Definition civetweb.h:57
@ MG_FEATURES_TLS
Definition civetweb.h:66
@ MG_FEATURES_X_DOMAIN_SOCKET
Definition civetweb.h:105
@ MG_FEATURES_SSL
Definition civetweb.h:67
@ MG_FEATURES_LUA
Definition civetweb.h:83
@ MG_FEATURES_WEBSOCKET
Definition civetweb.h:79
@ MG_FEATURES_SSJS
Definition civetweb.h:87
@ MG_FEATURES_COMPRESSION
Definition civetweb.h:99

◆ anonymous enum

anonymous enum
Enumerator
MG_CONFIG_TYPE_UNKNOWN 
MG_CONFIG_TYPE_NUMBER 
MG_CONFIG_TYPE_STRING 
MG_CONFIG_TYPE_FILE 
MG_CONFIG_TYPE_DIRECTORY 
MG_CONFIG_TYPE_BOOLEAN 
MG_CONFIG_TYPE_EXT_PATTERN 
MG_CONFIG_TYPE_STRING_LIST 
MG_CONFIG_TYPE_STRING_MULTILINE 
MG_CONFIG_TYPE_YES_NO_OPTIONAL 

Definition at line 693 of file civetweb.h.

693 {
704};
@ MG_CONFIG_TYPE_UNKNOWN
Definition civetweb.h:694
@ MG_CONFIG_TYPE_FILE
Definition civetweb.h:697
@ MG_CONFIG_TYPE_STRING
Definition civetweb.h:696
@ MG_CONFIG_TYPE_DIRECTORY
Definition civetweb.h:698
@ MG_CONFIG_TYPE_EXT_PATTERN
Definition civetweb.h:700
@ MG_CONFIG_TYPE_STRING_MULTILINE
Definition civetweb.h:702
@ MG_CONFIG_TYPE_STRING_LIST
Definition civetweb.h:701
@ MG_CONFIG_TYPE_YES_NO_OPTIONAL
Definition civetweb.h:703
@ MG_CONFIG_TYPE_NUMBER
Definition civetweb.h:695
@ MG_CONFIG_TYPE_BOOLEAN
Definition civetweb.h:699

◆ anonymous enum

anonymous enum
Enumerator
MG_WEBSOCKET_OPCODE_CONTINUATION 
MG_WEBSOCKET_OPCODE_TEXT 
MG_WEBSOCKET_OPCODE_BINARY 
MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE 
MG_WEBSOCKET_OPCODE_PING 
MG_WEBSOCKET_OPCODE_PONG 

Definition at line 857 of file civetweb.h.

857 {
864};
@ MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE
Definition civetweb.h:861
@ MG_WEBSOCKET_OPCODE_BINARY
Definition civetweb.h:860
@ MG_WEBSOCKET_OPCODE_PONG
Definition civetweb.h:863
@ MG_WEBSOCKET_OPCODE_TEXT
Definition civetweb.h:859
@ MG_WEBSOCKET_OPCODE_CONTINUATION
Definition civetweb.h:858
@ MG_WEBSOCKET_OPCODE_PING
Definition civetweb.h:862

Function Documentation

◆ mg_base64_decode()

CIVETWEB_API int mg_base64_decode ( const char * src,
size_t src_len,
unsigned char * dst,
size_t * dst_len )

Definition at line 7383 of file civetweb.c.

7387{
7388 size_t i;
7389 unsigned char a, b, c, d;
7390 size_t dst_len_limit = (size_t)-1;
7391 size_t dst_len_used = 0;
7392
7393 if (dst_len != NULL) {
7394 dst_len_limit = *dst_len;
7395 *dst_len = 0;
7396 }
7397
7398 for (i = 0; i < src_len; i += 4) {
7399 /* Read 4 characters from BASE64 string */
7400 a = b64reverse(src[i]);
7401 if (a >= 254) {
7402 return (int)i;
7403 }
7404
7405 b = b64reverse(((i + 1) >= src_len) ? 0 : src[i + 1]);
7406 if (b >= 254) {
7407 return (int)i + 1;
7408 }
7409
7410 c = b64reverse(((i + 2) >= src_len) ? 0 : src[i + 2]);
7411 if (c == 254) {
7412 return (int)i + 2;
7413 }
7414
7415 d = b64reverse(((i + 3) >= src_len) ? 0 : src[i + 3]);
7416 if (d == 254) {
7417 return (int)i + 3;
7418 }
7419
7420 /* Add first (of 3) decoded character */
7421 if (dst_len_used < dst_len_limit) {
7422 dst[dst_len_used] = (unsigned char)((unsigned char)(a << 2)
7423 + (unsigned char)(b >> 4));
7424 }
7425 dst_len_used++;
7426
7427 if (c != 255) {
7428 if (dst_len_used < dst_len_limit) {
7429
7430 dst[dst_len_used] = (unsigned char)((unsigned char)(b << 4)
7431 + (unsigned char)(c >> 2));
7432 }
7433 dst_len_used++;
7434 if (d != 255) {
7435 if (dst_len_used < dst_len_limit) {
7436 dst[dst_len_used] =
7437 (unsigned char)((unsigned char)(c << 6) + d);
7438 }
7439 dst_len_used++;
7440 }
7441 }
7442 }
7443
7444 /* Add terminating zero */
7445 if (dst_len_used < dst_len_limit) {
7446 dst[dst_len_used] = '\0';
7447 }
7448 dst_len_used++;
7449 if (dst_len != NULL) {
7450 *dst_len = dst_len_used;
7451 }
7452
7453 if (dst_len_used > dst_len_limit) {
7454 /* Out of memory */
7455 return 0;
7456 }
7457
7458 /* Return -1 for "OK" */
7459 return -1;
7460}
static unsigned char b64reverse(char letter)
Definition civetweb.c:7358
#define NULL
Definition gmacros.h:924

References b64reverse(), and NULL.

Referenced by parse_auth_header().

◆ mg_base64_encode()

CIVETWEB_API int mg_base64_encode ( const unsigned char * src,
size_t src_len,
char * dst,
size_t * dst_len )

Definition at line 7305 of file civetweb.c.

7309{
7310 static const char *b64 =
7311 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7312 size_t i, j;
7313 int a, b, c;
7314
7315 if (dst_len != NULL) {
7316 /* Expected length including 0 termination: */
7317 /* IN 1 -> OUT 5, IN 2 -> OUT 5, IN 3 -> OUT 5, IN 4 -> OUT 9,
7318 * IN 5 -> OUT 9, IN 6 -> OUT 9, IN 7 -> OUT 13, etc. */
7319 size_t expected_len = ((src_len + 2) / 3) * 4 + 1;
7320 if (*dst_len < expected_len) {
7321 if (*dst_len > 0) {
7322 dst[0] = '\0';
7323 }
7324 *dst_len = expected_len;
7325 return 0;
7326 }
7327 }
7328
7329 for (i = j = 0; i < src_len; i += 3) {
7330 a = src[i];
7331 b = ((i + 1) >= src_len) ? 0 : src[i + 1];
7332 c = ((i + 2) >= src_len) ? 0 : src[i + 2];
7333
7334 dst[j++] = b64[a >> 2];
7335 dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
7336 if (i + 1 < src_len) {
7337 dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
7338 }
7339 if (i + 2 < src_len) {
7340 dst[j++] = b64[c & 63];
7341 }
7342 }
7343 while (j % 4 != 0) {
7344 dst[j++] = '=';
7345 }
7346 dst[j++] = '\0';
7347
7348 if (dst_len != NULL) {
7349 *dst_len = (size_t)j;
7350 }
7351
7352 /* Return -1 for "OK" */
7353 return -1;
7354}

References NULL.

◆ mg_check_digest_access_authentication()

CIVETWEB_API int mg_check_digest_access_authentication ( struct mg_connection * conn,
const char * realm,
const char * filename )

Definition at line 8893 of file civetweb.c.

8896{
8897 struct mg_file file = STRUCT_FILE_INITIALIZER;
8898 int auth;
8899
8900 if (!conn || !filename) {
8901 return -1;
8902 }
8903 if (!mg_fopen(conn, filename, MG_FOPEN_MODE_READ, &file)) {
8904 return -2;
8905 }
8906
8907 auth = authorize(conn, &file, realm);
8908
8909 mg_fclose(&file.access);
8910
8911 return auth;
8912}
static int mg_fopen(const struct mg_connection *conn, const char *path, int mode, struct mg_file *filep)
Definition civetweb.c:2915
#define MG_FOPEN_MODE_READ
Definition civetweb.c:2843
static int authorize(struct mg_connection *conn, struct mg_file *filep, const char *realm)
Definition civetweb.c:8861
static int mg_fclose(struct mg_file_access *fileacc)
Definition civetweb.c:2986
#define STRUCT_FILE_INITIALIZER
Definition civetweb.c:1891
struct mg_file_access access
Definition civetweb.c:1887

References mg_file::access, authorize(), mg_fclose(), mg_fopen(), MG_FOPEN_MODE_READ, and STRUCT_FILE_INITIALIZER.

◆ mg_check_feature()

CIVETWEB_API unsigned mg_check_feature ( unsigned feature)

Definition at line 21430 of file civetweb.c.

21431{
21432 static const unsigned feature_set = 0
21433 /* Set bits for available features according to API documentation.
21434 * This bit mask is created at compile time, according to the active
21435 * preprocessor defines. It is a single const value at runtime. */
21436#if !defined(NO_FILES)
21438#endif
21439#if !defined(NO_SSL) || defined(USE_MBEDTLS)
21441#endif
21442#if !defined(NO_CGI)
21444#endif
21445#if defined(USE_IPV6)
21447#endif
21448#if defined(USE_WEBSOCKET)
21450#endif
21451#if defined(USE_LUA)
21453#endif
21454#if defined(USE_DUKTAPE)
21456#endif
21457#if !defined(NO_CACHING)
21459#endif
21460#if defined(USE_SERVER_STATS)
21462#endif
21463#if defined(USE_ZLIB)
21465#endif
21466#if defined(USE_HTTP2)
21468#endif
21469#if defined(USE_X_DOM_SOCKET)
21471#endif
21472
21473 /* Set some extra bits not defined in the API documentation.
21474 * These bits may change without further notice. */
21475#if defined(MG_LEGACY_INTERFACE)
21476 | 0x80000000u
21477#endif
21478#if defined(MG_EXPERIMENTAL_INTERFACES)
21479 | 0x40000000u
21480#endif
21481#if !defined(NO_RESPONSE_BUFFERING)
21482 | 0x20000000u
21483#endif
21484#if defined(MEMORY_DEBUGGING)
21485 | 0x10000000u
21486#endif
21487 ;
21488 return (feature & feature_set);
21489}

References MG_FEATURES_CACHE, MG_FEATURES_CGI, MG_FEATURES_COMPRESSION, MG_FEATURES_FILES, MG_FEATURES_HTTP2, MG_FEATURES_IPV6, MG_FEATURES_LUA, MG_FEATURES_SSJS, MG_FEATURES_SSL, MG_FEATURES_STATS, MG_FEATURES_WEBSOCKET, and MG_FEATURES_X_DOMAIN_SOCKET.

Referenced by mg_get_system_info(), and mg_init_library().

◆ mg_close_connection()

CIVETWEB_API struct mg_connection CIVETWEB_API void mg_close_connection ( struct mg_connection * conn)

Definition at line 17938 of file civetweb.c.

17939{
17940 if ((conn == NULL) || (conn->phys_ctx == NULL)) {
17941 return;
17942 }
17943
17944#if defined(USE_WEBSOCKET)
17945 if (conn->phys_ctx->context_type == CONTEXT_SERVER) {
17946 if (conn->in_websocket_handling) {
17947 /* Set close flag, so the server thread can exit. */
17948 conn->must_close = 1;
17949 return;
17950 }
17951 }
17952 if (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT) {
17953
17954 unsigned int i;
17955
17956 /* client context: loops must end */
17958 conn->must_close = 1;
17959
17960 /* We need to get the client thread out of the select/recv call
17961 * here. */
17962 /* Since we use a sleep quantum of some seconds to check for recv
17963 * timeouts, we will just wait a few seconds in mg_join_thread. */
17964
17965 /* join worker thread */
17966 for (i = 0; i < conn->phys_ctx->cfg_worker_threads; i++) {
17968 }
17969 }
17970#endif /* defined(USE_WEBSOCKET) */
17971
17972 close_connection(conn);
17973
17974#if !defined(NO_SSL) && !defined(USE_MBEDTLS) // TODO: mbedTLS client
17977 && (conn->phys_ctx->dd.ssl_ctx != NULL)) {
17978 SSL_CTX_free(conn->phys_ctx->dd.ssl_ctx);
17979 }
17980#endif
17981
17982#if defined(USE_WEBSOCKET)
17983 if (conn->phys_ctx->context_type == CONTEXT_WS_CLIENT) {
17985 (void)pthread_mutex_destroy(&conn->mutex);
17986 mg_free(conn);
17987 } else if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) {
17988 (void)pthread_mutex_destroy(&conn->mutex);
17989 mg_free(conn);
17990 }
17991#else
17992 if (conn->phys_ctx->context_type == CONTEXT_HTTP_CLIENT) { /* Client */
17993 (void)pthread_mutex_destroy(&conn->mutex);
17994 mg_free(conn);
17995 }
17996#endif /* defined(USE_WEBSOCKET) */
17997}
#define STOP_FLAG_ASSIGN(f, v)
Definition civetweb.c:2324
@ CONTEXT_WS_CLIENT
Definition civetweb.c:2265
@ CONTEXT_SERVER
Definition civetweb.c:2263
@ CONTEXT_HTTP_CLIENT
Definition civetweb.c:2264
static __inline void mg_free(void *a)
Definition civetweb.c:1492
static int mg_join_thread(pthread_t threadid)
Definition civetweb.c:5757
static void close_connection(struct mg_connection *conn)
Definition civetweb.c:17864
pthread_mutex_t mutex
Definition civetweb.c:2565
struct mg_context * phys_ctx
Definition civetweb.c:2497
pthread_t * worker_threadids
Definition civetweb.c:2379
stop_flag_t stop_flag
Definition civetweb.c:2373
int context_type
Definition civetweb.c:2354
struct mg_domain_context dd
Definition civetweb.c:2442
unsigned int cfg_worker_threads
Definition civetweb.c:2378
SSL_CTX * ssl_ctx
Definition civetweb.c:2270

References mg_context::cfg_worker_threads, close_connection(), CONTEXT_HTTP_CLIENT, CONTEXT_SERVER, mg_context::context_type, CONTEXT_WS_CLIENT, mg_context::dd, mg_free(), mg_join_thread(), mg_connection::must_close, mg_connection::mutex, NULL, mg_connection::phys_ctx, mg_domain_context::ssl_ctx, mg_context::stop_flag, STOP_FLAG_ASSIGN, and mg_context::worker_threadids.

Referenced by mg_connect_websocket_client_impl(), mg_download(), and run_client().

◆ mg_connect_client()

CIVETWEB_API struct mg_connection * mg_connect_client ( const char * host,
int port,
int use_ssl,
char * error_buffer,
size_t error_buffer_size )

Definition at line 18253 of file civetweb.c.

18258{
18259 struct mg_client_options opts;
18260 struct mg_init_data init;
18261 struct mg_error_data error;
18262
18263 memset(&init, 0, sizeof(init));
18264
18265 memset(&error, 0, sizeof(error));
18266 error.text_buffer_size = error_buffer_size;
18267 error.text = error_buffer;
18268
18269 memset(&opts, 0, sizeof(opts));
18270 opts.host = host;
18271 opts.port = port;
18272 if (use_ssl) {
18273 opts.host_name = host;
18274 }
18275
18276 return mg_connect_client_impl(&opts, use_ssl, &init, &error);
18277}
static struct mg_connection * mg_connect_client_impl(const struct mg_client_options *client_options, int use_ssl, struct mg_init_data *init, struct mg_error_data *error)
Definition civetweb.c:18001
static void error(LoadState *S, const char *why)

References error(), mg_client_options::host, mg_client_options::host_name, mg_connect_client_impl(), and mg_client_options::port.

Referenced by mg_download(), and run_client().

◆ mg_connect_client_secure()

CIVETWEB_API struct mg_connection * mg_connect_client_secure ( const struct mg_client_options * client_options,
char * error_buffer,
size_t error_buffer_size )

Definition at line 18237 of file civetweb.c.

18240{
18241 struct mg_init_data init;
18242 struct mg_error_data error;
18243
18244 memset(&init, 0, sizeof(init));
18245 memset(&error, 0, sizeof(error));
18246 error.text_buffer_size = error_buffer_size;
18247 error.text = error_buffer;
18248 return mg_connect_client_impl(client_options, 1, &init, &error);
18249}

References error(), and mg_connect_client_impl().

◆ mg_connect_websocket_client()

CIVETWEB_API struct mg_connection * mg_connect_websocket_client ( const char * host,
int port,
int use_ssl,
char * error_buffer,
size_t error_buffer_size,
const char * path,
const char * origin,
mg_websocket_data_handler data_func,
mg_websocket_close_handler close_func,
void * user_data )

Definition at line 19212 of file civetweb.c.

19222{
19223 struct mg_client_options client_options;
19224 memset(&client_options, 0, sizeof(client_options));
19225 client_options.host = host;
19226 client_options.port = port;
19227
19228 return mg_connect_websocket_client_impl(&client_options,
19229 use_ssl,
19230 error_buffer,
19231 error_buffer_size,
19232 path,
19233 origin,
19234 NULL,
19235 data_func,
19236 close_func,
19237 user_data);
19238}
static struct mg_connection * mg_connect_websocket_client_impl(const struct mg_client_options *client_options, int use_ssl, char *error_buffer, size_t error_buffer_size, const char *path, const char *origin, const char *extensions, mg_websocket_data_handler data_func, mg_websocket_close_handler close_func, void *user_data)
Definition civetweb.c:18997
static void close_func(LexState *ls)
const char * host
Definition civetweb.h:1484

References close_func(), mg_client_options::host, mg_connect_websocket_client_impl(), NULL, and mg_client_options::port.

◆ mg_connect_websocket_client_extensions()

CIVETWEB_API struct mg_connection * mg_connect_websocket_client_extensions ( const char * host,
int port,
int use_ssl,
char * error_buffer,
size_t error_buffer_size,
const char * path,
const char * origin,
const char * extensions,
mg_websocket_data_handler data_func,
mg_websocket_close_handler close_func,
void * user_data )

Definition at line 19269 of file civetweb.c.

19280{
19281 struct mg_client_options client_options;
19282 memset(&client_options, 0, sizeof(client_options));
19283 client_options.host = host;
19284 client_options.port = port;
19285
19286 return mg_connect_websocket_client_impl(&client_options,
19287 use_ssl,
19288 error_buffer,
19289 error_buffer_size,
19290 path,
19291 origin,
19292 extensions,
19293 data_func,
19294 close_func,
19295 user_data);
19296}

References close_func(), mg_client_options::host, mg_connect_websocket_client_impl(), and mg_client_options::port.

◆ mg_connect_websocket_client_secure()

CIVETWEB_API struct mg_connection * mg_connect_websocket_client_secure ( const struct mg_client_options * client_options,
char * error_buffer,
size_t error_buffer_size,
const char * path,
const char * origin,
mg_websocket_data_handler data_func,
mg_websocket_close_handler close_func,
void * user_data )

Definition at line 19242 of file civetweb.c.

19251{
19252 if (!client_options) {
19253 return NULL;
19254 }
19255 return mg_connect_websocket_client_impl(client_options,
19256 1,
19257 error_buffer,
19258 error_buffer_size,
19259 path,
19260 origin,
19261 NULL,
19262 data_func,
19263 close_func,
19264 user_data);
19265}

References close_func(), mg_connect_websocket_client_impl(), and NULL.

◆ mg_connect_websocket_client_secure_extensions()

CIVETWEB_API struct mg_connection * mg_connect_websocket_client_secure_extensions ( const struct mg_client_options * client_options,
char * error_buffer,
size_t error_buffer_size,
const char * path,
const char * origin,
const char * extensions,
mg_websocket_data_handler data_func,
mg_websocket_close_handler close_func,
void * user_data )

Definition at line 19300 of file civetweb.c.

19310{
19311 if (!client_options) {
19312 return NULL;
19313 }
19314 return mg_connect_websocket_client_impl(client_options,
19315 1,
19316 error_buffer,
19317 error_buffer_size,
19318 path,
19319 origin,
19320 extensions,
19321 data_func,
19322 close_func,
19323 user_data);
19324}

References close_func(), mg_connect_websocket_client_impl(), and NULL.

◆ mg_cry()

CIVETWEB_API void mg_cry ( const struct mg_connection * conn,
PRINTF_FORMAT_STRING(const char *fmt) ,
... )

◆ mg_disable_connection_keep_alive()

CIVETWEB_API void mg_disable_connection_keep_alive ( struct mg_connection * conn)

Definition at line 22042 of file civetweb.c.

22043{
22044 /* https://github.com/civetweb/civetweb/issues/727 */
22045 if (conn != NULL) {
22046 conn->must_close = 1;
22047 }
22048}

References mg_connection::must_close, and NULL.

◆ mg_download()

CIVETWEB_API struct mg_connection * mg_download ( const char * host,
int port,
int use_ssl,
char * error_buffer,
size_t error_buffer_size,
PRINTF_FORMAT_STRING(const char *request_fmt) ,
... )

◆ mg_exit_library()

CIVETWEB_API unsigned mg_exit_library ( void )

Definition at line 22477 of file civetweb.c.

22478{
22479 if (mg_init_library_called <= 0) {
22480 return 0;
22481 }
22482
22484
22486 if (mg_init_library_called == 0) {
22487#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1)) && !defined(NO_SSL)
22488 if (mg_openssl_initialized) {
22490 mg_openssl_initialized = 0;
22491 }
22492#endif
22493
22494#if defined(_WIN32)
22495 (void)WSACleanup();
22496 (void)pthread_mutex_destroy(&global_log_file_lock);
22497#else
22498 (void)pthread_mutexattr_destroy(&pthread_mutex_attr);
22499#endif
22500
22501 (void)pthread_key_delete(sTlsKey);
22502
22503#if defined(USE_LUA)
22504 lua_exit_optional_libraries();
22505#endif
22507 all_methods = NULL;
22508
22510 (void)pthread_mutex_destroy(&global_lock_mutex);
22511 return 1;
22512 }
22513
22515 return 1;
22516}
static pthread_key_t sTlsKey
Definition civetweb.c:1580
static pthread_mutex_t global_lock_mutex
Definition civetweb.c:1089
static int mg_init_library_called
Definition civetweb.c:1552
static pthread_mutexattr_t pthread_mutex_attr
Definition civetweb.c:1074
static char * all_methods
Definition civetweb.c:10876
static void uninitialize_openssl(void)
Definition civetweb.c:17594
static FUNCTION_MAY_BE_UNUSED void mg_global_unlock(void)
Definition civetweb.c:1102
static FUNCTION_MAY_BE_UNUSED void mg_global_lock(void)
Definition civetweb.c:1094

References all_methods, global_lock_mutex, mg_free(), mg_global_lock(), mg_global_unlock(), mg_init_library_called, NULL, pthread_mutex_attr, sTlsKey, and uninitialize_openssl().

Referenced by run_client().

◆ mg_get_builtin_mime_type()

CIVETWEB_API const char * mg_get_builtin_mime_type ( const char * file_name)

Definition at line 8332 of file civetweb.c.

8333{
8334 const char *ext;
8335 size_t i, path_len;
8336
8337 path_len = strlen(path);
8338
8339 for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
8340 ext = path + (path_len - builtin_mime_types[i].ext_len);
8341 if ((path_len > builtin_mime_types[i].ext_len)
8342 && (mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0)) {
8343 return builtin_mime_types[i].mime_type;
8344 }
8345 }
8346
8347 return "text/plain";
8348}
size_t ext_len
Definition civetweb.c:8223
const char * extension
Definition civetweb.c:8222
CIVETWEB_API int mg_strcasecmp(const char *s1, const char *s2)
Definition civetweb.c:3034
static const struct @5 builtin_mime_types[]

References builtin_mime_types, ext_len, extension, mg_strcasecmp(), and NULL.

Referenced by get_mime_type().

◆ mg_get_context()

CIVETWEB_API struct mg_context * mg_get_context ( const struct mg_connection * conn)

Definition at line 3188 of file civetweb.c.

3189{
3190 return (conn == NULL) ? (struct mg_context *)NULL : (conn->phys_ctx);
3191}

References NULL, and mg_connection::phys_ctx.

Referenced by mg_get_user_context_data().

◆ mg_get_context_info()

CIVETWEB_API int mg_get_context_info ( const struct mg_context * ctx,
char * buffer,
int buflen )

Definition at line 21843 of file civetweb.c.

21844{
21845#if defined(USE_SERVER_STATS)
21846 char *end, *append_eoobj = NULL, block[256];
21847 size_t context_info_length = 0;
21848
21849#if defined(_WIN32)
21850 static const char eol[] = "\r\n", eoobj[] = "\r\n}\r\n";
21851#else
21852 static const char eol[] = "\n", eoobj[] = "\n}\n";
21853#endif
21854 struct mg_memory_stat *ms = get_memory_stat((struct mg_context *)ctx);
21855
21856 if ((buffer == NULL) || (buflen < 1)) {
21857 buflen = 0;
21858 end = buffer;
21859 } else {
21860 *buffer = 0;
21861 end = buffer + buflen;
21862 }
21863 if (buflen > (int)(sizeof(eoobj) - 1)) {
21864 /* has enough space to append eoobj */
21865 append_eoobj = buffer;
21866 end -= sizeof(eoobj) - 1;
21867 }
21868
21869 context_info_length += mg_str_append(&buffer, end, "{");
21870
21871 if (ms) { /* <-- should be always true */
21872 /* Memory information */
21873 int blockCount = (int)ms->blockCount;
21874 int64_t totalMemUsed = ms->totalMemUsed;
21875 int64_t maxMemUsed = ms->maxMemUsed;
21876 if (totalMemUsed > maxMemUsed) {
21877 maxMemUsed = totalMemUsed;
21878 }
21879
21881 NULL,
21882 block,
21883 sizeof(block),
21884 "%s\"memory\" : {%s"
21885 "\"blocks\" : %i,%s"
21886 "\"used\" : %" INT64_FMT ",%s"
21887 "\"maxUsed\" : %" INT64_FMT "%s"
21888 "}",
21889 eol,
21890 eol,
21891 blockCount,
21892 eol,
21893 totalMemUsed,
21894 eol,
21895 maxMemUsed,
21896 eol);
21897 context_info_length += mg_str_append(&buffer, end, block);
21898 }
21899
21900 if (ctx) {
21901 /* Declare all variables at begin of the block, to comply
21902 * with old C standards. */
21903 char start_time_str[64] = {0};
21904 char now_str[64] = {0};
21905 time_t start_time = ctx->start_time;
21906 time_t now = time(NULL);
21907 int64_t total_data_read, total_data_written;
21908 int active_connections = (int)ctx->active_connections;
21909 int max_active_connections = (int)ctx->max_active_connections;
21910 int total_connections = (int)ctx->total_connections;
21911 if (active_connections > max_active_connections) {
21912 max_active_connections = active_connections;
21913 }
21914 if (active_connections > total_connections) {
21915 total_connections = active_connections;
21916 }
21917
21918 /* Connections information */
21920 NULL,
21921 block,
21922 sizeof(block),
21923 ",%s\"connections\" : {%s"
21924 "\"active\" : %i,%s"
21925 "\"maxActive\" : %i,%s"
21926 "\"total\" : %i%s"
21927 "}",
21928 eol,
21929 eol,
21930 active_connections,
21931 eol,
21932 max_active_connections,
21933 eol,
21934 total_connections,
21935 eol);
21936 context_info_length += mg_str_append(&buffer, end, block);
21937
21938 /* Queue information */
21939#if !defined(ALTERNATIVE_QUEUE)
21941 NULL,
21942 block,
21943 sizeof(block),
21944 ",%s\"queue\" : {%s"
21945 "\"length\" : %i,%s"
21946 "\"filled\" : %i,%s"
21947 "\"maxFilled\" : %i,%s"
21948 "\"full\" : %s%s"
21949 "}",
21950 eol,
21951 eol,
21952 ctx->sq_size,
21953 eol,
21954 ctx->sq_head - ctx->sq_tail,
21955 eol,
21956 ctx->sq_max_fill,
21957 eol,
21958 (ctx->sq_blocked ? "true" : "false"),
21959 eol);
21960 context_info_length += mg_str_append(&buffer, end, block);
21961#endif
21962
21963 /* Requests information */
21965 NULL,
21966 block,
21967 sizeof(block),
21968 ",%s\"requests\" : {%s"
21969 "\"total\" : %lu%s"
21970 "}",
21971 eol,
21972 eol,
21973 (unsigned long)ctx->total_requests,
21974 eol);
21975 context_info_length += mg_str_append(&buffer, end, block);
21976
21977 /* Data information */
21978 total_data_read =
21979 mg_atomic_add64((volatile int64_t *)&ctx->total_data_read, 0);
21980 total_data_written =
21981 mg_atomic_add64((volatile int64_t *)&ctx->total_data_written, 0);
21983 NULL,
21984 block,
21985 sizeof(block),
21986 ",%s\"data\" : {%s"
21987 "\"read\" : %" INT64_FMT ",%s"
21988 "\"written\" : %" INT64_FMT "%s"
21989 "}",
21990 eol,
21991 eol,
21992 total_data_read,
21993 eol,
21994 total_data_written,
21995 eol);
21996 context_info_length += mg_str_append(&buffer, end, block);
21997
21998 /* Execution time information */
21999 gmt_time_string(start_time_str,
22000 sizeof(start_time_str) - 1,
22001 &start_time);
22002 gmt_time_string(now_str, sizeof(now_str) - 1, &now);
22003
22005 NULL,
22006 block,
22007 sizeof(block),
22008 ",%s\"time\" : {%s"
22009 "\"uptime\" : %.0f,%s"
22010 "\"start\" : \"%s\",%s"
22011 "\"now\" : \"%s\"%s"
22012 "}",
22013 eol,
22014 eol,
22015 difftime(now, start_time),
22016 eol,
22017 start_time_str,
22018 eol,
22019 now_str,
22020 eol);
22021 context_info_length += mg_str_append(&buffer, end, block);
22022 }
22023
22024 /* Terminate string */
22025 if (append_eoobj) {
22026 strcat(append_eoobj, eoobj);
22027 }
22028 context_info_length += sizeof(eoobj) - 1;
22029
22030 return (int)context_info_length;
22031#else
22032 (void)ctx;
22033 if ((buffer != NULL) && (buflen > 0)) {
22034 *buffer = 0;
22035 }
22036 return 0;
22037#endif
22038}
static size_t mg_str_append(char **dst, char *end, const char *src)
Definition civetweb.c:21493
#define INT64_FMT
Definition civetweb.c:926
static void gmt_time_string(char *buf, size_t buf_len, time_t *t)
Definition civetweb.c:3341
static void mg_snprintf(const struct mg_connection *conn, int *truncated, char *buf, size_t buflen, PRINTF_FORMAT_STRING(const char *fmt),...) PRINTF_ARGS(5
static void block(LexState *ls)
time_t start_time
Definition civetweb.c:2412
volatile int sq_head
Definition civetweb.c:2389
volatile int sq_tail
Definition civetweb.c:2390
volatile int sq_blocked
Definition civetweb.c:2393

References block(), gmt_time_string(), INT64_FMT, mg_snprintf(), mg_str_append(), NULL, mg_context::sq_blocked, mg_context::sq_head, mg_context::sq_size, mg_context::sq_tail, and mg_context::start_time.

◆ mg_get_cookie()

CIVETWEB_API int mg_get_cookie ( const char * cookie,
const char * var_name,
char * buf,
size_t buf_len )

Definition at line 7256 of file civetweb.c.

7260{
7261 const char *s, *p, *end;
7262 int name_len, len = -1;
7263
7264 if ((dst == NULL) || (dst_size == 0)) {
7265 return -2;
7266 }
7267
7268 dst[0] = '\0';
7269 if ((var_name == NULL) || ((s = cookie_header) == NULL)) {
7270 return -1;
7271 }
7272
7273 name_len = (int)strlen(var_name);
7274 end = s + strlen(s);
7275 for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
7276 if (s[name_len] == '=') {
7277 /* HCP24: now check is it a substring or a full cookie name */
7278 if ((s == cookie_header) || (s[-1] == ' ')) {
7279 s += name_len + 1;
7280 if ((p = strchr(s, ' ')) == NULL) {
7281 p = end;
7282 }
7283 if (p[-1] == ';') {
7284 p--;
7285 }
7286 if ((*s == '"') && (p[-1] == '"') && (p > s + 1)) {
7287 s++;
7288 p--;
7289 }
7290 if ((size_t)(p - s) < dst_size) {
7291 len = (int)(p - s);
7292 mg_strlcpy(dst, s, (size_t)len + 1);
7293 } else {
7294 len = -3;
7295 }
7296 break;
7297 }
7298 }
7299 }
7300 return len;
7301}
static const char * mg_strcasestr(const char *big_str, const char *small_str)
Definition civetweb.c:3075
static void mg_strlcpy(char *dst, const char *src, size_t n)
Definition civetweb.c:3002
CURL_EXTERN CURLMcode curl_socket_t s
Definition multi.h:318

References mg_strcasestr(), mg_strlcpy(), NULL, and s.

◆ mg_get_header()

CIVETWEB_API const char * mg_get_header ( const struct mg_connection * conn,
const char * name )

Definition at line 3855 of file civetweb.c.

3856{
3857 if (!conn) {
3858 return NULL;
3859 }
3860
3864 name);
3865 }
3869 name);
3870 }
3871 return NULL;
3872}
static const char * get_header(const struct mg_header *hdr, int num_hdr, const char *name)
Definition civetweb.c:3820
@ CONNECTION_TYPE_RESPONSE
Definition civetweb.c:2462
@ CONNECTION_TYPE_REQUEST
Definition civetweb.c:2461
const char * name
Definition lsqlite3.c:2154
int connection_type
Definition civetweb.c:2486
struct mg_response_info response_info
Definition civetweb.c:2495
struct mg_request_info request_info
Definition civetweb.c:2494
struct mg_header http_headers[MG_MAX_HEADERS]
Definition civetweb.h:179
struct mg_header http_headers[MG_MAX_HEADERS]
Definition civetweb.h:200

References mg_connection::connection_type, CONNECTION_TYPE_REQUEST, CONNECTION_TYPE_RESPONSE, get_header(), mg_request_info::http_headers, mg_response_info::http_headers, name, NULL, mg_request_info::num_headers, mg_response_info::num_headers, mg_connection::request_info, and mg_connection::response_info.

Referenced by dav_move_file(), forward_body_data(), handle_propfind(), handle_static_file_request(), header_val(), interpret_uri(), is_not_modified(), parse_auth_header(), prepare_cgi_environment(), put_file(), send_cors_header(), should_keep_alive(), and should_switch_to_protocol().

◆ mg_get_option()

CIVETWEB_API const char * mg_get_option ( const struct mg_context * ctx,
const char * name )

Definition at line 3173 of file civetweb.c.

3174{
3175 int i;
3176 if ((i = get_option_index(name)) == -1) {
3177 return NULL;
3178 } else if (!ctx || ctx->dd.config[i] == NULL) {
3179 return "";
3180 } else {
3181 return ctx->dd.config[i];
3182 }
3183}
static int get_option_index(const char *name)
Definition civetweb.c:3159
char * config[NUM_OPTIONS]
Definition civetweb.c:2271

References mg_domain_context::config, mg_context::dd, get_option_index(), name, and NULL.

◆ mg_get_request_info()

CIVETWEB_API const struct mg_request_info * mg_get_request_info ( const struct mg_connection * conn)

Definition at line 3521 of file civetweb.c.

3522{
3523 if (!conn) {
3524 return NULL;
3525 }
3526#if defined(MG_ALLOW_USING_GET_REQUEST_INFO_FOR_RESPONSE)
3528 char txt[16];
3529 struct mg_workerTLS *tls =
3530 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
3531
3532 sprintf(txt, "%03i", conn->response_info.status_code);
3533 if (strlen(txt) == 3) {
3534 memcpy(tls->txtbuf, txt, 4);
3535 } else {
3536 strcpy(tls->txtbuf, "ERR");
3537 }
3538
3539 ((struct mg_connection *)conn)->request_info.local_uri =
3540 tls->txtbuf; /* use thread safe buffer */
3541 ((struct mg_connection *)conn)->request_info.local_uri_raw =
3542 tls->txtbuf; /* use the same thread safe buffer */
3543 ((struct mg_connection *)conn)->request_info.request_uri =
3544 tls->txtbuf; /* use the same thread safe buffer */
3545
3546 ((struct mg_connection *)conn)->request_info.num_headers =
3548 memcpy(((struct mg_connection *)conn)->request_info.http_headers,
3550 sizeof(conn->response_info.http_headers));
3551 } else
3552#endif
3554 return NULL;
3555 }
3556 return &conn->request_info;
3557}

References mg_connection::connection_type, CONNECTION_TYPE_REQUEST, CONNECTION_TYPE_RESPONSE, mg_request_info::http_headers, mg_response_info::http_headers, NULL, mg_response_info::num_headers, mg_connection::request_info, mg_connection::response_info, mg_response_info::status_code, and sTlsKey.

Referenced by get_request_handler(), and user_handler().

◆ mg_get_request_link()

CIVETWEB_API int mg_get_request_link ( const struct mg_connection * conn,
char * buf,
size_t buflen )

Definition at line 3745 of file civetweb.c.

3746{
3747 return mg_construct_local_link(conn, buf, buflen, NULL, -1, NULL);
3748}
static int mg_construct_local_link(const struct mg_connection *conn, char *buf, size_t buflen, const char *define_proto, int define_port, const char *define_uri)
Definition civetweb.c:3601

References mg_construct_local_link(), and NULL.

Referenced by dav_lock_file(), dav_proppatch(), dav_unlock_file(), and handle_request().

◆ mg_get_response()

CIVETWEB_API int mg_get_response ( struct mg_connection * conn,
char * ebuf,
size_t ebuf_len,
int timeout )

Definition at line 18822 of file civetweb.c.

18826{
18827 int err, ret;
18828 char txt[32]; /* will not overflow */
18829 char *save_timeout;
18830 char *new_timeout;
18831
18832 if (ebuf_len > 0) {
18833 ebuf[0] = '\0';
18834 }
18835
18836 if (!conn) {
18837 mg_snprintf(conn,
18838 NULL, /* No truncation check for ebuf */
18839 ebuf,
18840 ebuf_len,
18841 "%s",
18842 "Parameter error");
18843 return -1;
18844 }
18845
18846 /* Reset the previous responses */
18847 conn->data_len = 0;
18848
18849 /* Implementation of API function for HTTP clients */
18850 save_timeout = conn->dom_ctx->config[REQUEST_TIMEOUT];
18851
18852 if (timeout >= 0) {
18853 mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
18854 new_timeout = txt;
18855 } else {
18856 new_timeout = NULL;
18857 }
18858
18859 conn->dom_ctx->config[REQUEST_TIMEOUT] = new_timeout;
18860 ret = get_response(conn, ebuf, ebuf_len, &err);
18861 conn->dom_ctx->config[REQUEST_TIMEOUT] = save_timeout;
18862
18863 /* TODO: here, the URI is the http response code */
18866
18867 /* TODO (mid): Define proper return values - maybe return length?
18868 * For the first test use <0 for error and >0 for OK */
18869 return (ret == 0) ? -1 : +1;
18870}
@ REQUEST_TIMEOUT
Definition civetweb.c:1937
static int get_response(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
Definition civetweb.c:18737
struct mg_domain_context * dom_ctx
Definition civetweb.c:2498
const char * local_uri
Definition civetweb.h:157
const char * local_uri_raw
Definition civetweb.h:154
const char * request_uri
Definition civetweb.h:152

References mg_domain_context::config, mg_connection::data_len, mg_connection::dom_ctx, get_response(), mg_request_info::local_uri, mg_request_info::local_uri_raw, mg_snprintf(), NULL, mg_connection::request_info, REQUEST_TIMEOUT, and mg_request_info::request_uri.

Referenced by run_client().

◆ mg_get_response_code_text()

CIVETWEB_API const char * mg_get_response_code_text ( const struct mg_connection * conn,
int response_code )

Definition at line 4176 of file civetweb.c.

4177{
4178 /* See IANA HTTP status code assignment:
4179 * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
4180 */
4181
4182 switch (response_code) {
4183 /* RFC2616 Section 10.1 - Informational 1xx */
4184 case 100:
4185 return "Continue"; /* RFC2616 Section 10.1.1 */
4186 case 101:
4187 return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
4188 case 102:
4189 return "Processing"; /* RFC2518 Section 10.1 */
4190
4191 /* RFC2616 Section 10.2 - Successful 2xx */
4192 case 200:
4193 return "OK"; /* RFC2616 Section 10.2.1 */
4194 case 201:
4195 return "Created"; /* RFC2616 Section 10.2.2 */
4196 case 202:
4197 return "Accepted"; /* RFC2616 Section 10.2.3 */
4198 case 203:
4199 return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
4200 case 204:
4201 return "No Content"; /* RFC2616 Section 10.2.5 */
4202 case 205:
4203 return "Reset Content"; /* RFC2616 Section 10.2.6 */
4204 case 206:
4205 return "Partial Content"; /* RFC2616 Section 10.2.7 */
4206 case 207:
4207 return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1
4208 */
4209 case 208:
4210 return "Already Reported"; /* RFC5842 Section 7.1 */
4211
4212 case 226:
4213 return "IM used"; /* RFC3229 Section 10.4.1 */
4214
4215 /* RFC2616 Section 10.3 - Redirection 3xx */
4216 case 300:
4217 return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
4218 case 301:
4219 return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
4220 case 302:
4221 return "Found"; /* RFC2616 Section 10.3.3 */
4222 case 303:
4223 return "See Other"; /* RFC2616 Section 10.3.4 */
4224 case 304:
4225 return "Not Modified"; /* RFC2616 Section 10.3.5 */
4226 case 305:
4227 return "Use Proxy"; /* RFC2616 Section 10.3.6 */
4228 case 307:
4229 return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
4230 case 308:
4231 return "Permanent Redirect"; /* RFC7238 Section 3 */
4232
4233 /* RFC2616 Section 10.4 - Client Error 4xx */
4234 case 400:
4235 return "Bad Request"; /* RFC2616 Section 10.4.1 */
4236 case 401:
4237 return "Unauthorized"; /* RFC2616 Section 10.4.2 */
4238 case 402:
4239 return "Payment Required"; /* RFC2616 Section 10.4.3 */
4240 case 403:
4241 return "Forbidden"; /* RFC2616 Section 10.4.4 */
4242 case 404:
4243 return "Not Found"; /* RFC2616 Section 10.4.5 */
4244 case 405:
4245 return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
4246 case 406:
4247 return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
4248 case 407:
4249 return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
4250 case 408:
4251 return "Request Time-out"; /* RFC2616 Section 10.4.9 */
4252 case 409:
4253 return "Conflict"; /* RFC2616 Section 10.4.10 */
4254 case 410:
4255 return "Gone"; /* RFC2616 Section 10.4.11 */
4256 case 411:
4257 return "Length Required"; /* RFC2616 Section 10.4.12 */
4258 case 412:
4259 return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
4260 case 413:
4261 return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
4262 case 414:
4263 return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
4264 case 415:
4265 return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
4266 case 416:
4267 return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17
4268 */
4269 case 417:
4270 return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
4271
4272 case 421:
4273 return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
4274 case 422:
4275 return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
4276 * Section 11.2 */
4277 case 423:
4278 return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
4279 case 424:
4280 return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
4281 * Section 11.4 */
4282
4283 case 426:
4284 return "Upgrade Required"; /* RFC 2817 Section 4 */
4285
4286 case 428:
4287 return "Precondition Required"; /* RFC 6585, Section 3 */
4288 case 429:
4289 return "Too Many Requests"; /* RFC 6585, Section 4 */
4290
4291 case 431:
4292 return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
4293
4294 case 451:
4295 return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
4296 * Section 3 */
4297
4298 /* RFC2616 Section 10.5 - Server Error 5xx */
4299 case 500:
4300 return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
4301 case 501:
4302 return "Not Implemented"; /* RFC2616 Section 10.5.2 */
4303 case 502:
4304 return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
4305 case 503:
4306 return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
4307 case 504:
4308 return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
4309 case 505:
4310 return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
4311 case 506:
4312 return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
4313 case 507:
4314 return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
4315 * Section 11.5 */
4316 case 508:
4317 return "Loop Detected"; /* RFC5842 Section 7.1 */
4318
4319 case 510:
4320 return "Not Extended"; /* RFC 2774, Section 7 */
4321 case 511:
4322 return "Network Authentication Required"; /* RFC 6585, Section 6 */
4323
4324 /* Other status codes, not shown in the IANA HTTP status code
4325 * assignment.
4326 * E.g., "de facto" standards due to common use, ... */
4327 case 418:
4328 return "I am a teapot"; /* RFC2324 Section 2.3.2 */
4329 case 419:
4330 return "Authentication Timeout"; /* common use */
4331 case 420:
4332 return "Enhance Your Calm"; /* common use */
4333 case 440:
4334 return "Login Timeout"; /* common use */
4335 case 509:
4336 return "Bandwidth Limit Exceeded"; /* common use */
4337
4338 default:
4339 /* This error code is unknown. This should not happen. */
4340 if (conn) {
4341 mg_cry_internal(conn,
4342 "Unknown HTTP response code: %u",
4343 response_code);
4344 }
4345
4346 /* Return at least a category according to RFC 2616 Section 10. */
4347 if (response_code >= 100 && response_code < 200) {
4348 /* Unknown informational status code */
4349 return "Information";
4350 }
4351 if (response_code >= 200 && response_code < 300) {
4352 /* Unknown success code */
4353 return "Success";
4354 }
4355 if (response_code >= 300 && response_code < 400) {
4356 /* Unknown redirection code */
4357 return "Redirection";
4358 }
4359 if (response_code >= 400 && response_code < 500) {
4360 /* Unknown request error code */
4361 return "Client Error";
4362 }
4363 if (response_code >= 500 && response_code < 600) {
4364 /* Unknown server error code */
4365 return "Server Error";
4366 }
4367
4368 /* Response code not even within reasonable range */
4369 return "";
4370 }
4371}
#define mg_cry_internal(conn, fmt,...)
Definition civetweb.c:2583

References mg_cry_internal.

Referenced by mg_send_http_error_impl().

◆ mg_get_response_info()

CIVETWEB_API const struct mg_response_info * mg_get_response_info ( const struct mg_connection * conn)

Definition at line 3561 of file civetweb.c.

3562{
3563 if (!conn) {
3564 return NULL;
3565 }
3567 return NULL;
3568 }
3569 return &conn->response_info;
3570}

References mg_connection::connection_type, CONNECTION_TYPE_RESPONSE, NULL, and mg_connection::response_info.

Referenced by run_client().

◆ mg_get_server_ports()

CIVETWEB_API int mg_get_server_ports ( const struct mg_context * ctx,
int size,
struct mg_server_port * ports )

Definition at line 3248 of file civetweb.c.

3251{
3252 int i, cnt = 0;
3253
3254 if (size <= 0) {
3255 return -1;
3256 }
3257 memset(ports, 0, sizeof(*ports) * (size_t)size);
3258 if (!ctx) {
3259 return -1;
3260 }
3261 if (!ctx->listening_sockets) {
3262 return -1;
3263 }
3264
3265 for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
3266
3267 ports[cnt].port =
3268 ntohs(USA_IN_PORT_UNSAFE(&(ctx->listening_sockets[i].lsa)));
3269 ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
3270 ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
3271
3272 if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
3273 /* IPv4 */
3274 ports[cnt].protocol = 1;
3275 cnt++;
3276 } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
3277 /* IPv6 */
3278 ports[cnt].protocol = 3;
3279 cnt++;
3280 }
3281 }
3282
3283 return cnt;
3284}
#define USA_IN_PORT_UNSAFE(s)
Definition civetweb.c:1860
struct socket * listening_sockets
Definition civetweb.c:2356
unsigned int num_listening_sockets
Definition civetweb.c:2358
unsigned char is_ssl
Definition civetweb.c:1906
union usa lsa
Definition civetweb.c:1904
unsigned char ssl_redir
Definition civetweb.c:1907
struct sockaddr sa
Definition civetweb.c:1833

References mg_server_port::is_redirect, socket::is_ssl, mg_server_port::is_ssl, mg_context::listening_sockets, socket::lsa, mg_context::num_listening_sockets, mg_server_port::port, mg_server_port::protocol, usa::sa, socket::ssl_redir, and USA_IN_PORT_UNSAFE.

◆ mg_get_system_info()

CIVETWEB_API int mg_get_system_info ( char * buffer,
int buflen )

Definition at line 21512 of file civetweb.c.

21513{
21514 char *end, *append_eoobj = NULL, block[256];
21515 size_t system_info_length = 0;
21516
21517#if defined(_WIN32)
21518 static const char eol[] = "\r\n", eoobj[] = "\r\n}\r\n";
21519#else
21520 static const char eol[] = "\n", eoobj[] = "\n}\n";
21521#endif
21522
21523 if ((buffer == NULL) || (buflen < 1)) {
21524 buflen = 0;
21525 end = buffer;
21526 } else {
21527 *buffer = 0;
21528 end = buffer + buflen;
21529 }
21530 if (buflen > (int)(sizeof(eoobj) - 1)) {
21531 /* has enough space to append eoobj */
21532 append_eoobj = buffer;
21533 if (end) {
21534 end -= sizeof(eoobj) - 1;
21535 }
21536 }
21537
21538 system_info_length += mg_str_append(&buffer, end, "{");
21539
21540 /* Server version */
21541 {
21542 const char *version = mg_version();
21544 NULL,
21545 block,
21546 sizeof(block),
21547 "%s\"version\" : \"%s\"",
21548 eol,
21549 version);
21550 system_info_length += mg_str_append(&buffer, end, block);
21551 }
21552
21553 /* System info */
21554 {
21555#if defined(_WIN32)
21556 DWORD dwVersion = 0;
21557 DWORD dwMajorVersion = 0;
21558 DWORD dwMinorVersion = 0;
21559 SYSTEM_INFO si;
21560
21561 GetSystemInfo(&si);
21562
21563#if defined(_MSC_VER)
21564#pragma warning(push)
21565 /* GetVersion was declared deprecated */
21566#pragma warning(disable : 4996)
21567#endif
21568 dwVersion = GetVersion();
21569#if defined(_MSC_VER)
21570#pragma warning(pop)
21571#endif
21572
21573 dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
21574 dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
21575
21577 NULL,
21578 block,
21579 sizeof(block),
21580 ",%s\"os\" : \"Windows %u.%u\"",
21581 eol,
21582 (unsigned)dwMajorVersion,
21583 (unsigned)dwMinorVersion);
21584 system_info_length += mg_str_append(&buffer, end, block);
21585
21587 NULL,
21588 block,
21589 sizeof(block),
21590 ",%s\"cpu\" : \"type %u, cores %u, mask %x\"",
21591 eol,
21592 (unsigned)si.wProcessorArchitecture,
21593 (unsigned)si.dwNumberOfProcessors,
21594 (unsigned)si.dwActiveProcessorMask);
21595 system_info_length += mg_str_append(&buffer, end, block);
21596#elif defined(__ZEPHYR__)
21598 NULL,
21599 block,
21600 sizeof(block),
21601 ",%s\"os\" : \"%s %s\"",
21602 eol,
21603 "Zephyr OS",
21604 ZEPHYR_VERSION);
21605 system_info_length += mg_str_append(&buffer, end, block);
21606#else
21607 struct utsname name;
21608 memset(&name, 0, sizeof(name));
21609 uname(&name);
21610
21612 NULL,
21613 block,
21614 sizeof(block),
21615 ",%s\"os\" : \"%s %s (%s) - %s\"",
21616 eol,
21617 name.sysname,
21618 name.version,
21619 name.release,
21620 name.machine);
21621 system_info_length += mg_str_append(&buffer, end, block);
21622#endif
21623 }
21624
21625 /* Features */
21626 {
21628 NULL,
21629 block,
21630 sizeof(block),
21631 ",%s\"features\" : %lu"
21632 ",%s\"feature_list\" : \"Server:%s%s%s%s%s%s%s%s%s\"",
21633 eol,
21634 (unsigned long)mg_check_feature(0xFFFFFFFFu),
21635 eol,
21636 mg_check_feature(MG_FEATURES_FILES) ? " Files" : "",
21637 mg_check_feature(MG_FEATURES_SSL) ? " HTTPS" : "",
21638 mg_check_feature(MG_FEATURES_CGI) ? " CGI" : "",
21639 mg_check_feature(MG_FEATURES_IPV6) ? " IPv6" : "",
21641 : "",
21642 mg_check_feature(MG_FEATURES_LUA) ? " Lua" : "",
21643 mg_check_feature(MG_FEATURES_SSJS) ? " JavaScript" : "",
21644 mg_check_feature(MG_FEATURES_CACHE) ? " Cache" : "",
21645 mg_check_feature(MG_FEATURES_STATS) ? " Stats" : "");
21646 system_info_length += mg_str_append(&buffer, end, block);
21647
21648#if defined(USE_LUA)
21650 NULL,
21651 block,
21652 sizeof(block),
21653 ",%s\"lua_version\" : \"%u (%s)\"",
21654 eol,
21655 (unsigned)LUA_VERSION_NUM,
21656 LUA_RELEASE);
21657 system_info_length += mg_str_append(&buffer, end, block);
21658#endif
21659#if defined(USE_DUKTAPE)
21661 NULL,
21662 block,
21663 sizeof(block),
21664 ",%s\"javascript\" : \"Duktape %u.%u.%u\"",
21665 eol,
21666 (unsigned)DUK_VERSION / 10000,
21667 ((unsigned)DUK_VERSION / 100) % 100,
21668 (unsigned)DUK_VERSION % 100);
21669 system_info_length += mg_str_append(&buffer, end, block);
21670#endif
21671 }
21672
21673 /* Build identifier. If BUILD_DATE is not set, __DATE__ will be used. */
21674 {
21675#if defined(BUILD_DATE)
21676 const char *bd = BUILD_DATE;
21677#else
21678#if defined(GCC_DIAGNOSTIC)
21679#if GCC_VERSION >= 40900
21680#pragma GCC diagnostic push
21681 /* Disable idiotic compiler warning -Wdate-time, appeared in gcc5. This
21682 * does not work in some versions. If "BUILD_DATE" is defined to some
21683 * string, it is used instead of __DATE__. */
21684#pragma GCC diagnostic ignored "-Wdate-time"
21685#endif
21686#endif
21687 const char *bd = __DATE__;
21688#if defined(GCC_DIAGNOSTIC)
21689#if GCC_VERSION >= 40900
21690#pragma GCC diagnostic pop
21691#endif
21692#endif
21693#endif
21694
21696 NULL, NULL, block, sizeof(block), ",%s\"build\" : \"%s\"", eol, bd);
21697
21698 system_info_length += mg_str_append(&buffer, end, block);
21699 }
21700
21701 /* Compiler information */
21702 /* http://sourceforge.net/p/predef/wiki/Compilers/ */
21703 {
21704#if defined(_MSC_VER)
21706 NULL,
21707 block,
21708 sizeof(block),
21709 ",%s\"compiler\" : \"MSC: %u (%u)\"",
21710 eol,
21711 (unsigned)_MSC_VER,
21712 (unsigned)_MSC_FULL_VER);
21713 system_info_length += mg_str_append(&buffer, end, block);
21714#elif defined(__MINGW64__)
21716 NULL,
21717 block,
21718 sizeof(block),
21719 ",%s\"compiler\" : \"MinGW64: %u.%u\"",
21720 eol,
21721 (unsigned)__MINGW64_VERSION_MAJOR,
21722 (unsigned)__MINGW64_VERSION_MINOR);
21723 system_info_length += mg_str_append(&buffer, end, block);
21725 NULL,
21726 block,
21727 sizeof(block),
21728 ",%s\"compiler\" : \"MinGW32: %u.%u\"",
21729 eol,
21730 (unsigned)__MINGW32_MAJOR_VERSION,
21731 (unsigned)__MINGW32_MINOR_VERSION);
21732 system_info_length += mg_str_append(&buffer, end, block);
21733#elif defined(__MINGW32__)
21735 NULL,
21736 block,
21737 sizeof(block),
21738 ",%s\"compiler\" : \"MinGW32: %u.%u\"",
21739 eol,
21740 (unsigned)__MINGW32_MAJOR_VERSION,
21741 (unsigned)__MINGW32_MINOR_VERSION);
21742 system_info_length += mg_str_append(&buffer, end, block);
21743#elif defined(__clang__)
21745 NULL,
21746 block,
21747 sizeof(block),
21748 ",%s\"compiler\" : \"clang: %u.%u.%u (%s)\"",
21749 eol,
21750 __clang_major__,
21751 __clang_minor__,
21752 __clang_patchlevel__,
21753 __clang_version__);
21754 system_info_length += mg_str_append(&buffer, end, block);
21755#elif defined(__GNUC__)
21757 NULL,
21758 block,
21759 sizeof(block),
21760 ",%s\"compiler\" : \"gcc: %u.%u.%u\"",
21761 eol,
21762 (unsigned)__GNUC__,
21763 (unsigned)__GNUC_MINOR__,
21764 (unsigned)__GNUC_PATCHLEVEL__);
21765 system_info_length += mg_str_append(&buffer, end, block);
21766#elif defined(__INTEL_COMPILER)
21768 NULL,
21769 block,
21770 sizeof(block),
21771 ",%s\"compiler\" : \"Intel C/C++: %u\"",
21772 eol,
21773 (unsigned)__INTEL_COMPILER);
21774 system_info_length += mg_str_append(&buffer, end, block);
21775#elif defined(__BORLANDC__)
21777 NULL,
21778 block,
21779 sizeof(block),
21780 ",%s\"compiler\" : \"Borland C: 0x%x\"",
21781 eol,
21782 (unsigned)__BORLANDC__);
21783 system_info_length += mg_str_append(&buffer, end, block);
21784#elif defined(__SUNPRO_C)
21786 NULL,
21787 block,
21788 sizeof(block),
21789 ",%s\"compiler\" : \"Solaris: 0x%x\"",
21790 eol,
21791 (unsigned)__SUNPRO_C);
21792 system_info_length += mg_str_append(&buffer, end, block);
21793#else
21795 NULL,
21796 block,
21797 sizeof(block),
21798 ",%s\"compiler\" : \"other\"",
21799 eol);
21800 system_info_length += mg_str_append(&buffer, end, block);
21801#endif
21802 }
21803
21804 /* Determine 32/64 bit data mode.
21805 * see https://en.wikipedia.org/wiki/64-bit_computing */
21806 {
21808 NULL,
21809 block,
21810 sizeof(block),
21811 ",%s\"data_model\" : \"int:%u/%u/%u/%u, float:%u/%u/%u, "
21812 "char:%u/%u, "
21813 "ptr:%u, size:%u, time:%u\"",
21814 eol,
21815 (unsigned)sizeof(short),
21816 (unsigned)sizeof(int),
21817 (unsigned)sizeof(long),
21818 (unsigned)sizeof(long long),
21819 (unsigned)sizeof(float),
21820 (unsigned)sizeof(double),
21821 (unsigned)sizeof(long double),
21822 (unsigned)sizeof(char),
21823 (unsigned)sizeof(wchar_t),
21824 (unsigned)sizeof(void *),
21825 (unsigned)sizeof(size_t),
21826 (unsigned)sizeof(time_t));
21827 system_info_length += mg_str_append(&buffer, end, block);
21828 }
21829
21830 /* Terminate string */
21831 if (append_eoobj) {
21832 strcat(append_eoobj, eoobj);
21833 }
21834 system_info_length += sizeof(eoobj) - 1;
21835
21836 return (int)system_info_length;
21837}
CIVETWEB_API const char * mg_version(void)
Definition civetweb.c:3514
CIVETWEB_API unsigned mg_check_feature(unsigned feature)
Definition civetweb.c:21430
#define LUA_VERSION_NUM
#define LUA_RELEASE

References block(), DUK_VERSION, LUA_RELEASE, LUA_VERSION_NUM, mg_check_feature(), MG_FEATURES_CACHE, MG_FEATURES_CGI, MG_FEATURES_FILES, MG_FEATURES_IPV6, MG_FEATURES_LUA, MG_FEATURES_SSJS, MG_FEATURES_SSL, MG_FEATURES_STATS, MG_FEATURES_WEBSOCKET, mg_snprintf(), mg_str_append(), mg_version(), name, and NULL.

Referenced by init_system_info().

◆ mg_get_thread_pointer()

CIVETWEB_API void * mg_get_thread_pointer ( const struct mg_connection * conn)

Definition at line 3209 of file civetweb.c.

3210{
3211 /* both methods should return the same pointer */
3212 if (conn) {
3213 /* quick access, in case conn is known */
3214 return conn->tls_user_ptr;
3215 } else {
3216 /* otherwise get pointer from thread local storage (TLS) */
3217 struct mg_workerTLS *tls =
3218 (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
3219 return tls->user_ptr;
3220 }
3221}
void * tls_user_ptr
Definition civetweb.c:2571
void * user_ptr
Definition civetweb.c:1590

References sTlsKey, mg_connection::tls_user_ptr, and mg_workerTLS::user_ptr.

◆ mg_get_user_connection_data()

CIVETWEB_API void * mg_get_user_connection_data ( const struct mg_connection * conn)

Definition at line 3238 of file civetweb.c.

3239{
3240 if (conn != NULL) {
3241 return conn->request_info.conn_data;
3242 }
3243 return NULL;
3244}
void * conn_data
Definition civetweb.h:176

References mg_request_info::conn_data, NULL, and mg_connection::request_info.

◆ mg_get_user_context_data()

CIVETWEB_API void * mg_get_user_context_data ( const struct mg_connection * conn)

Definition at line 3202 of file civetweb.c.

3203{
3204 return mg_get_user_data(mg_get_context(conn));
3205}
CIVETWEB_API void * mg_get_user_data(const struct mg_context *ctx)
Definition civetweb.c:3195
CIVETWEB_API struct mg_context * mg_get_context(const struct mg_connection *conn)
Definition civetweb.c:3188

References mg_get_context(), and mg_get_user_data().

◆ mg_get_user_data()

CIVETWEB_API void * mg_get_user_data ( const struct mg_context * ctx)

Definition at line 3195 of file civetweb.c.

3196{
3197 return (ctx == NULL) ? NULL : ctx->user_data;
3198}
void * user_data
Definition civetweb.c:2433

References NULL, and mg_context::user_data.

Referenced by mg_get_user_context_data().

◆ mg_get_valid_options()

CIVETWEB_API const struct mg_option * mg_get_valid_options ( void )

Definition at line 2833 of file civetweb.c.

2834{
2835 return config_options;
2836}
static const struct mg_option config_options[]
Definition civetweb.c:2062

References config_options.

Referenced by set_option(), and show_usage_and_exit().

◆ mg_get_var()

CIVETWEB_API int mg_get_var ( const char * data,
size_t data_len,
const char * var_name,
char * dst,
size_t dst_len )

Definition at line 7088 of file civetweb.c.

7093{
7094 return mg_get_var2(data, data_len, name, dst, dst_len, 0);
7095}
CIVETWEB_API int mg_get_var2(const char *data, size_t data_len, const char *name, char *dst, size_t dst_len, size_t occurrence)
Definition civetweb.c:7099

References mg_get_var2(), and name.

◆ mg_get_var2()

CIVETWEB_API int mg_get_var2 ( const char * data,
size_t data_len,
const char * var_name,
char * dst,
size_t dst_len,
size_t occurrence )

Definition at line 7099 of file civetweb.c.

7105{
7106 const char *p, *e, *s;
7107 size_t name_len;
7108 int len;
7109
7110 if ((dst == NULL) || (dst_len == 0)) {
7111 len = -2;
7112 } else if ((data == NULL) || (name == NULL) || (data_len == 0)) {
7113 len = -1;
7114 dst[0] = '\0';
7115 } else {
7116 name_len = strlen(name);
7117 e = data + data_len;
7118 len = -1;
7119 dst[0] = '\0';
7120
7121 /* data is "var1=val1&var2=val2...". Find variable first */
7122 for (p = data; p + name_len < e; p++) {
7123 if (((p == data) || (p[-1] == '&')) && (p[name_len] == '=')
7124 && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
7125 /* Point p to variable value */
7126 p += name_len + 1;
7127
7128 /* Point s to the end of the value */
7129 s = (const char *)memchr(p, '&', (size_t)(e - p));
7130 if (s == NULL) {
7131 s = e;
7132 }
7133 DEBUG_ASSERT(s >= p);
7134 if (s < p) {
7135 return -3;
7136 }
7137
7138 /* Decode variable into destination buffer */
7139 len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
7140
7141 /* Redirect error code from -1 to -2 (destination buffer too
7142 * small). */
7143 if (len == -1) {
7144 len = -2;
7145 }
7146 break;
7147 }
7148 }
7149 }
7150
7151 return len;
7152}
CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len)
Definition civetweb.c:3019
CIVETWEB_API int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded)
Definition civetweb.c:7048
#define DEBUG_ASSERT(cond)
Definition civetweb.c:260

References DEBUG_ASSERT, mg_strncasecmp(), mg_url_decode(), name, NULL, and s.

Referenced by mg_get_var().

◆ mg_handle_form_request()

CIVETWEB_API int mg_handle_form_request ( struct mg_connection * conn,
struct mg_form_data_handler * fdh )

◆ mg_init_library()

CIVETWEB_API unsigned mg_init_library ( unsigned features)

Definition at line 22347 of file civetweb.c.

22348{
22349 unsigned features_to_init = mg_check_feature(features & 0xFFu);
22350 unsigned features_inited = features_to_init;
22351
22352 if (mg_init_library_called <= 0) {
22353 /* Not initialized yet */
22354 if (0 != pthread_mutex_init(&global_lock_mutex, NULL)) {
22355 return 0;
22356 }
22357 }
22358
22360
22361 if (mg_init_library_called <= 0) {
22362 int i;
22363 size_t len;
22364
22365#if defined(_WIN32)
22366 int file_mutex_init = 1;
22367 int wsa = 1;
22368#else
22369 int mutexattr_init = 1;
22370#endif
22371 int failed = 1;
22372 int key_create = pthread_key_create(&sTlsKey, tls_dtor);
22373
22374 if (key_create == 0) {
22375#if defined(_WIN32)
22376 file_mutex_init =
22377 pthread_mutex_init(&global_log_file_lock, &pthread_mutex_attr);
22378 if (file_mutex_init == 0) {
22379 /* Start WinSock */
22380 WSADATA data;
22381 failed = wsa = WSAStartup(MAKEWORD(2, 2), &data);
22382 }
22383#else
22384 mutexattr_init = pthread_mutexattr_init(&pthread_mutex_attr);
22385 if (mutexattr_init == 0) {
22386 failed = pthread_mutexattr_settype(&pthread_mutex_attr,
22387 PTHREAD_MUTEX_RECURSIVE);
22388 }
22389#endif
22390 }
22391
22392 if (failed) {
22393#if defined(_WIN32)
22394 if (wsa == 0) {
22395 (void)WSACleanup();
22396 }
22397 if (file_mutex_init == 0) {
22398 (void)pthread_mutex_destroy(&global_log_file_lock);
22399 }
22400#else
22401 if (mutexattr_init == 0) {
22402 (void)pthread_mutexattr_destroy(&pthread_mutex_attr);
22403 }
22404#endif
22405 if (key_create == 0) {
22406 (void)pthread_key_delete(sTlsKey);
22407 }
22409 (void)pthread_mutex_destroy(&global_lock_mutex);
22410 return 0;
22411 }
22412
22413 len = 1;
22414 for (i = 0; http_methods[i].name != NULL; i++) {
22415 size_t sl = strlen(http_methods[i].name);
22416 len += sl;
22417 if (i > 0) {
22418 len += 2;
22419 }
22420 }
22421 all_methods = (char *)mg_malloc(len);
22422 if (!all_methods) {
22423 /* Must never happen */
22425 (void)pthread_mutex_destroy(&global_lock_mutex);
22426 return 0;
22427 }
22428 all_methods[0] = 0;
22429 for (i = 0; http_methods[i].name != NULL; i++) {
22430 if (i > 0) {
22431 strcat(all_methods, ", ");
22432 strcat(all_methods, http_methods[i].name);
22433 } else {
22434 strcpy(all_methods, http_methods[i].name);
22435 }
22436 }
22437 }
22438
22439#if defined(USE_LUA)
22440 lua_init_optional_libraries();
22441#endif
22442
22443#if (defined(OPENSSL_API_1_0) || defined(OPENSSL_API_1_1) \
22444 || defined(OPENSSL_API_3_0)) \
22445 && !defined(NO_SSL)
22446
22447 if (features_to_init & MG_FEATURES_SSL) {
22448 if (!mg_openssl_initialized) {
22449 char ebuf[128];
22450 if (initialize_openssl(ebuf, sizeof(ebuf))) {
22451 mg_openssl_initialized = 1;
22452 } else {
22453 (void)ebuf;
22454 DEBUG_TRACE("Initializing SSL failed: %s", ebuf);
22455 features_inited &= ~((unsigned)(MG_FEATURES_SSL));
22456 }
22457 } else {
22458 /* ssl already initialized */
22459 }
22460 }
22461
22462#endif
22463
22464 if (mg_init_library_called <= 0) {
22466 } else {
22468 }
22470
22471 return features_inited;
22472}
static void tls_dtor(void *key)
Definition civetweb.c:16321
static __inline void * mg_malloc(size_t a)
Definition civetweb.c:1474
static const struct mg_http_method_info http_methods[]
Definition civetweb.c:10813
#define DEBUG_TRACE(fmt,...)
Definition civetweb.c:242
static int initialize_openssl(char *ebuf, size_t ebuf_len)
Definition civetweb.c:16821
const char * name
Definition civetweb.c:10803

References all_methods, DEBUG_TRACE, global_lock_mutex, http_methods, initialize_openssl(), mg_check_feature(), MG_FEATURES_SSL, mg_global_lock(), mg_global_unlock(), mg_init_library_called, mg_malloc(), mg_http_method_info::name, name, NULL, pthread_mutex_attr, sTlsKey, and tls_dtor().

Referenced by legacy_init(), and run_client().

◆ mg_lock_connection()

CIVETWEB_API void mg_lock_connection ( struct mg_connection * conn)

Definition at line 13000 of file civetweb.c.

13001{
13002 if (conn) {
13003 (void)pthread_mutex_lock(&conn->mutex);
13004 }
13005}

References mg_connection::mutex.

Referenced by close_connection().

◆ mg_lock_context()

CIVETWEB_API void mg_lock_context ( struct mg_context * ctx)

◆ mg_md5()

CIVETWEB_API char * mg_md5 ( char buf[33],
... )

Definition at line 8404 of file civetweb.c.

8405{
8406 md5_byte_t hash[16];
8407 const char *p;
8408 va_list ap;
8409 md5_state_t ctx;
8410
8411 md5_init(&ctx);
8412
8413 va_start(ap, buf);
8414 while ((p = va_arg(ap, const char *)) != NULL) {
8415 md5_append(&ctx, (const md5_byte_t *)p, strlen(p));
8416 }
8417 va_end(ap);
8418
8419 md5_finish(&ctx, hash);
8420 bin2str(buf, hash, sizeof(hash));
8421 return buf;
8422}
static void bin2str(char *to, const unsigned char *p, size_t len)
Definition civetweb.c:8389

References bin2str(), and NULL.

Referenced by check_password_digest(), dav_lock_file(), mg_modify_passwords_file(), and read_auth_file().

◆ mg_modify_passwords_file()

CIVETWEB_API int mg_modify_passwords_file ( const char * passwords_file_name,
const char * realm,
const char * user,
const char * password )

Definition at line 9220 of file civetweb.c.

9224{
9225 char ha1buf[33];
9226 if ((fname == NULL) || (domain == NULL) || (user == NULL)) {
9227 return 0;
9228 }
9229 if ((pass == NULL) || (pass[0] == 0)) {
9230 return mg_modify_passwords_file_ha1(fname, domain, user, NULL);
9231 }
9232
9233 mg_md5(ha1buf, user, ":", domain, ":", pass, NULL);
9234 return mg_modify_passwords_file_ha1(fname, domain, user, ha1buf);
9235}
CIVETWEB_API char * mg_md5(char buf[33],...)
Definition civetweb.c:8404
CIVETWEB_API int mg_modify_passwords_file_ha1(const char *fname, const char *domain, const char *user, const char *ha1)
Definition civetweb.c:9057

References mg_md5(), mg_modify_passwords_file_ha1(), and NULL.

Referenced by start_civetweb().

◆ mg_modify_passwords_file_ha1()

CIVETWEB_API int mg_modify_passwords_file_ha1 ( const char * passwords_file_name,
const char * realm,
const char * user,
const char * ha1 )

Definition at line 9057 of file civetweb.c.

9061{
9062 int found = 0, i, result = 1;
9063 char line[512], u[256], d[256], h[256];
9064 struct stat st = {0};
9065 FILE *fp = NULL;
9066 char *temp_file = NULL;
9067 int temp_file_offs = 0;
9068
9069 /* Regard empty password as no password - remove user record. */
9070 if ((ha1 != NULL) && (ha1[0] == '\0')) {
9071 ha1 = NULL;
9072 }
9073
9074 /* Other arguments must not be empty */
9075 if ((fname == NULL) || (domain == NULL) || (user == NULL)) {
9076 return 0;
9077 }
9078
9079 /* Using the given file format, user name and domain must not contain
9080 * the ':' character */
9081 if (strchr(user, ':') != NULL) {
9082 return 0;
9083 }
9084 if (strchr(domain, ':') != NULL) {
9085 return 0;
9086 }
9087
9088 /* Do not allow control characters like newline in user name and domain.
9089 * Do not allow excessively long names either. */
9090 for (i = 0; ((i < 255) && (user[i] != 0)); i++) {
9091 if (iscntrl((unsigned char)user[i])) {
9092 return 0;
9093 }
9094 }
9095 if (user[i]) {
9096 return 0; /* user name too long */
9097 }
9098 for (i = 0; ((i < 255) && (domain[i] != 0)); i++) {
9099 if (iscntrl((unsigned char)domain[i])) {
9100 return 0;
9101 }
9102 }
9103 if (domain[i]) {
9104 return 0; /* domain name too long */
9105 }
9106
9107 /* The maximum length of the path to the password file is limited */
9108 if (strlen(fname) >= UTF8_PATH_MAX) {
9109 return 0;
9110 }
9111
9112 /* Check if the file exists, and get file size */
9113 if (0 == stat(fname, &st)) {
9114 int temp_buf_len;
9115 if (st.st_size > 10485760) {
9116 /* Some funster provided a >10 MB text file */
9117 return 0;
9118 }
9119
9120 /* Add enough space for one more line */
9121 temp_buf_len = (int)st.st_size + 1024;
9122
9123 /* Allocate memory (instead of using a temporary file) */
9124 temp_file = (char *)mg_calloc((size_t)temp_buf_len, 1);
9125 if (!temp_file) {
9126 /* Out of memory */
9127 return 0;
9128 }
9129
9130 /* File exists. Read it into a memory buffer. */
9131 fp = fopen(fname, "r");
9132 if (fp == NULL) {
9133 /* Cannot read file. No permission? */
9134 mg_free(temp_file);
9135 return 0;
9136 }
9137
9138 /* Read content and store in memory */
9139 while ((fgets(line, sizeof(line), fp) != NULL)
9140 && ((temp_file_offs + 600) < temp_buf_len)) {
9141 /* file format is "user:domain:hash\n" */
9142 if (sscanf(line, "%255[^:]:%255[^:]:%255s", u, d, h) != 3) {
9143 continue;
9144 }
9145 u[255] = 0;
9146 d[255] = 0;
9147 h[255] = 0;
9148
9149 if (!strcmp(u, user) && !strcmp(d, domain)) {
9150 /* Found the user: change the password hash or drop the user
9151 */
9152 if ((ha1 != NULL) && (!found)) {
9153 i = sprintf(temp_file + temp_file_offs,
9154 "%s:%s:%s\n",
9155 user,
9156 domain,
9157 ha1);
9158 if (i < 1) {
9159 fclose(fp);
9160 mg_free(temp_file);
9161 return 0;
9162 }
9163 temp_file_offs += i;
9164 }
9165 found = 1;
9166 } else {
9167 /* Copy existing user, including password hash */
9168 i = sprintf(temp_file + temp_file_offs, "%s:%s:%s\n", u, d, h);
9169 if (i < 1) {
9170 fclose(fp);
9171 mg_free(temp_file);
9172 return 0;
9173 }
9174 temp_file_offs += i;
9175 }
9176 }
9177 fclose(fp);
9178 }
9179
9180 /* Create new file */
9181 fp = fopen(fname, "w");
9182 if (!fp) {
9183 mg_free(temp_file);
9184 return 0;
9185 }
9186
9187#if !defined(_WIN32)
9188 /* On Linux & co., restrict file read/write permissions to the owner */
9189 if (fchmod(fileno(fp), S_IRUSR | S_IWUSR) != 0) {
9190 result = 0;
9191 }
9192#endif
9193
9194 if ((temp_file != NULL) && (temp_file_offs > 0)) {
9195 /* Store buffered content of old file */
9196 if (fwrite(temp_file, 1, (size_t)temp_file_offs, fp)
9197 != (size_t)temp_file_offs) {
9198 result = 0;
9199 }
9200 }
9201
9202 /* If new user, just add it */
9203 if ((ha1 != NULL) && (!found)) {
9204 if (fprintf(fp, "%s:%s:%s\n", user, domain, ha1) < 6) {
9205 result = 0;
9206 }
9207 }
9208
9209 /* All data written */
9210 if (fclose(fp) != 0) {
9211 result = 0;
9212 }
9213
9214 mg_free(temp_file);
9215 return result;
9216}
#define UTF8_PATH_MAX
Definition civetweb.c:861
static __inline void * mg_calloc(size_t a, size_t b)
Definition civetweb.c:1480
size_t fwrite(const void *, size_t, size_t, FILE *)

References fwrite(), mg_calloc(), mg_free(), NULL, and UTF8_PATH_MAX.

Referenced by mg_modify_passwords_file().

◆ mg_printf()

CIVETWEB_API int mg_printf ( struct mg_connection * ,
PRINTF_FORMAT_STRING(const char *fmt) ,
... )

◆ mg_read()

CIVETWEB_API int mg_read ( struct mg_connection * conn,
void * buf,
size_t len )

Definition at line 6614 of file civetweb.c.

6615{
6616 if (len > INT_MAX) {
6617 len = INT_MAX;
6618 }
6619
6620 if (conn == NULL) {
6621 return 0;
6622 }
6623
6624 if (conn->is_chunked) {
6625 size_t all_read = 0;
6626
6627 while (len > 0) {
6628 if (conn->is_chunked >= 3) {
6629 /* No more data left to read */
6630 return 0;
6631 }
6632 if (conn->is_chunked != 1) {
6633 /* Has error */
6634 return -1;
6635 }
6636
6637 if (conn->consumed_content != conn->content_len) {
6638 /* copy from the current chunk */
6639 int read_ret = mg_read_inner(conn, (char *)buf + all_read, len);
6640
6641 if (read_ret < 1) {
6642 /* read error */
6643 conn->is_chunked = 2;
6644 return -1;
6645 }
6646
6647 all_read += (size_t)read_ret;
6648 len -= (size_t)read_ret;
6649
6650 if (conn->consumed_content == conn->content_len) {
6651 /* Add data bytes in the current chunk have been read,
6652 * so we are expecting \r\n now. */
6653 char x[2];
6654 conn->content_len += 2;
6655 if ((mg_read_inner(conn, x, 2) != 2) || (x[0] != '\r')
6656 || (x[1] != '\n')) {
6657 /* Protocol violation */
6658 conn->is_chunked = 2;
6659 return -1;
6660 }
6661 }
6662
6663 } else {
6664 /* fetch a new chunk */
6665 size_t i;
6666 char lenbuf[64];
6667 char *end = NULL;
6668 unsigned long chunkSize = 0;
6669
6670 for (i = 0; i < (sizeof(lenbuf) - 1); i++) {
6671 conn->content_len++;
6672 if (mg_read_inner(conn, lenbuf + i, 1) != 1) {
6673 lenbuf[i] = 0;
6674 }
6675 if ((i > 0) && (lenbuf[i] == ';')) {
6676 // chunk extension --> skip chars until next CR
6677 //
6678 // RFC 2616, 3.6.1 Chunked Transfer Coding
6679 // (https://www.rfc-editor.org/rfc/rfc2616#page-25)
6680 //
6681 // chunk = chunk-size [ chunk-extension ] CRLF
6682 // chunk-data CRLF
6683 // ...
6684 // chunk-extension= *( ";" chunk-ext-name [ "="
6685 // chunk-ext-val ] )
6686 do
6687 ++conn->content_len;
6688 while (mg_read_inner(conn, lenbuf + i, 1) == 1
6689 && lenbuf[i] != '\r');
6690 }
6691 if ((i > 0) && (lenbuf[i] == '\r')
6692 && (lenbuf[i - 1] != '\r')) {
6693 continue;
6694 }
6695 if ((i > 1) && (lenbuf[i] == '\n')
6696 && (lenbuf[i - 1] == '\r')) {
6697 lenbuf[i + 1] = 0;
6698 chunkSize = strtoul(lenbuf, &end, 16);
6699 if (chunkSize == 0) {
6700 /* regular end of content */
6701 conn->is_chunked = 3;
6702 }
6703 break;
6704 }
6705 if (!isxdigit((unsigned char)lenbuf[i])) {
6706 /* illegal character for chunk length */
6707 conn->is_chunked = 2;
6708 return -1;
6709 }
6710 }
6711 if ((end == NULL) || (*end != '\r')) {
6712 /* chunksize not set correctly */
6713 conn->is_chunked = 2;
6714 return -1;
6715 }
6716 if (conn->is_chunked == 3) {
6717 /* try discarding trailer for keep-alive */
6718
6719 // We found the last chunk (length 0) including the
6720 // CRLF that terminates that chunk. Now follows a possibly
6721 // empty trailer and a final CRLF.
6722 //
6723 // see RFC 2616, 3.6.1 Chunked Transfer Coding
6724 // (https://www.rfc-editor.org/rfc/rfc2616#page-25)
6725 //
6726 // Chunked-Body = *chunk
6727 // last-chunk
6728 // trailer
6729 // CRLF
6730 // ...
6731 // last-chunk = 1*("0") [ chunk-extension ] CRLF
6732 // ...
6733 // trailer = *(entity-header CRLF)
6734
6735 int crlf_count = 2; // one CRLF already determined
6736
6737 while (crlf_count < 4 && conn->is_chunked == 3) {
6738 ++conn->content_len;
6739 if (mg_read_inner(conn, lenbuf, 1) == 1) {
6740 if ((crlf_count == 0 || crlf_count == 2)) {
6741 if (lenbuf[0] == '\r')
6742 ++crlf_count;
6743 else
6744 crlf_count = 0;
6745 } else {
6746 // previous character was a CR
6747 // --> next character must be LF
6748
6749 if (lenbuf[0] == '\n')
6750 ++crlf_count;
6751 else
6752 conn->is_chunked = 2;
6753 }
6754 } else
6755 // premature end of trailer
6756 conn->is_chunked = 2;
6757 }
6758
6759 if (conn->is_chunked == 2)
6760 return -1;
6761 else
6762 conn->is_chunked = 4;
6763
6764 break;
6765 }
6766
6767 /* append a new chunk */
6768 conn->content_len += (int64_t)chunkSize;
6769 }
6770 }
6771
6772 return (int)all_read;
6773 }
6774 return mg_read_inner(conn, buf, len);
6775}
static int mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
Definition civetweb.c:6494
int64_t content_len
Definition civetweb.c:2518
int64_t consumed_content
Definition civetweb.c:2524

References mg_connection::consumed_content, mg_connection::content_len, mg_connection::is_chunked, mg_read_inner(), and NULL.

Referenced by discard_unread_request_data(), forward_body_data(), mg_store_body(), and run_client().

◆ mg_response_header_add()

◆ mg_response_header_add_lines()

CIVETWEB_API int mg_response_header_add_lines ( struct mg_connection * conn,
const char * http1_headers )

◆ mg_response_header_send()

◆ mg_response_header_start()

◆ mg_send_chunk()

CIVETWEB_API int CIVETWEB_API int mg_send_chunk ( struct mg_connection * conn,
const char * chunk,
unsigned int chunk_len )

Definition at line 6860 of file civetweb.c.

6863{
6864 char lenbuf[16];
6865 size_t lenbuf_len;
6866 int ret;
6867 int t;
6868
6869 /* First store the length information in a text buffer. */
6870 sprintf(lenbuf, "%x\r\n", chunk_len);
6871 lenbuf_len = strlen(lenbuf);
6872
6873 /* Then send length information, chunk and terminating \r\n. */
6874 ret = mg_write(conn, lenbuf, lenbuf_len);
6875 if (ret != (int)lenbuf_len) {
6876 return -1;
6877 }
6878 t = ret;
6879
6880 ret = mg_write(conn, chunk, chunk_len);
6881 if (ret != (int)chunk_len) {
6882 return -1;
6883 }
6884 t += ret;
6885
6886 ret = mg_write(conn, "\r\n", 2);
6887 if (ret != 2) {
6888 return -1;
6889 }
6890 t += ret;
6891
6892 return t;
6893}
CIVETWEB_API int mg_write(struct mg_connection *conn, const void *buf, size_t len)
Definition civetweb.c:6779
static void chunk(LexState *ls)

References chunk(), and mg_write().

◆ mg_send_digest_access_authentication_request()

CIVETWEB_API int mg_send_digest_access_authentication_request ( struct mg_connection * conn,
const char * realm )

Definition at line 9022 of file civetweb.c.

9024{
9025 if (conn && conn->dom_ctx) {
9026 send_authorization_request(conn, realm);
9027 return 0;
9028 }
9029 return -1;
9030}
static void send_authorization_request(struct mg_connection *conn, const char *realm)
Definition civetweb.c:8974

References mg_connection::dom_ctx, and send_authorization_request().

◆ mg_send_file()

CIVETWEB_API void mg_send_file ( struct mg_connection * conn,
const char * path )

Definition at line 10510 of file civetweb.c.

10511{
10512 mg_send_mime_file2(conn, path, NULL, NULL);
10513}
CIVETWEB_API void mg_send_mime_file2(struct mg_connection *conn, const char *path, const char *mime_type, const char *additional_headers)
Definition civetweb.c:10526

References mg_send_mime_file2(), and NULL.

◆ mg_send_file_body()

CIVETWEB_API int mg_send_file_body ( struct mg_connection * conn,
const char * path )

Definition at line 10451 of file civetweb.c.

10452{
10453 struct mg_file file = STRUCT_FILE_INITIALIZER;
10454 if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, &file)) {
10455 return -1;
10456 }
10457 fclose_on_exec(&file.access, conn);
10458 send_file_data(conn, &file, 0, INT64_MAX, 0); /* send static file */
10459 (void)mg_fclose(&file.access); /* Ignore errors for readonly files */
10460 return 0; /* >= 0 for OK */
10461}
static void send_file_data(struct mg_connection *conn, struct mg_file *filep, int64_t offset, int64_t len, int no_buffering)
Definition civetweb.c:10055
static void fclose_on_exec(struct mg_file_access *filep, struct mg_connection *conn)
Definition civetweb.c:10196
#define INT64_MAX
Definition civetweb.c:513

References mg_file::access, fclose_on_exec(), INT64_MAX, mg_fclose(), mg_fopen(), MG_FOPEN_MODE_READ, send_file_data(), and STRUCT_FILE_INITIALIZER.

◆ mg_send_http_error()

CIVETWEB_API int mg_send_http_error ( struct mg_connection * conn,
int status_code,
PRINTF_FORMAT_STRING(const char *fmt) ,
... )

◆ mg_send_http_ok()

CIVETWEB_API int CIVETWEB_API int mg_send_http_ok ( struct mg_connection * conn,
const char * mime_type,
long long content_length )

Definition at line 4576 of file civetweb.c.

4579{
4580 if ((mime_type == NULL) || (*mime_type == 0)) {
4581 /* No content type defined: default to text/html */
4582 mime_type = "text/html";
4583 }
4584
4585 mg_response_header_start(conn, 200);
4588 send_cors_header(conn);
4589 mg_response_header_add(conn, "Content-Type", mime_type, -1);
4590 if (content_length < 0) {
4591 /* Size not known. Use chunked encoding (HTTP/1.x) */
4592 if (conn->protocol_type == PROTOCOL_TYPE_HTTP1) {
4593 /* Only HTTP/1.x defines "chunked" encoding, HTTP/2 does not*/
4594 mg_response_header_add(conn, "Transfer-Encoding", "chunked", -1);
4595 }
4596 } else {
4597 char len[32];
4598 int trunc = 0;
4599 mg_snprintf(conn,
4600 &trunc,
4601 len,
4602 sizeof(len),
4603 "%" UINT64_FMT,
4604 (uint64_t)content_length);
4605 if (!trunc) {
4606 /* Since 32 bytes is enough to hold any 64 bit decimal number,
4607 * !trunc is always true */
4608 mg_response_header_add(conn, "Content-Length", len, -1);
4609 }
4610 }
4612
4613 return 0;
4614}
const char * mime_type
Definition civetweb.c:8224
#define UINT64_FMT
Definition civetweb.c:927
static void send_no_cache_header(struct mg_connection *conn)
Definition civetweb.c:4056
static void send_additional_header(struct mg_connection *conn)
Definition civetweb.c:4122
static void send_cors_header(struct mg_connection *conn)
Definition civetweb.c:4149
@ PROTOCOL_TYPE_HTTP1
Definition civetweb.c:2466
CIVETWEB_API int mg_response_header_send(struct mg_connection *conn)
CIVETWEB_API int mg_response_header_add(struct mg_connection *conn, const char *header, const char *value, int value_len)
CIVETWEB_API int mg_response_header_start(struct mg_connection *conn, int status)

References mg_response_header_add(), mg_response_header_send(), mg_response_header_start(), mg_snprintf(), mime_type, NULL, mg_connection::protocol_type, PROTOCOL_TYPE_HTTP1, send_additional_header(), send_cors_header(), send_no_cache_header(), and UINT64_FMT.

◆ mg_send_http_redirect()

CIVETWEB_API int mg_send_http_redirect ( struct mg_connection * conn,
const char * target_url,
int redirect_code )

Definition at line 4618 of file civetweb.c.

4621{
4622 /* Send a 30x redirect response.
4623 *
4624 * Redirect types (status codes):
4625 *
4626 * Status | Perm/Temp | Method | Version
4627 * 301 | permanent | POST->GET undefined | HTTP/1.0
4628 * 302 | temporary | POST->GET undefined | HTTP/1.0
4629 * 303 | temporary | always use GET | HTTP/1.1
4630 * 307 | temporary | always keep method | HTTP/1.1
4631 * 308 | permanent | always keep method | HTTP/1.1
4632 */
4633
4634#if defined(MG_SEND_REDIRECT_BODY)
4635 char redirect_body[MG_BUF_LEN];
4636 size_t content_len = 0;
4637 char content_len_text[32];
4638#endif
4639
4640 /* In case redirect_code=0, use 307. */
4641 if (redirect_code == 0) {
4642 redirect_code = 307;
4643 }
4644
4645 /* In case redirect_code is none of the above, return error. */
4646 if ((redirect_code != 301) && (redirect_code != 302)
4647 && (redirect_code != 303) && (redirect_code != 307)
4648 && (redirect_code != 308)) {
4649 /* Parameter error */
4650 return -2;
4651 }
4652
4653 /* If target_url is not defined, redirect to "/". */
4654 if ((target_url == NULL) || (*target_url == 0)) {
4655 target_url = "/";
4656 }
4657
4658#if defined(MG_SEND_REDIRECT_BODY)
4659 /* TODO: condition name? */
4660
4661 /* Prepare a response body with a hyperlink.
4662 *
4663 * According to RFC2616 (and RFC1945 before):
4664 * Unless the request method was HEAD, the entity of the
4665 * response SHOULD contain a short hypertext note with a hyperlink to
4666 * the new URI(s).
4667 *
4668 * However, this response body is not useful in M2M communication.
4669 * Probably the original reason in the RFC was, clients not supporting
4670 * a 30x HTTP redirect could still show the HTML page and let the user
4671 * press the link. Since current browsers support 30x HTTP, the additional
4672 * HTML body does not seem to make sense anymore.
4673 *
4674 * The new RFC7231 (Section 6.4) does no longer recommend it ("SHOULD"),
4675 * but it only notes:
4676 * The server's response payload usually contains a short
4677 * hypertext note with a hyperlink to the new URI(s).
4678 *
4679 * Deactivated by default. If you need the 30x body, set the define.
4680 */
4682 conn,
4683 NULL /* ignore truncation */,
4684 redirect_body,
4685 sizeof(redirect_body),
4686 "<html><head>%s</head><body><a href=\"%s\">%s</a></body></html>",
4687 redirect_text,
4688 target_url,
4689 target_url);
4690 content_len = strlen(reply);
4691 sprintf(content_len_text, "%lu", (unsigned long)content_len);
4692#endif
4693
4694 /* Send all required headers */
4695 mg_response_header_start(conn, redirect_code);
4696 mg_response_header_add(conn, "Location", target_url, -1);
4697 if ((redirect_code == 301) || (redirect_code == 308)) {
4698 /* Permanent redirect */
4700 } else {
4701 /* Temporary redirect */
4703 }
4705 send_cors_header(conn);
4706#if defined(MG_SEND_REDIRECT_BODY)
4707 mg_response_header_add(conn, "Content-Type", "text/html", -1);
4708 mg_response_header_add(conn, "Content-Length", content_len_text, -1);
4709#else
4710 mg_response_header_add(conn, "Content-Length", "0", 1);
4711#endif
4713
4714#if defined(MG_SEND_REDIRECT_BODY)
4715 /* Send response body */
4716 /* ... unless it is a HEAD request */
4717 if (0 != strcmp(conn->request_info.request_method, "HEAD")) {
4718 ret = mg_write(conn, redirect_body, content_len);
4719 }
4720#endif
4721
4722 return 1;
4723}
static void send_static_cache_header(struct mg_connection *conn)
Definition civetweb.c:4074
#define MG_BUF_LEN
Definition civetweb.c:498
const char * request_method
Definition civetweb.h:151

References MG_BUF_LEN, mg_response_header_add(), mg_response_header_send(), mg_response_header_start(), mg_snprintf(), mg_write(), NULL, mg_connection::request_info, mg_request_info::request_method, send_additional_header(), send_cors_header(), send_no_cache_header(), and send_static_cache_header().

Referenced by handle_request(), and redirect_to_https_port().

◆ mg_send_mime_file()

CIVETWEB_API void mg_send_mime_file ( struct mg_connection * conn,
const char * path,
const char * mime_type )

Definition at line 10517 of file civetweb.c.

10520{
10521 mg_send_mime_file2(conn, path, mime_type, NULL);
10522}

References mg_send_mime_file2(), mime_type, and NULL.

◆ mg_send_mime_file2()

CIVETWEB_API void mg_send_mime_file2 ( struct mg_connection * conn,
const char * path,
const char * mime_type,
const char * additional_headers )

Definition at line 10526 of file civetweb.c.

10530{
10531 struct mg_file file = STRUCT_FILE_INITIALIZER;
10532
10533 if (!conn) {
10534 /* No conn */
10535 return;
10536 }
10537
10538 if (mg_stat(conn, path, &file.stat)) {
10539#if !defined(NO_CACHING)
10540 if (is_not_modified(conn, &file.stat)) {
10541 /* Send 304 "Not Modified" - this must not send any body data */
10543 } else
10544#endif /* NO_CACHING */
10545 if (file.stat.is_directory) {
10547 "yes")) {
10548 handle_directory_request(conn, path);
10549 } else {
10550 mg_send_http_error(conn,
10551 403,
10552 "%s",
10553 "Error: Directory listing denied");
10554 }
10555 } else {
10557 conn, path, &file, mime_type, additional_headers);
10558 }
10559 } else {
10560 mg_send_http_error(conn, 404, "%s", "Error: File not found");
10561 }
10562}
@ ENABLE_DIRECTORY_LISTING
Definition civetweb.c:2002
static void handle_static_file_request(struct mg_connection *conn, const char *path, struct mg_file *filep, const char *mime_type, const char *additional_headers)
Definition civetweb.c:10220
static void handle_directory_request(struct mg_connection *conn, const char *dir)
Definition civetweb.c:9942
static int mg_stat(const struct mg_connection *conn, const char *path, struct mg_file_stat *filep)
Definition civetweb.c:5650
static int is_not_modified(const struct mg_connection *conn, const struct mg_file_stat *filestat)
Definition civetweb.c:10468
CIVETWEB_API int mg_send_http_error(struct mg_connection *conn, int status, const char *fmt,...)
Definition civetweb.c:4562
static void handle_not_modified_static_file_request(struct mg_connection *conn, struct mg_file *filep)
Definition civetweb.c:10483
struct mg_file_stat stat
Definition civetweb.c:1886

References mg_domain_context::config, mg_connection::dom_ctx, ENABLE_DIRECTORY_LISTING, handle_directory_request(), handle_not_modified_static_file_request(), handle_static_file_request(), mg_file_stat::is_directory, is_not_modified(), mg_send_http_error(), mg_stat(), mg_strcasecmp(), mime_type, mg_file::stat, and STRUCT_FILE_INITIALIZER.

Referenced by mg_send_file(), and mg_send_mime_file().

◆ mg_set_auth_handler()

CIVETWEB_API void mg_set_auth_handler ( struct mg_context * ctx,
const char * uri,
mg_authorization_handler handler,
void * cbdata )

Definition at line 14538 of file civetweb.c.

14542{
14544 &(ctx->dd),
14545 uri,
14547 handler == NULL,
14548 NULL,
14549 NULL,
14550 NULL,
14551 NULL,
14552 NULL,
14553 NULL,
14554 handler,
14555 cbdata);
14556}
static void mg_set_handler_type(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx, const char *uri, int handler_type, int is_delete_request, mg_request_handler handler, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, mg_authorization_handler auth_handler, void *cbdata)
Definition civetweb.c:14280
@ AUTH_HANDLER
Definition civetweb.c:2225

References AUTH_HANDLER, mg_handler_info::cbdata, mg_context::dd, mg_handler_info::handler, mg_set_handler_type(), NULL, and mg_handler_info::uri.

◆ mg_set_request_handler()

CIVETWEB_API void mg_set_request_handler ( struct mg_context * ctx,
const char * uri,
mg_request_handler handler,
void * cbdata )

Definition at line 14466 of file civetweb.c.

14470{
14472 &(ctx->dd),
14473 uri,
14475 handler == NULL,
14476 handler,
14477 NULL,
14478 NULL,
14479 NULL,
14480 NULL,
14481 NULL,
14482 NULL,
14483 cbdata);
14484}
@ REQUEST_HANDLER
Definition civetweb.c:2225

References mg_handler_info::cbdata, mg_context::dd, mg_handler_info::handler, mg_set_handler_type(), NULL, REQUEST_HANDLER, and mg_handler_info::uri.

Referenced by start_http_server().

◆ mg_set_user_connection_data()

CIVETWEB_API void mg_set_user_connection_data ( const struct mg_connection * conn,
void * data )

Definition at line 3225 of file civetweb.c.

3226{
3227 if (const_conn != NULL) {
3228 /* Const cast, since "const struct mg_connection *" does not mean
3229 * the connection object is not modified. Here "const" is used,
3230 * to indicate mg_read/mg_write/mg_send/.. must not be called. */
3231 struct mg_connection *conn = (struct mg_connection *)const_conn;
3232 conn->request_info.conn_data = data;
3233 }
3234}

References mg_request_info::conn_data, NULL, and mg_connection::request_info.

Referenced by close_connection(), and init_connection().

◆ mg_set_websocket_handler()

CIVETWEB_API void mg_set_websocket_handler ( struct mg_context * ctx,
const char * uri,
mg_websocket_connect_handler connect_handler,
mg_websocket_ready_handler ready_handler,
mg_websocket_data_handler data_handler,
mg_websocket_close_handler close_handler,
void * cbdata )

Definition at line 14488 of file civetweb.c.

14495{
14497 uri,
14498 NULL,
14499 connect_handler,
14500 ready_handler,
14501 data_handler,
14502 close_handler,
14503 cbdata);
14504}
CIVETWEB_API void mg_set_websocket_handler_with_subprotocols(struct mg_context *ctx, const char *uri, struct mg_websocket_subprotocols *subprotocols, mg_websocket_connect_handler connect_handler, mg_websocket_ready_handler ready_handler, mg_websocket_data_handler data_handler, mg_websocket_close_handler close_handler, void *cbdata)
Definition civetweb.c:14508

References mg_handler_info::cbdata, mg_handler_info::close_handler, mg_handler_info::connect_handler, mg_handler_info::data_handler, mg_set_websocket_handler_with_subprotocols(), NULL, mg_handler_info::ready_handler, and mg_handler_info::uri.

◆ mg_set_websocket_handler_with_subprotocols()

CIVETWEB_API void mg_set_websocket_handler_with_subprotocols ( struct mg_context * ctx,
const char * uri,
struct mg_websocket_subprotocols * subprotocols,
mg_websocket_connect_handler connect_handler,
mg_websocket_ready_handler ready_handler,
mg_websocket_data_handler data_handler,
mg_websocket_close_handler close_handler,
void * cbdata )

Definition at line 14508 of file civetweb.c.

14517{
14518 int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
14519 && (data_handler == NULL)
14520 && (close_handler == NULL);
14522 &(ctx->dd),
14523 uri,
14525 is_delete_request,
14526 NULL,
14527 subprotocols,
14528 connect_handler,
14529 ready_handler,
14530 data_handler,
14531 close_handler,
14532 NULL,
14533 cbdata);
14534}
@ WEBSOCKET_HANDLER
Definition civetweb.c:2225

References mg_handler_info::cbdata, mg_handler_info::close_handler, mg_handler_info::connect_handler, mg_handler_info::data_handler, mg_context::dd, mg_set_handler_type(), NULL, mg_handler_info::ready_handler, mg_handler_info::subprotocols, mg_handler_info::uri, and WEBSOCKET_HANDLER.

Referenced by mg_set_websocket_handler().

◆ mg_split_form_urlencoded()

CIVETWEB_API int mg_split_form_urlencoded ( char * data,
struct mg_header * form_fields,
unsigned num_form_fields )

Definition at line 7157 of file civetweb.c.

7160{
7161 char *b;
7162 int i;
7163 int num = 0;
7164
7165 if (data == NULL) {
7166 /* parameter error */
7167 return -1;
7168 }
7169
7170 if ((form_fields == NULL) && (num_form_fields == 0)) {
7171 /* determine the number of expected fields */
7172 if (data[0] == 0) {
7173 return 0;
7174 }
7175 /* count number of & to return the number of key-value-pairs */
7176 num = 1;
7177 while (*data) {
7178 if (*data == '&') {
7179 num++;
7180 }
7181 data++;
7182 }
7183 return num;
7184 }
7185
7186 if ((form_fields == NULL) || ((int)num_form_fields <= 0)) {
7187 /* parameter error */
7188 return -1;
7189 }
7190
7191 for (i = 0; i < (int)num_form_fields; i++) {
7192 /* extract key-value pairs from input data */
7193 while ((*data == ' ') || (*data == '\t')) {
7194 /* skip initial spaces */
7195 data++;
7196 }
7197 if (*data == 0) {
7198 /* end of string reached */
7199 break;
7200 }
7201 form_fields[num].name = data;
7202
7203 /* find & or = */
7204 b = data;
7205 while ((*b != 0) && (*b != '&') && (*b != '=')) {
7206 b++;
7207 }
7208
7209 if (*b == 0) {
7210 /* last key without value */
7211 form_fields[num].value = NULL;
7212 } else if (*b == '&') {
7213 /* mid key without value */
7214 form_fields[num].value = NULL;
7215 } else {
7216 /* terminate string */
7217 *b = 0;
7218 /* value starts after '=' */
7219 data = b + 1;
7220 form_fields[num].value = data;
7221 }
7222
7223 /* new field is stored */
7224 num++;
7225
7226 /* find a next key */
7227 b = strchr(data, '&');
7228 if (b == 0) {
7229 /* no more data */
7230 break;
7231 } else {
7232 /* terminate value of last field at '&' */
7233 *b = 0;
7234 /* next key-value-pairs starts after '&' */
7235 data = b + 1;
7236 }
7237 }
7238
7239 /* Decode all values */
7240 for (i = 0; i < num; i++) {
7241 if (form_fields[i].name) {
7242 url_decode_in_place((char *)form_fields[i].name);
7243 }
7244 if (form_fields[i].value) {
7245 url_decode_in_place((char *)form_fields[i].value);
7246 }
7247 }
7248
7249 /* return number of fields found */
7250 return num;
7251}
static void url_decode_in_place(char *buf)
Definition civetweb.c:7080
int value
Definition lsqlite3.c:2155
const char * value
Definition civetweb.h:145
const char * name
Definition civetweb.h:144

References mg_header::name, name, NULL, url_decode_in_place(), mg_header::value, and value.

◆ mg_start()

CIVETWEB_API struct mg_context * mg_start ( const struct mg_callbacks * callbacks,
void * user_data,
const char ** configuration_options )

Definition at line 21205 of file civetweb.c.

21208{
21209 struct mg_init_data init = {0};
21210 init.callbacks = callbacks;
21211 init.user_data = user_data;
21212 init.configuration_options = options;
21213
21214 return mg_start2(&init, NULL);
21215}
CIVETWEB_API struct mg_context * mg_start2(struct mg_init_data *init, struct mg_error_data *error)
Definition civetweb.c:20464
void * user_data
Definition civetweb.h:1800
const struct mg_callbacks * callbacks
Definition civetweb.h:1799
const char ** configuration_options
Definition civetweb.h:1801

References mg_init_data::callbacks, mg_init_data::configuration_options, mg_start2(), NULL, and mg_init_data::user_data.

Referenced by start_http_server().

◆ mg_start2()

CIVETWEB_API struct mg_context * mg_start2 ( struct mg_init_data * init,
struct mg_error_data * error )

Definition at line 20464 of file civetweb.c.

20465{
20466 struct mg_context *ctx;
20467 const char *name, *value, *default_value;
20468 int idx, ok, workerthreadcount;
20469 unsigned int i;
20470 int itmp;
20471 void (*exit_callback)(const struct mg_context *ctx) = 0;
20472 const char **options =
20473 ((init != NULL) ? (init->configuration_options) : (NULL));
20474
20475 struct mg_workerTLS tls;
20476
20477 if (error != NULL) {
20479 error->code_sub = 0;
20480 if (error->text_buffer_size > 0) {
20481 *error->text = 0;
20482 }
20483 }
20484
20485 if (mg_init_library_called == 0) {
20486 /* Legacy INIT, if mg_start is called without mg_init_library.
20487 * Note: This will cause a memory leak when unloading the library.
20488 */
20489 legacy_init(options);
20490 }
20491 if (mg_init_library_called == 0) {
20492 if (error != NULL) {
20495 NULL, /* No truncation check for error buffers */
20496 error->text,
20497 error->text_buffer_size,
20498 "%s",
20499 "Library uninitialized");
20500 }
20501 return NULL;
20502 }
20503
20504 /* Allocate context and initialize reasonable general case defaults. */
20505 ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx));
20506 if (ctx == NULL) {
20507 if (error != NULL) {
20509 error->code_sub = (unsigned)sizeof(*ctx);
20511 NULL, /* No truncation check for error buffers */
20512 error->text,
20513 error->text_buffer_size,
20514 "%s",
20515 "Out of memory");
20516 }
20517 return NULL;
20518 }
20519
20520 /* Random number generator will initialize at the first call */
20521 ctx->dd.auth_nonce_mask =
20522 (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
20523
20524 /* Save started thread index to reuse in other external API calls
20525 * For the sake of thread synchronization all non-civetweb threads
20526 * can be considered as single external thread */
20528 tls.is_master = -1; /* Thread calling mg_start */
20529 tls.thread_idx = ctx->starter_thread_idx;
20530#if defined(_WIN32)
20531 tls.pthread_cond_helper_mutex = NULL;
20532#endif
20533 pthread_setspecific(sTlsKey, &tls);
20534
20535 ok = (0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr));
20536#if !defined(ALTERNATIVE_QUEUE)
20537 ok &= (0 == pthread_cond_init(&ctx->sq_empty, NULL));
20538 ok &= (0 == pthread_cond_init(&ctx->sq_full, NULL));
20539 ctx->sq_blocked = 0;
20540#endif
20541 ok &= (0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr));
20542#if defined(USE_LUA)
20543 ok &= (0 == pthread_mutex_init(&ctx->lua_bg_mutex, &pthread_mutex_attr));
20544#endif
20545 if (!ok) {
20546 unsigned error_id = (unsigned)ERRNO;
20547 const char *err_msg =
20548 "Cannot initialize thread synchronization objects";
20549 /* Fatal error - abort start. However, this situation should never
20550 * occur in practice. */
20551
20552 mg_cry_ctx_internal(ctx, "%s", err_msg);
20553 if (error != NULL) {
20555 error->code_sub = error_id;
20557 NULL, /* No truncation check for error buffers */
20558 error->text,
20559 error->text_buffer_size,
20560 "%s",
20561 err_msg);
20562 }
20563
20564 mg_free(ctx);
20565 pthread_setspecific(sTlsKey, NULL);
20566 return NULL;
20567 }
20568
20569 if ((init != NULL) && (init->callbacks != NULL)) {
20570 /* Set all callbacks except exit_context. */
20571 ctx->callbacks = *init->callbacks;
20572 exit_callback = init->callbacks->exit_context;
20573 /* The exit callback is activated once the context is successfully
20574 * created. It should not be called, if an incomplete context object
20575 * is deleted during a failed initialization. */
20576 ctx->callbacks.exit_context = 0;
20577 }
20578 ctx->user_data = ((init != NULL) ? (init->user_data) : (NULL));
20579 ctx->dd.handlers = NULL;
20580 ctx->dd.next = NULL;
20581
20582#if defined(USE_LUA)
20583 lua_ctx_init(ctx);
20584#endif
20585
20586 /* Store options */
20587 while (options && (name = *options++) != NULL) {
20588 idx = get_option_index(name);
20589 if (idx == -1) {
20590 mg_cry_ctx_internal(ctx, "Invalid option: %s", name);
20591 if (error != NULL) {
20593 error->code_sub = (unsigned)-1;
20595 NULL, /* No truncation check for error buffers */
20596 error->text,
20597 error->text_buffer_size,
20598 "Invalid configuration option: %s",
20599 name);
20600 }
20601
20602 free_context(ctx);
20603 pthread_setspecific(sTlsKey, NULL);
20604 return NULL;
20605
20606 } else if ((value = *options++) == NULL) {
20607 mg_cry_ctx_internal(ctx, "%s: option value cannot be NULL", name);
20608 if (error != NULL) {
20610 error->code_sub = (unsigned)idx;
20612 NULL, /* No truncation check for error buffers */
20613 error->text,
20614 error->text_buffer_size,
20615 "Invalid configuration option value: %s",
20616 name);
20617 }
20618
20619 free_context(ctx);
20620 pthread_setspecific(sTlsKey, NULL);
20621 return NULL;
20622 }
20623 if (ctx->dd.config[idx] != NULL) {
20624 /* A duplicate configuration option is not an error - the last
20625 * option value will be used. */
20626 mg_cry_ctx_internal(ctx, "warning: %s: duplicate option", name);
20627 mg_free(ctx->dd.config[idx]);
20628 }
20629 ctx->dd.config[idx] = mg_strdup_ctx(value, ctx);
20630 DEBUG_TRACE("[%s] -> [%s]", name, value);
20631 }
20632
20633 /* Set default value if needed */
20634 for (i = 0; config_options[i].name != NULL; i++) {
20635 default_value = config_options[i].default_value;
20636 if ((ctx->dd.config[i] == NULL) && (default_value != NULL)) {
20637 ctx->dd.config[i] = mg_strdup_ctx(default_value, ctx);
20638 }
20639 }
20640
20641 /* Request size option */
20642 itmp = atoi(ctx->dd.config[MAX_REQUEST_SIZE]);
20643 if (itmp < 1024) {
20645 "%s too small",
20647 if (error != NULL) {
20649 error->code_sub = (unsigned)MAX_REQUEST_SIZE;
20651 NULL, /* No truncation check for error buffers */
20652 error->text,
20653 error->text_buffer_size,
20654 "Invalid configuration option value: %s",
20656 }
20657
20658 free_context(ctx);
20659 pthread_setspecific(sTlsKey, NULL);
20660 return NULL;
20661 }
20662 ctx->max_request_size = (unsigned)itmp;
20663
20664 /* Queue length */
20665#if !defined(ALTERNATIVE_QUEUE)
20666 itmp = atoi(ctx->dd.config[CONNECTION_QUEUE_SIZE]);
20667 if (itmp < 1) {
20669 "%s too small",
20671 if (error != NULL) {
20673 error->code_sub = CONNECTION_QUEUE_SIZE;
20675 NULL, /* No truncation check for error buffers */
20676 error->text,
20677 error->text_buffer_size,
20678 "Invalid configuration option value: %s",
20680 }
20681
20682 free_context(ctx);
20683 pthread_setspecific(sTlsKey, NULL);
20684 return NULL;
20685 }
20686 ctx->squeue =
20687 (struct socket *)mg_calloc((unsigned int)itmp, sizeof(struct socket));
20688 if (ctx->squeue == NULL) {
20690 "Out of memory: Cannot allocate %s",
20692 if (error != NULL) {
20694 error->code_sub = (unsigned)itmp * (unsigned)sizeof(struct socket);
20696 NULL, /* No truncation check for error buffers */
20697 error->text,
20698 error->text_buffer_size,
20699 "Out of memory: Cannot allocate %s",
20701 }
20702
20703 free_context(ctx);
20704 pthread_setspecific(sTlsKey, NULL);
20705 return NULL;
20706 }
20707 ctx->sq_size = itmp;
20708#endif
20709
20710 /* Worker thread count option */
20711 workerthreadcount = atoi(ctx->dd.config[NUM_THREADS]);
20712
20713 if ((workerthreadcount > MAX_WORKER_THREADS) || (workerthreadcount <= 0)) {
20714 if (workerthreadcount <= 0) {
20715 mg_cry_ctx_internal(ctx, "%s", "Invalid number of worker threads");
20716 } else {
20717 mg_cry_ctx_internal(ctx, "%s", "Too many worker threads");
20718 }
20719 if (error != NULL) {
20721 error->code_sub = NUM_THREADS;
20723 NULL, /* No truncation check for error buffers */
20724 error->text,
20725 error->text_buffer_size,
20726 "Invalid configuration option value: %s",
20728 }
20729
20730 free_context(ctx);
20731 pthread_setspecific(sTlsKey, NULL);
20732 return NULL;
20733 }
20734
20735 /* Document root */
20736#if defined(NO_FILES)
20737 if (ctx->dd.config[DOCUMENT_ROOT] != NULL) {
20738 mg_cry_ctx_internal(ctx, "%s", "Document root must not be set");
20739 if (error != NULL) {
20741 error->code_sub = (unsigned)DOCUMENT_ROOT;
20743 NULL, /* No truncation check for error buffers */
20744 error->text,
20745 error->text_buffer_size,
20746 "Invalid configuration option value: %s",
20748 }
20749
20750 free_context(ctx);
20751 pthread_setspecific(sTlsKey, NULL);
20752 return NULL;
20753 }
20754#endif
20755
20757
20758#if defined(USE_LUA)
20759 /* If a Lua background script has been configured, start it. */
20760 ctx->lua_bg_log_available = 0;
20761 if (ctx->dd.config[LUA_BACKGROUND_SCRIPT] != NULL) {
20762 char ebuf[256];
20763 struct vec opt_vec;
20764 struct vec eq_vec;
20765 const char *sparams;
20766
20767 memset(ebuf, 0, sizeof(ebuf));
20768 pthread_mutex_lock(&ctx->lua_bg_mutex);
20769
20770 /* Create a Lua state, load all standard libraries and the mg table */
20771 lua_State *state = mg_lua_context_script_prepare(
20772 ctx->dd.config[LUA_BACKGROUND_SCRIPT], ctx, ebuf, sizeof(ebuf));
20773 if (!state) {
20775 "lua_background_script load error: %s",
20776 ebuf);
20777 if (error != NULL) {
20780 NULL, /* No truncation check for error buffers */
20781 error->text,
20782 error->text_buffer_size,
20783 "Error in script %s: %s",
20784 config_options[LUA_BACKGROUND_SCRIPT].name,
20785 ebuf);
20786 }
20787
20788 pthread_mutex_unlock(&ctx->lua_bg_mutex);
20789
20790 free_context(ctx);
20791 pthread_setspecific(sTlsKey, NULL);
20792 return NULL;
20793 }
20794
20795 /* Add a table with parameters into mg.params */
20796 sparams = ctx->dd.config[LUA_BACKGROUND_SCRIPT_PARAMS];
20797 if (sparams && sparams[0]) {
20798 lua_getglobal(state, "mg");
20799 lua_pushstring(state, "params");
20800 lua_newtable(state);
20801
20802 while ((sparams = next_option(sparams, &opt_vec, &eq_vec))
20803 != NULL) {
20804 reg_llstring(
20805 state, opt_vec.ptr, opt_vec.len, eq_vec.ptr, eq_vec.len);
20806 if (mg_strncasecmp(sparams, opt_vec.ptr, opt_vec.len) == 0)
20807 break;
20808 }
20809 lua_rawset(state, -3);
20810 lua_pop(state, 1);
20811 }
20812
20813 /* Call script */
20814 state = mg_lua_context_script_run(state,
20815 ctx->dd.config[LUA_BACKGROUND_SCRIPT],
20816 ctx,
20817 ebuf,
20818 sizeof(ebuf));
20819 if (!state) {
20821 "lua_background_script start error: %s",
20822 ebuf);
20823 if (error != NULL) {
20826 NULL, /* No truncation check for error buffers */
20827 error->text,
20828 error->text_buffer_size,
20829 "Error in script %s: %s",
20831 ebuf);
20832 }
20833 pthread_mutex_unlock(&ctx->lua_bg_mutex);
20834
20835 free_context(ctx);
20836 pthread_setspecific(sTlsKey, NULL);
20837 return NULL;
20838 }
20839
20840 /* state remains valid */
20841 ctx->lua_background_state = (void *)state;
20842 pthread_mutex_unlock(&ctx->lua_bg_mutex);
20843
20844 } else {
20845 ctx->lua_background_state = 0;
20846 }
20847#endif
20848
20849 /* Step by step initialization of ctx - depending on build options */
20850#if !defined(NO_FILESYSTEMS)
20851 if (!set_gpass_option(ctx, NULL)) {
20852 const char *err_msg = "Invalid global password file";
20853 /* Fatal error - abort start. */
20854 mg_cry_ctx_internal(ctx, "%s", err_msg);
20855
20856 if (error != NULL) {
20859 NULL, /* No truncation check for error buffers */
20860 error->text,
20861 error->text_buffer_size,
20862 "%s",
20863 err_msg);
20864 }
20865 free_context(ctx);
20866 pthread_setspecific(sTlsKey, NULL);
20867 return NULL;
20868 }
20869#endif
20870
20871#if defined(USE_MBEDTLS)
20872 if (!mg_sslctx_init(ctx, NULL)) {
20873 const char *err_msg = "Error initializing SSL context";
20874 /* Fatal error - abort start. */
20875 mg_cry_ctx_internal(ctx, "%s", err_msg);
20876
20877 if (error != NULL) {
20880 NULL, /* No truncation check for error buffers */
20881 error->text,
20882 error->text_buffer_size,
20883 "%s",
20884 err_msg);
20885 }
20886
20887 free_context(ctx);
20888 pthread_setspecific(sTlsKey, NULL);
20889 return NULL;
20890 }
20891
20892#elif !defined(NO_SSL)
20893 if (!init_ssl_ctx(ctx, NULL)) {
20894 const char *err_msg = "Error initializing SSL context";
20895 /* Fatal error - abort start. */
20896 mg_cry_ctx_internal(ctx, "%s", err_msg);
20897
20898 if (error != NULL) {
20901 NULL, /* No truncation check for error buffers */
20902 error->text,
20903 error->text_buffer_size,
20904 "%s",
20905 err_msg);
20906 }
20907
20908 free_context(ctx);
20909 pthread_setspecific(sTlsKey, NULL);
20910 return NULL;
20911 }
20912#endif
20913
20914 if (!set_ports_option(ctx)) {
20915 const char *err_msg = "Failed to setup server ports";
20916 /* Fatal error - abort start. */
20917 mg_cry_ctx_internal(ctx, "%s", err_msg);
20918
20919 if (error != NULL) {
20922 NULL, /* No truncation check for error buffers */
20923 error->text,
20924 error->text_buffer_size,
20925 "%s",
20926 err_msg);
20927 }
20928
20929 free_context(ctx);
20930 pthread_setspecific(sTlsKey, NULL);
20931 return NULL;
20932 }
20933
20934#if !defined(_WIN32) && !defined(__ZEPHYR__)
20935 if (!set_uid_option(ctx)) {
20936 const char *err_msg = "Failed to run as configured user";
20937 /* Fatal error - abort start. */
20938 mg_cry_ctx_internal(ctx, "%s", err_msg);
20939
20940 if (error != NULL) {
20943 NULL, /* No truncation check for error buffers */
20944 error->text,
20945 error->text_buffer_size,
20946 "%s",
20947 err_msg);
20948 }
20949
20950 free_context(ctx);
20951 pthread_setspecific(sTlsKey, NULL);
20952 return NULL;
20953 }
20954#endif
20955
20956 if (!set_acl_option(ctx)) {
20957 const char *err_msg = "Failed to setup access control list";
20958 /* Fatal error - abort start. */
20959 mg_cry_ctx_internal(ctx, "%s", err_msg);
20960
20961 if (error != NULL) {
20964 NULL, /* No truncation check for error buffers */
20965 error->text,
20966 error->text_buffer_size,
20967 "%s",
20968 err_msg);
20969 }
20970
20971 free_context(ctx);
20972 pthread_setspecific(sTlsKey, NULL);
20973 return NULL;
20974 }
20975
20976 ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
20977 ctx->worker_threadids = (pthread_t *)mg_calloc_ctx(ctx->cfg_worker_threads,
20978 sizeof(pthread_t),
20979 ctx);
20980
20981 if (ctx->worker_threadids == NULL) {
20982 const char *err_msg = "Not enough memory for worker thread ID array";
20983 mg_cry_ctx_internal(ctx, "%s", err_msg);
20984
20985 if (error != NULL) {
20987 error->code_sub =
20988 (unsigned)ctx->cfg_worker_threads * (unsigned)sizeof(pthread_t);
20990 NULL, /* No truncation check for error buffers */
20991 error->text,
20992 error->text_buffer_size,
20993 "%s",
20994 err_msg);
20995 }
20996
20997 free_context(ctx);
20998 pthread_setspecific(sTlsKey, NULL);
20999 return NULL;
21000 }
21001 ctx->worker_connections =
21003 sizeof(struct mg_connection),
21004 ctx);
21005 if (ctx->worker_connections == NULL) {
21006 const char *err_msg =
21007 "Not enough memory for worker thread connection array";
21008 mg_cry_ctx_internal(ctx, "%s", err_msg);
21009
21010 if (error != NULL) {
21012 error->code_sub = (unsigned)ctx->cfg_worker_threads
21013 * (unsigned)sizeof(struct mg_connection);
21015 NULL, /* No truncation check for error buffers */
21016 error->text,
21017 error->text_buffer_size,
21018 "%s",
21019 err_msg);
21020 }
21021
21022 free_context(ctx);
21023 pthread_setspecific(sTlsKey, NULL);
21024 return NULL;
21025 }
21026
21027#if defined(ALTERNATIVE_QUEUE)
21028 ctx->client_wait_events =
21029 (void **)mg_calloc_ctx(ctx->cfg_worker_threads,
21030 sizeof(ctx->client_wait_events[0]),
21031 ctx);
21032 if (ctx->client_wait_events == NULL) {
21033 const char *err_msg = "Not enough memory for worker event array";
21034 mg_cry_ctx_internal(ctx, "%s", err_msg);
21036
21037 if (error != NULL) {
21039 error->code_sub = (unsigned)ctx->cfg_worker_threads
21040 * (unsigned)sizeof(ctx->client_wait_events[0]);
21042 NULL, /* No truncation check for error buffers */
21043 error->text,
21044 error->text_buffer_size,
21045 "%s",
21046 err_msg);
21047 }
21048
21049 free_context(ctx);
21050 pthread_setspecific(sTlsKey, NULL);
21051 return NULL;
21052 }
21053
21054 ctx->client_socks =
21056 sizeof(ctx->client_socks[0]),
21057 ctx);
21058 if (ctx->client_socks == NULL) {
21059 const char *err_msg = "Not enough memory for worker socket array";
21060 mg_cry_ctx_internal(ctx, "%s", err_msg);
21061 mg_free(ctx->client_wait_events);
21063
21064 if (error != NULL) {
21066 error->code_sub = (unsigned)ctx->cfg_worker_threads
21067 * (unsigned)sizeof(ctx->client_socks[0]);
21069 NULL, /* No truncation check for error buffers */
21070 error->text,
21071 error->text_buffer_size,
21072 "%s",
21073 err_msg);
21074 }
21075
21076 free_context(ctx);
21077 pthread_setspecific(sTlsKey, NULL);
21078 return NULL;
21079 }
21080
21081 for (i = 0; (unsigned)i < ctx->cfg_worker_threads; i++) {
21082 ctx->client_wait_events[i] = event_create();
21083 if (ctx->client_wait_events[i] == 0) {
21084 const char *err_msg = "Error creating worker event %i";
21085 mg_cry_ctx_internal(ctx, err_msg, i);
21086 while (i > 0) {
21087 i--;
21088 event_destroy(ctx->client_wait_events[i]);
21089 }
21090 mg_free(ctx->client_socks);
21091 mg_free(ctx->client_wait_events);
21093
21094 if (error != NULL) {
21096 error->code_sub = (unsigned)ERRNO;
21098 NULL, /* No truncation check for error buffers */
21099 error->text,
21100 error->text_buffer_size,
21101 err_msg,
21102 i);
21103 }
21104
21105 free_context(ctx);
21106 pthread_setspecific(sTlsKey, NULL);
21107 return NULL;
21108 }
21109 }
21110#endif
21111
21112#if defined(USE_TIMERS)
21113 if (timers_init(ctx) != 0) {
21114 const char *err_msg = "Error creating timers";
21115 mg_cry_ctx_internal(ctx, "%s", err_msg);
21116
21117 if (error != NULL) {
21119 error->code_sub = (unsigned)ERRNO;
21121 NULL, /* No truncation check for error buffers */
21122 error->text,
21123 error->text_buffer_size,
21124 "%s",
21125 err_msg);
21126 }
21127
21128 free_context(ctx);
21129 pthread_setspecific(sTlsKey, NULL);
21130 return NULL;
21131 }
21132#endif
21133
21134 /* Context has been created - init user libraries */
21135 if (ctx->callbacks.init_context) {
21136 ctx->callbacks.init_context(ctx);
21137 }
21138
21139 /* From now, the context is successfully created.
21140 * When it is destroyed, the exit callback should be called. */
21141 ctx->callbacks.exit_context = exit_callback;
21142 ctx->context_type = CONTEXT_SERVER; /* server context */
21143
21144 /* Start worker threads */
21145 for (i = 0; i < ctx->cfg_worker_threads; i++) {
21146 /* worker_thread sets up the other fields */
21147 ctx->worker_connections[i].phys_ctx = ctx;
21149 &ctx->worker_connections[i],
21150 &ctx->worker_threadids[i])
21151 != 0) {
21152
21153 long error_no = (long)ERRNO;
21154
21155 /* thread was not created */
21156 if (i > 0) {
21157 /* If the second, third, ... thread cannot be created, set a
21158 * warning, but keep running. */
21160 "Cannot start worker thread %i: error %ld",
21161 i + 1,
21162 error_no);
21163
21164 /* If the server initialization should stop here, all
21165 * threads that have already been created must be stopped
21166 * first, before any free_context(ctx) call.
21167 */
21168
21169 } else {
21170 /* If the first worker thread cannot be created, stop
21171 * initialization and free the entire server context. */
21173 "Cannot create threads: error %ld",
21174 error_no);
21175
21176 if (error != NULL) {
21178 error->code_sub = (unsigned)error_no;
21180 NULL,
21181 NULL, /* No truncation check for error buffers */
21182 error->text,
21183 error->text_buffer_size,
21184 "Cannot create first worker thread: error %ld",
21185 error_no);
21186 }
21187
21188 free_context(ctx);
21189 pthread_setspecific(sTlsKey, NULL);
21190 return NULL;
21191 }
21192 break;
21193 }
21194 }
21195
21196 /* Start master (listening) thread */
21198
21199 pthread_setspecific(sTlsKey, NULL);
21200 return ctx;
21201}
@ CONNECTION_QUEUE_SIZE
Definition civetweb.c:1927
@ MAX_REQUEST_SIZE
Definition civetweb.c:1925
@ NUM_THREADS
Definition civetweb.c:1921
@ DOCUMENT_ROOT
Definition civetweb.c:1954
#define MAX_WORKER_THREADS
Definition civetweb.c:465
#define mg_cry_ctx_internal(ctx, fmt,...)
Definition civetweb.c:2586
#define mg_calloc_ctx(a, b, c)
Definition civetweb.c:1498
#define ERRNO
Definition civetweb.c:924
static int set_uid_option(struct mg_context *phys_ctx)
Definition civetweb.c:16267
static int set_gpass_option(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
Definition civetweb.c:17636
static int set_ports_option(struct mg_context *phys_ctx)
Definition civetweb.c:15736
static int mg_start_thread_with_id(mg_thread_func_t func, void *param, pthread_t *threadidptr)
Definition civetweb.c:5726
static const char * next_option(const char *list, struct vec *val, struct vec *eq_val)
Definition civetweb.c:3899
static void get_system_name(char **sysName)
Definition civetweb.c:20389
static int set_acl_option(struct mg_context *phys_ctx)
Definition civetweb.c:17662
static char * mg_strdup_ctx(const char *str, struct mg_context *ctx)
Definition civetweb.c:3062
static void * master_thread(void *thread_func_param)
Definition civetweb.c:20231
static void free_context(struct mg_context *ctx)
Definition civetweb.c:20249
static void legacy_init(const char **options)
Definition civetweb.c:20436
static FUNCTION_MAY_BE_UNUSED ptrdiff_t mg_atomic_inc(volatile ptrdiff_t *addr)
Definition civetweb.c:1121
static void * worker_thread(void *thread_func_param)
Definition civetweb.c:19937
static int init_ssl_ctx(struct mg_context *phys_ctx, struct mg_domain_context *dom_ctx)
Definition civetweb.c:17485
static volatile ptrdiff_t thread_idx_max
Definition civetweb.c:1581
static uint64_t get_random(void)
Definition civetweb.c:5909
LUA_API void lua_pushstring(lua_State *L, const char *s)
LUA_API void lua_rawset(lua_State *L, int idx)
#define lua_newtable(L)
#define lua_pop(L, n)
#define lua_getglobal(L, s)
void(* exit_context)(const struct mg_context *ctx)
Definition civetweb.h:372
void(* init_context)(const struct mg_context *ctx)
Definition civetweb.h:367
pthread_cond_t sq_empty
Definition civetweb.c:2392
struct socket * squeue
Definition civetweb.c:2387
unsigned long starter_thread_idx
Definition civetweb.c:2380
struct mg_connection * worker_connections
Definition civetweb.c:2360
char * systemName
Definition civetweb.c:2411
pthread_t masterthreadid
Definition civetweb.c:2376
pthread_mutex_t thread_mutex
Definition civetweb.c:2374
struct mg_callbacks callbacks
Definition civetweb.c:2432
pthread_cond_t sq_full
Definition civetweb.c:2391
unsigned int max_request_size
Definition civetweb.c:2401
uint64_t auth_nonce_mask
Definition civetweb.c:2276
struct mg_domain_context * next
Definition civetweb.c:2285
struct mg_handler_info * handlers
Definition civetweb.c:2272
const char * default_value
Definition civetweb.h:688
const char * name
Definition civetweb.h:686

References mg_domain_context::auth_nonce_mask, mg_context::callbacks, mg_init_data::callbacks, mg_context::cfg_worker_threads, mg_domain_context::config, config_options, mg_init_data::configuration_options, CONNECTION_QUEUE_SIZE, CONTEXT_SERVER, mg_context::context_type, mg_context::dd, DEBUG_TRACE, mg_option::default_value, DOCUMENT_ROOT, ERRNO, error(), mg_callbacks::exit_context, free_context(), get_option_index(), get_random(), get_system_name(), mg_domain_context::handlers, mg_callbacks::init_context, init_ssl_ctx(), mg_workerTLS::is_master, legacy_init(), vec::len, lua_getglobal, lua_newtable, lua_pop, lua_pushstring(), lua_rawset(), master_thread(), mg_context::masterthreadid, MAX_REQUEST_SIZE, mg_context::max_request_size, MAX_WORKER_THREADS, mg_atomic_inc(), mg_calloc(), mg_calloc_ctx, mg_cry_ctx_internal, MG_ERROR_DATA_CODE_INIT_ACL_FAILED, MG_ERROR_DATA_CODE_INIT_LIBRARY_FAILED, MG_ERROR_DATA_CODE_INIT_PORTS_FAILED, MG_ERROR_DATA_CODE_INIT_TLS_FAILED, MG_ERROR_DATA_CODE_INIT_USER_FAILED, MG_ERROR_DATA_CODE_INVALID_OPTION, MG_ERROR_DATA_CODE_INVALID_PASS_FILE, MG_ERROR_DATA_CODE_OK, MG_ERROR_DATA_CODE_OS_ERROR, MG_ERROR_DATA_CODE_OUT_OF_MEMORY, MG_ERROR_DATA_CODE_SCRIPT_ERROR, mg_free(), mg_init_library_called, mg_snprintf(), mg_start_thread_with_id(), mg_strdup_ctx(), mg_strncasecmp(), mg_option::name, name, mg_domain_context::next, next_option(), mg_context::nonce_mutex, NULL, NUM_THREADS, mg_connection::phys_ctx, pthread_mutex_attr, vec::ptr, set_acl_option(), set_gpass_option(), set_ports_option(), set_uid_option(), mg_context::sq_blocked, mg_context::sq_empty, mg_context::sq_full, mg_context::sq_size, mg_context::squeue, mg_context::starter_thread_idx, sTlsKey, mg_context::systemName, mg_workerTLS::thread_idx, thread_idx_max, mg_context::thread_mutex, mg_context::user_data, mg_init_data::user_data, value, mg_context::worker_connections, worker_thread(), and mg_context::worker_threadids.

Referenced by mg_start(), and start_civetweb().

◆ mg_start_domain()

CIVETWEB_API int mg_start_domain ( struct mg_context * ctx,
const char ** configuration_options )

Definition at line 21422 of file civetweb.c.

21423{
21424 return mg_start_domain2(ctx, options, NULL);
21425}
CIVETWEB_API int mg_start_domain2(struct mg_context *ctx, const char **options, struct mg_error_data *error)
Definition civetweb.c:21220

References mg_start_domain2(), and NULL.

Referenced by start_civetweb().

◆ mg_start_domain2()

CIVETWEB_API int mg_start_domain2 ( struct mg_context * ctx,
const char ** configuration_options,
struct mg_error_data * error )

Definition at line 21220 of file civetweb.c.

21223{
21224 const char *name;
21225 const char *value;
21226 const char *default_value;
21227 struct mg_domain_context *new_dom;
21228 struct mg_domain_context *dom;
21229 int idx, i;
21230
21231 if (error != NULL) {
21233 error->code_sub = 0;
21234 if (error->text_buffer_size > 0) {
21235 *error->text = 0;
21236 }
21237 }
21238
21239 if ((ctx == NULL) || (options == NULL)) {
21240 if (error != NULL) {
21243 NULL, /* No truncation check for error buffers */
21244 error->text,
21245 error->text_buffer_size,
21246 "%s",
21247 "Invalid parameters");
21248 }
21249 return -1;
21250 }
21251
21252 if (!STOP_FLAG_IS_ZERO(&ctx->stop_flag)) {
21253 if (error != NULL) {
21256 NULL, /* No truncation check for error buffers */
21257 error->text,
21258 error->text_buffer_size,
21259 "%s",
21260 "Server already stopped");
21261 }
21262 return -7;
21263 }
21264
21265 new_dom = (struct mg_domain_context *)
21266 mg_calloc_ctx(1, sizeof(struct mg_domain_context), ctx);
21267
21268 if (!new_dom) {
21269 /* Out of memory */
21270 if (error != NULL) {
21272 error->code_sub = (unsigned)sizeof(struct mg_domain_context);
21274 NULL, /* No truncation check for error buffers */
21275 error->text,
21276 error->text_buffer_size,
21277 "%s",
21278 "Out or memory");
21279 }
21280 return -6;
21281 }
21282
21283 /* Store options - TODO: unite duplicate code */
21284 while (options && (name = *options++) != NULL) {
21285 idx = get_option_index(name);
21286 if (idx == -1) {
21287 mg_cry_ctx_internal(ctx, "Invalid option: %s", name);
21288 if (error != NULL) {
21290 error->code_sub = (unsigned)-1;
21292 NULL, /* No truncation check for error buffers */
21293 error->text,
21294 error->text_buffer_size,
21295 "Invalid option: %s",
21296 name);
21297 }
21298 mg_free(new_dom);
21299 return -2;
21300 } else if ((value = *options++) == NULL) {
21301 mg_cry_ctx_internal(ctx, "%s: option value cannot be NULL", name);
21302 if (error != NULL) {
21304 error->code_sub = (unsigned)idx;
21306 NULL, /* No truncation check for error buffers */
21307 error->text,
21308 error->text_buffer_size,
21309 "Invalid option value: %s",
21310 name);
21311 }
21312 mg_free(new_dom);
21313 return -2;
21314 }
21315 if (new_dom->config[idx] != NULL) {
21316 /* Duplicate option: Later values overwrite earlier ones. */
21317 mg_cry_ctx_internal(ctx, "warning: %s: duplicate option", name);
21318 mg_free(new_dom->config[idx]);
21319 }
21320 new_dom->config[idx] = mg_strdup_ctx(value, ctx);
21321 DEBUG_TRACE("[%s] -> [%s]", name, value);
21322 }
21323
21324 /* Authentication domain is mandatory */
21325 /* TODO: Maybe use a new option hostname? */
21326 if (!new_dom->config[AUTHENTICATION_DOMAIN]) {
21327 mg_cry_ctx_internal(ctx, "%s", "authentication domain required");
21328 if (error != NULL) {
21330 error->code_sub = AUTHENTICATION_DOMAIN;
21332 NULL, /* No truncation check for error buffers */
21333 error->text,
21334 error->text_buffer_size,
21335 "Mandatory option %s missing",
21337 }
21338 mg_free(new_dom);
21339 return -4;
21340 }
21341
21342 /* Set default value if needed. Take the config value from
21343 * ctx as a default value. */
21344 for (i = 0; config_options[i].name != NULL; i++) {
21345 default_value = ctx->dd.config[i];
21346 if ((new_dom->config[i] == NULL) && (default_value != NULL)) {
21347 new_dom->config[i] = mg_strdup_ctx(default_value, ctx);
21348 }
21349 }
21350
21351 new_dom->handlers = NULL;
21352 new_dom->next = NULL;
21353 new_dom->nonce_count = 0;
21354 new_dom->auth_nonce_mask = get_random() ^ (get_random() << 31);
21355
21356#if defined(USE_LUA) && defined(USE_WEBSOCKET)
21357 new_dom->shared_lua_websockets = NULL;
21358#endif
21359
21360#if !defined(NO_SSL) && !defined(USE_MBEDTLS)
21361 if (!init_ssl_ctx(ctx, new_dom)) {
21362 /* Init SSL failed */
21363 if (error != NULL) {
21366 NULL, /* No truncation check for error buffers */
21367 error->text,
21368 error->text_buffer_size,
21369 "%s",
21370 "Initializing SSL context failed");
21371 }
21372 mg_free(new_dom);
21373 return -3;
21374 }
21375#endif
21376
21377 /* Add element to linked list. */
21378 mg_lock_context(ctx);
21379
21380 idx = 0;
21381 dom = &(ctx->dd);
21382 for (;;) {
21385 /* Domain collision */
21387 "domain %s already in use",
21388 new_dom->config[AUTHENTICATION_DOMAIN]);
21389 if (error != NULL) {
21392 NULL, /* No truncation check for error buffers */
21393 error->text,
21394 error->text_buffer_size,
21395 "Domain %s specified by %s is already in use",
21396 new_dom->config[AUTHENTICATION_DOMAIN],
21398 }
21399 mg_free(new_dom);
21400 mg_unlock_context(ctx);
21401 return -5;
21402 }
21403
21404 /* Count number of domains */
21405 idx++;
21406
21407 if (dom->next == NULL) {
21408 dom->next = new_dom;
21409 break;
21410 }
21411 dom = dom->next;
21412 }
21413
21414 mg_unlock_context(ctx);
21415
21416 /* Return domain number */
21417 return idx;
21418}
CIVETWEB_API void mg_lock_context(struct mg_context *ctx)
Definition civetweb.c:13018
@ AUTHENTICATION_DOMAIN
Definition civetweb.c:1999
CIVETWEB_API void mg_unlock_context(struct mg_context *ctx)
Definition civetweb.c:13027
#define STOP_FLAG_IS_ZERO(f)
Definition civetweb.c:2322
unsigned long nonce_count
Definition civetweb.c:2277

References mg_domain_context::auth_nonce_mask, AUTHENTICATION_DOMAIN, mg_domain_context::config, config_options, mg_context::dd, DEBUG_TRACE, error(), get_option_index(), get_random(), mg_domain_context::handlers, init_ssl_ctx(), mg_calloc_ctx, mg_cry_ctx_internal, MG_ERROR_DATA_CODE_DUPLICATE_DOMAIN, MG_ERROR_DATA_CODE_INIT_TLS_FAILED, MG_ERROR_DATA_CODE_INVALID_OPTION, MG_ERROR_DATA_CODE_INVALID_PARAM, MG_ERROR_DATA_CODE_MISSING_OPTION, MG_ERROR_DATA_CODE_OK, MG_ERROR_DATA_CODE_OUT_OF_MEMORY, MG_ERROR_DATA_CODE_SERVER_STOPPED, mg_free(), mg_lock_context(), mg_snprintf(), mg_strcasecmp(), mg_strdup_ctx(), mg_unlock_context(), mg_option::name, name, mg_domain_context::next, mg_domain_context::nonce_count, NULL, mg_context::stop_flag, STOP_FLAG_IS_ZERO, and value.

Referenced by mg_start_domain().

◆ mg_start_thread()

CIVETWEB_API int mg_start_thread ( mg_thread_func_t f,
void * p )

Definition at line 5700 of file civetweb.c.

5701{
5702 pthread_t thread_id;
5703 pthread_attr_t attr;
5704 int result;
5705
5706 (void)pthread_attr_init(&attr);
5707 (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
5708
5709#if defined(__ZEPHYR__)
5710 pthread_attr_setstack(&attr, &civetweb_main_stack, ZEPHYR_STACK_SIZE);
5711#elif defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
5712 /* Compile-time option to control stack size,
5713 * e.g. -DUSE_STACK_SIZE=16384 */
5714 (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
5715#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
5716
5717 result = pthread_create(&thread_id, &attr, func, param);
5718 pthread_attr_destroy(&attr);
5719
5720 return result;
5721}

◆ mg_stop()

CIVETWEB_API void mg_stop ( struct mg_context * ctx)

Definition at line 20346 of file civetweb.c.

20347{
20348 pthread_t mt;
20349 if (!ctx) {
20350 return;
20351 }
20352
20353 /* We don't use a lock here. Calling mg_stop with the same ctx from
20354 * two threads is not allowed. */
20355 mt = ctx->masterthreadid;
20356 if (mt == 0) {
20357 return;
20358 }
20359
20360 ctx->masterthreadid = 0;
20361
20362 /* Set stop flag, so all threads know they have to exit. */
20363 STOP_FLAG_ASSIGN(&ctx->stop_flag, 1);
20364
20365 /* Join timer thread */
20366#if defined(USE_TIMERS)
20367 timers_exit(ctx);
20368#endif
20369
20370 /* Wait until everything has stopped. */
20371 while (!STOP_FLAG_IS_TWO(&ctx->stop_flag)) {
20372 (void)mg_sleep(10);
20373 }
20374
20375 /* Wait to stop master thread */
20376 mg_join_thread(mt);
20377
20378 /* Close remaining Lua states */
20379#if defined(USE_LUA)
20380 lua_ctx_exit(ctx);
20381#endif
20382
20383 /* Free memory */
20384 free_context(ctx);
20385}
#define STOP_FLAG_IS_TWO(f)
Definition civetweb.c:2323
#define mg_sleep(x)
Definition civetweb.c:920

References free_context(), mg_context::masterthreadid, mg_join_thread(), mg_sleep, mg_context::stop_flag, STOP_FLAG_ASSIGN, and STOP_FLAG_IS_TWO.

Referenced by start_http_server(), and stop_civetweb().

◆ mg_store_body()

CIVETWEB_API long long mg_store_body ( struct mg_connection * conn,
const char * path )

Definition at line 10622 of file civetweb.c.

10623{
10624 char buf[MG_BUF_LEN];
10625 long long len = 0;
10626 int ret, n;
10627 struct mg_file fi;
10628
10629 if (conn->consumed_content != 0) {
10630 mg_cry_internal(conn, "%s: Contents already consumed", __func__);
10631 return -11;
10632 }
10633
10634 ret = put_dir(conn, path);
10635 if (ret < 0) {
10636 /* -1 for path too long,
10637 * -2 for path can not be created. */
10638 return ret;
10639 }
10640 if (ret != 1) {
10641 /* Return 0 means, path itself is a directory. */
10642 return 0;
10643 }
10644
10645 if (mg_fopen(conn, path, MG_FOPEN_MODE_WRITE, &fi) == 0) {
10646 return -12;
10647 }
10648
10649 ret = mg_read(conn, buf, sizeof(buf));
10650 while (ret > 0) {
10651 n = (int)fwrite(buf, 1, (size_t)ret, fi.access.fp);
10652 if (n != ret) {
10653 (void)mg_fclose(
10654 &fi.access); /* File is bad and will be removed anyway. */
10655 remove_bad_file(conn, path);
10656 return -13;
10657 }
10658 len += ret;
10659 ret = mg_read(conn, buf, sizeof(buf));
10660 }
10661
10662 /* File is open for writing. If fclose fails, there was probably an
10663 * error flushing the buffer to disk, so the file on disk might be
10664 * broken. Delete it and return an error to the caller. */
10665 if (mg_fclose(&fi.access) != 0) {
10666 remove_bad_file(conn, path);
10667 return -14;
10668 }
10669
10670 return len;
10671}
static void remove_bad_file(const struct mg_connection *conn, const char *path)
Definition civetweb.c:10609
static int put_dir(struct mg_connection *conn, const char *path)
Definition civetweb.c:10572
#define MG_FOPEN_MODE_WRITE
Definition civetweb.c:2846
CIVETWEB_API int mg_read(struct mg_connection *conn, void *buf, size_t len)
Definition civetweb.c:6614

References mg_file::access, mg_connection::consumed_content, mg_file_access::fp, fwrite(), MG_BUF_LEN, mg_cry_internal, mg_fclose(), mg_fopen(), MG_FOPEN_MODE_WRITE, mg_read(), put_dir(), and remove_bad_file().

◆ mg_strcasecmp()

◆ mg_strncasecmp()

CIVETWEB_API int mg_strncasecmp ( const char * s1,
const char * s2,
size_t len )

Definition at line 3019 of file civetweb.c.

3020{
3021 int diff = 0;
3022
3023 if (len > 0) {
3024 do {
3025 diff = lowercase(s1++) - lowercase(s2++);
3026 } while (diff == 0 && s1[-1] != '\0' && --len > 0);
3027 }
3028
3029 return diff;
3030}

References lowercase().

Referenced by get_mime_type(), get_rel_url_at_current_server(), get_uri_type(), header_has_option(), mg_get_var2(), mg_start2(), mg_strcasestr(), parse_auth_header(), and switch_domain_context().

◆ mg_unlock_connection()

CIVETWEB_API void mg_unlock_connection ( struct mg_connection * conn)

Definition at line 13009 of file civetweb.c.

13010{
13011 if (conn) {
13012 (void)pthread_mutex_unlock(&conn->mutex);
13013 }
13014}

References mg_connection::mutex.

Referenced by close_connection().

◆ mg_unlock_context()

◆ mg_url_decode()

CIVETWEB_API int mg_url_decode ( const char * src,
int src_len,
char * dst,
int dst_len,
int is_form_url_encoded )

Definition at line 7048 of file civetweb.c.

7053{
7054 int i, j, a, b;
7055#define HEXTOI(x) (isdigit(x) ? (x - '0') : (x - 'W'))
7056
7057 for (i = j = 0; (i < src_len) && (j < (dst_len - 1)); i++, j++) {
7058 if ((i < src_len - 2) && (src[i] == '%')
7059 && isxdigit((unsigned char)src[i + 1])
7060 && isxdigit((unsigned char)src[i + 2])) {
7061 a = tolower((unsigned char)src[i + 1]);
7062 b = tolower((unsigned char)src[i + 2]);
7063 dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
7064 i += 2;
7065 } else if (is_form_url_encoded && (src[i] == '+')) {
7066 dst[j] = ' ';
7067 } else {
7068 dst[j] = src[i];
7069 }
7070 }
7071
7072 dst[j] = '\0'; /* Null-terminate the destination */
7073
7074 return (i >= src_len) ? j : -1;
7075}
#define HEXTOI(x)

References HEXTOI.

Referenced by dav_move_file(), mg_get_var2(), and url_decode_in_place().

◆ mg_url_encode()

CIVETWEB_API int mg_url_encode ( const char * src,
char * dst,
size_t dst_len )

Definition at line 9581 of file civetweb.c.

9582{
9583 static const char *dont_escape = "._-$,;~()";
9584 static const char *hex = "0123456789abcdef";
9585 char *pos = dst;
9586 const char *end = dst + dst_len - 1;
9587
9588 for (; ((*src != '\0') && (pos < end)); src++, pos++) {
9589 if (isalnum((unsigned char)*src)
9590 || (strchr(dont_escape, *src) != NULL)) {
9591 *pos = *src;
9592 } else if (pos + 2 < end) {
9593 pos[0] = '%';
9594 pos[1] = hex[(unsigned char)*src >> 4];
9595 pos[2] = hex[(unsigned char)*src & 0xf];
9596 pos += 2;
9597 } else {
9598 break;
9599 }
9600 }
9601
9602 *pos = '\0';
9603 return (*src == '\0') ? (int)(pos - dst) : -1;
9604}

References NULL.

Referenced by mg_construct_local_link(), and print_dir_entry().

◆ mg_version()

CIVETWEB_API const char * mg_version ( void )

Definition at line 3514 of file civetweb.c.

3515{
3516 return CIVETWEB_VERSION;
3517}
#define CIVETWEB_VERSION
Definition civetweb.h:26

References CIVETWEB_VERSION.

Referenced by init_server_name(), mg_get_system_info(), prepare_cgi_environment(), and show_server_name().

◆ mg_websocket_client_write()

CIVETWEB_API int mg_websocket_client_write ( struct mg_connection * conn,
int opcode,
const char * data,
size_t data_len )

◆ mg_websocket_write()

CIVETWEB_API int mg_websocket_write ( struct mg_connection * conn,
int opcode,
const char * data,
size_t data_len )

◆ mg_write()

CIVETWEB_API int mg_write ( struct mg_connection * conn,
const void * buf,
size_t len )

Definition at line 6779 of file civetweb.c.

6780{
6781 time_t now;
6782 int n, total, allowed;
6783
6784 if (conn == NULL) {
6785 return 0;
6786 }
6787 if (len > INT_MAX) {
6788 return -1;
6789 }
6790
6791 /* Mark connection as "data sent" */
6792 conn->request_state = 10;
6793#if defined(USE_HTTP2)
6794 if (conn->protocol_type == PROTOCOL_TYPE_HTTP2) {
6795 http2_data_frame_head(conn, len, 0);
6796 }
6797#endif
6798
6799 if (conn->throttle > 0) {
6800 if ((now = time(NULL)) != conn->last_throttle_time) {
6801 conn->last_throttle_time = now;
6802 conn->last_throttle_bytes = 0;
6803 }
6804 allowed = conn->throttle - conn->last_throttle_bytes;
6805 if (allowed > (int)len) {
6806 allowed = (int)len;
6807 }
6808
6809 total = push_all(conn->phys_ctx,
6810 NULL,
6811 conn->client.sock,
6812 conn->ssl,
6813 (const char *)buf,
6814 allowed);
6815
6816 if (total == allowed) {
6817
6818 buf = (const char *)buf + total;
6819 conn->last_throttle_bytes += total;
6820 while ((total < (int)len)
6821 && STOP_FLAG_IS_ZERO(&conn->phys_ctx->stop_flag)) {
6822 allowed = (conn->throttle > ((int)len - total))
6823 ? (int)len - total
6824 : conn->throttle;
6825
6826 n = push_all(conn->phys_ctx,
6827 NULL,
6828 conn->client.sock,
6829 conn->ssl,
6830 (const char *)buf,
6831 allowed);
6832
6833 if (n != allowed) {
6834 break;
6835 }
6836 sleep(1);
6837 conn->last_throttle_bytes = allowed;
6838 conn->last_throttle_time = time(NULL);
6839 buf = (const char *)buf + n;
6840 total += n;
6841 }
6842 }
6843 } else {
6844 total = push_all(conn->phys_ctx,
6845 NULL,
6846 conn->client.sock,
6847 conn->ssl,
6848 (const char *)buf,
6849 (int)len);
6850 }
6851 if (total > 0) {
6852 conn->num_bytes_sent += total;
6853 }
6854 return total;
6855}
static int push_all(struct mg_context *ctx, FILE *fp, SOCKET sock, SSL *ssl, const char *buf, int len)
Definition civetweb.c:6162
@ PROTOCOL_TYPE_HTTP2
Definition civetweb.c:2468
time_t last_throttle_time
Definition civetweb.c:2563
int64_t num_bytes_sent
Definition civetweb.c:2517
struct socket client
Definition civetweb.c:2507
int last_throttle_bytes
Definition civetweb.c:2564
SOCKET sock
Definition civetweb.c:1903

References mg_connection::client, mg_connection::last_throttle_bytes, mg_connection::last_throttle_time, NULL, mg_connection::num_bytes_sent, mg_connection::phys_ctx, mg_connection::protocol_type, PROTOCOL_TYPE_HTTP2, push_all(), mg_connection::request_state, socket::sock, mg_connection::ssl, mg_context::stop_flag, STOP_FLAG_IS_ZERO, and mg_connection::throttle.

Referenced by handle_cgi_request(), mg_send_chunk(), mg_send_http_error_impl(), mg_send_http_redirect(), mg_vprintf(), send_file_data(), and send_ssi_file().