mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-12 10:13:29 +00:00
Moved to unix file format
This commit is contained in:
+460
-460
@@ -1,460 +1,460 @@
|
||||
// Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||
// Copyright (c) 2013 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// This library is dual-licensed: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation. For the terms of this
|
||||
// license, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// You are free to use this library under the terms of the GNU General
|
||||
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// Alternatively, you can license this library under a commercial
|
||||
// license, as set out in <http://cesanta.com/products.html>.
|
||||
|
||||
#if defined(_WIN32)
|
||||
#undef _UNICODE
|
||||
#define _MBCS
|
||||
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
|
||||
#endif
|
||||
#else
|
||||
#ifdef __linux__
|
||||
#define _XOPEN_SOURCE 600 // For flockfile() on Linux
|
||||
#endif
|
||||
#if !defined(_LARGEFILE_SOURCE)
|
||||
#define _LARGEFILE_SOURCE // Enable 64-bit file offsets
|
||||
#endif
|
||||
#define __STDC_FORMAT_MACROS // <inttypes.h> wants this for C++
|
||||
#define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX
|
||||
#endif
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
// conditional expression is constant: introduced by FD_SET(..)
|
||||
#pragma warning (disable : 4127)
|
||||
// non-constant aggregate initializer: issued due to missing C99 support
|
||||
#pragma warning (disable : 4204)
|
||||
#endif
|
||||
|
||||
// Disable WIN32_LEAN_AND_MEAN.
|
||||
// This makes windows.h always include winsock2.h
|
||||
#ifdef WIN32_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#if defined(__SYMBIAN32__)
|
||||
#define NO_SSL // SSL is not supported
|
||||
#define NO_CGI // CGI is not supported
|
||||
#define PATH_MAX FILENAME_MAX
|
||||
#endif // __SYMBIAN32__
|
||||
|
||||
#ifndef _WIN32_WCE // Some ANSI #includes are not available on Windows CE
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#endif // !_WIN32_WCE
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(__SYMBIAN32__) // Windows specific
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400 // To make it link in VS2005
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
#include <process.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#else // _WIN32_WCE
|
||||
#define NO_CGI // WinCE has no pipes
|
||||
|
||||
typedef long off_t;
|
||||
|
||||
#define errno GetLastError()
|
||||
#define strerror(x) _ultoa(x, (char *) _alloca(sizeof(x) *3 ), 10)
|
||||
#endif // _WIN32_WCE
|
||||
|
||||
#define MAKEUQUAD(lo, hi) ((uint64_t)(((uint32_t)(lo)) | \
|
||||
((uint64_t)((uint32_t)(hi))) << 32))
|
||||
#define RATE_DIFF 10000000 // 100 nsecs
|
||||
#define EPOCH_DIFF MAKEUQUAD(0xd53e8000, 0x019db1de)
|
||||
#define SYS2UNIX_TIME(lo, hi) \
|
||||
(time_t) ((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)
|
||||
|
||||
// Visual Studio 6 does not know __func__ or __FUNCTION__
|
||||
// The rest of MS compilers use __FUNCTION__, not C99 __func__
|
||||
// Also use _strtoui64 on modern M$ compilers
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
#define STRX(x) #x
|
||||
#define STR(x) STRX(x)
|
||||
#define __func__ __FILE__ ":" STR(__LINE__)
|
||||
#define strtoull(x, y, z) (unsigned __int64) _atoi64(x)
|
||||
#define strtoll(x, y, z) _atoi64(x)
|
||||
#else
|
||||
#define __func__ __FUNCTION__
|
||||
#define strtoull(x, y, z) _strtoui64(x, y, z)
|
||||
#define strtoll(x, y, z) _strtoi64(x, y, z)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define ERRNO GetLastError()
|
||||
#define NO_SOCKLEN_T
|
||||
#define SSL_LIB "ssleay32.dll"
|
||||
#define CRYPTO_LIB "libeay32.dll"
|
||||
#define O_NONBLOCK 0
|
||||
#if !defined(EWOULDBLOCK)
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#endif // !EWOULDBLOCK
|
||||
#define _POSIX_
|
||||
#define INT64_FMT "I64d"
|
||||
|
||||
#define WINCDECL __cdecl
|
||||
#define SHUT_WR 1
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define mg_sleep(x) Sleep(x)
|
||||
|
||||
#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
|
||||
#ifndef popen
|
||||
#define popen(x, y) _popen(x, y)
|
||||
#endif
|
||||
#ifndef pclose
|
||||
#define pclose(x) _pclose(x)
|
||||
#endif
|
||||
#define close(x) _close(x)
|
||||
#define dlsym(x,y) GetProcAddress((HINSTANCE) (x), (y))
|
||||
#define RTLD_LAZY 0
|
||||
#define fseeko(x, y, z) _lseeki64(_fileno(x), (y), (z))
|
||||
#define fdopen(x, y) _fdopen((x), (y))
|
||||
#define write(x, y, z) _write((x), (y), (unsigned) z)
|
||||
#define read(x, y, z) _read((x), (y), (unsigned) z)
|
||||
#define flockfile(x)
|
||||
#define funlockfile(x)
|
||||
#define sleep(x) Sleep((x) * 1000)
|
||||
#define rmdir(x) _rmdir(x)
|
||||
|
||||
#if !defined(va_copy)
|
||||
#define va_copy(x, y) x = y
|
||||
#endif // !va_copy MINGW #defines va_copy
|
||||
|
||||
#if !defined(fileno)
|
||||
#define fileno(x) _fileno(x)
|
||||
#endif // !fileno MINGW #defines fileno
|
||||
|
||||
typedef HANDLE pthread_mutex_t;
|
||||
typedef struct {HANDLE signal, broadcast;} pthread_cond_t;
|
||||
typedef DWORD pthread_t;
|
||||
#define pid_t HANDLE // MINGW typedefs pid_t to int. Using #define here.
|
||||
|
||||
static int pthread_mutex_lock(pthread_mutex_t *);
|
||||
static int pthread_mutex_unlock(pthread_mutex_t *);
|
||||
static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len);
|
||||
|
||||
#if defined(HAVE_STDINT)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int64 int64_t;
|
||||
#define INT64_MAX 9223372036854775807
|
||||
#endif // HAVE_STDINT
|
||||
|
||||
// POSIX dirent interface
|
||||
struct dirent {
|
||||
char d_name[PATH_MAX];
|
||||
};
|
||||
|
||||
typedef struct DIR {
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW info;
|
||||
struct dirent result;
|
||||
} DIR;
|
||||
|
||||
#ifndef HAVE_POLL
|
||||
struct pollfd {
|
||||
SOCKET fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
#define POLLIN 1
|
||||
#endif
|
||||
|
||||
|
||||
// Mark required libraries
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#endif
|
||||
|
||||
#else // UNIX specific
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/poll.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#if !defined(NO_SSL_DL) && !defined(NO_SSL)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#if defined(__MACH__)
|
||||
#define SSL_LIB "libssl.dylib"
|
||||
#define CRYPTO_LIB "libcrypto.dylib"
|
||||
#else
|
||||
#if !defined(SSL_LIB)
|
||||
#define SSL_LIB "libssl.so"
|
||||
#endif
|
||||
#if !defined(CRYPTO_LIB)
|
||||
#define CRYPTO_LIB "libcrypto.so"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif // O_BINARY
|
||||
#define closesocket(a) close(a)
|
||||
#define mg_mkdir(x, y) mkdir(x, y)
|
||||
#define mg_remove(x) remove(x)
|
||||
#define mg_sleep(x) usleep((x) * 1000)
|
||||
#define ERRNO errno
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define INT64_FMT PRId64
|
||||
typedef int SOCKET;
|
||||
#define WINCDECL
|
||||
|
||||
#endif // End of Windows and UNIX specific includes
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
#define MONGOOSE_VERSION "4.2"
|
||||
#define PASSWORDS_FILE_NAME ".htpasswd"
|
||||
#define CGI_ENVIRONMENT_SIZE 4096
|
||||
#define MAX_CGI_ENVIR_VARS 64
|
||||
#define MG_BUF_LEN 8192
|
||||
#define MAX_REQUEST_SIZE 16384
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
#undef DEBUG_TRACE
|
||||
#define DEBUG_TRACE(x)
|
||||
#else
|
||||
#if defined(DEBUG)
|
||||
#define DEBUG_TRACE(x) do { \
|
||||
flockfile(stdout); \
|
||||
printf("*** %lu.%p.%s.%d: ", \
|
||||
(unsigned long) time(NULL), (void *) pthread_self(), \
|
||||
__func__, __LINE__); \
|
||||
printf x; \
|
||||
putchar('\n'); \
|
||||
fflush(stdout); \
|
||||
funlockfile(stdout); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DEBUG_TRACE(x)
|
||||
#endif // DEBUG
|
||||
#endif // DEBUG_TRACE
|
||||
|
||||
// Darwin prior to 7.0 and Win32 do not have socklen_t
|
||||
#ifdef NO_SOCKLEN_T
|
||||
typedef int socklen_t;
|
||||
#endif // NO_SOCKLEN_T
|
||||
#define _DARWIN_UNLIMITED_SELECT
|
||||
|
||||
#define IP_ADDR_STR_LEN 50 // IPv6 hex string is 46 chars
|
||||
|
||||
#if !defined(MSG_NOSIGNAL)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(SOMAXCONN)
|
||||
#define SOMAXCONN 100
|
||||
#endif
|
||||
|
||||
#if !defined(PATH_MAX)
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
// Size of the accepted socket queue
|
||||
#if !defined(MGSQLEN)
|
||||
#define MGSQLEN 20
|
||||
#endif
|
||||
|
||||
// Extra HTTP headers to send in every static file reply
|
||||
#if !defined(EXTRA_HTTP_HEADERS)
|
||||
#define EXTRA_HTTP_HEADERS ""
|
||||
#endif
|
||||
|
||||
static const char *http_500_error = "Internal Server Error";
|
||||
|
||||
#if defined(NO_SSL_DL)
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#else
|
||||
// SSL loaded dynamically from DLL.
|
||||
// I put the prototypes here to be independent from OpenSSL source installation.
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_method_st SSL_METHOD;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
struct ssl_func {
|
||||
const char *name; // SSL function name
|
||||
void (*ptr)(void); // Function pointer
|
||||
};
|
||||
|
||||
static struct ssl_func ssl_sw[];
|
||||
|
||||
#define SSL_free (* (void (*)(SSL *)) ssl_sw[0].ptr)
|
||||
#define SSL_accept (* (int (*)(SSL *)) ssl_sw[1].ptr)
|
||||
#define SSL_connect (* (int (*)(SSL *)) ssl_sw[2].ptr)
|
||||
#define SSL_read (* (int (*)(SSL *, void *, int)) ssl_sw[3].ptr)
|
||||
#define SSL_write (* (int (*)(SSL *, const void *,int)) ssl_sw[4].ptr)
|
||||
#define SSL_get_error (* (int (*)(SSL *, int)) ssl_sw[5].ptr)
|
||||
#define SSL_set_fd (* (int (*)(SSL *, SOCKET)) ssl_sw[6].ptr)
|
||||
#define SSL_new (* (SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
|
||||
#define SSL_CTX_new (* (SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
|
||||
#define SSLv23_server_method (* (SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
|
||||
#define SSL_library_init (* (int (*)(void)) ssl_sw[10].ptr)
|
||||
#define SSL_CTX_use_PrivateKey_file (* (int (*)(SSL_CTX *, \
|
||||
const char *, int)) ssl_sw[11].ptr)
|
||||
#define SSL_CTX_use_certificate_file (* (int (*)(SSL_CTX *, \
|
||||
const char *, int)) ssl_sw[12].ptr)
|
||||
#define SSL_CTX_set_default_passwd_cb \
|
||||
(* (void (*)(SSL_CTX *, mg_event_handler_t)) ssl_sw[13].ptr)
|
||||
#define SSL_CTX_free (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)
|
||||
#define SSL_load_error_strings (* (void (*)(void)) ssl_sw[15].ptr)
|
||||
#define SSL_CTX_use_certificate_chain_file \
|
||||
(* (int (*)(SSL_CTX *, const char *)) ssl_sw[16].ptr)
|
||||
#define SSLv23_client_method (* (SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
|
||||
#define SSL_pending (* (int (*)(SSL *)) ssl_sw[18].ptr)
|
||||
#define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int)) ssl_sw[19].ptr)
|
||||
#define SSL_shutdown (* (int (*)(SSL *)) ssl_sw[20].ptr)
|
||||
|
||||
#define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr)
|
||||
#define CRYPTO_set_locking_callback \
|
||||
(* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr)
|
||||
#define CRYPTO_set_id_callback \
|
||||
(* (void (*)(unsigned long (*)(void))) crypto_sw[2].ptr)
|
||||
#define ERR_get_error (* (unsigned long (*)(void)) crypto_sw[3].ptr)
|
||||
#define ERR_error_string (* (char * (*)(unsigned long,char *)) crypto_sw[4].ptr)
|
||||
#endif // NO_SSL_DL
|
||||
|
||||
// Unified socket address. For IPv6 support, add IPv6 address structure
|
||||
// in the union u.
|
||||
union usa {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
#if defined(USE_IPV6)
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Describes a string (chunk of memory).
|
||||
struct vec {
|
||||
const char *ptr;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct file {
|
||||
int is_directory;
|
||||
time_t modification_time;
|
||||
int64_t size;
|
||||
// set to 1 if the content is gzipped
|
||||
// in which case we need a content-encoding: gzip header
|
||||
int gzipped;
|
||||
};
|
||||
#define STRUCT_FILE_INITIALIZER { 0, 0, 0, 0 }
|
||||
|
||||
// Describes listening socket, or socket which was accept()-ed by the master
|
||||
// thread and queued for future handling by the worker thread.
|
||||
struct socket {
|
||||
SOCKET sock; // Listening socket
|
||||
union usa lsa; // Local socket address
|
||||
union usa rsa; // Remote socket address
|
||||
unsigned is_ssl:1; // Is port SSL-ed
|
||||
unsigned ssl_redir:1; // Is port supposed to redirect everything to SSL port
|
||||
};
|
||||
|
||||
// NOTE(lsm): this enum shoulds be in sync with the config_options.
|
||||
enum {
|
||||
CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER,
|
||||
PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, THROTTLE,
|
||||
ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
|
||||
GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
|
||||
EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
|
||||
NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT,
|
||||
NUM_OPTIONS
|
||||
};
|
||||
|
||||
struct mg_context {
|
||||
volatile int stop_flag; // Should we stop event loop
|
||||
SSL_CTX *ssl_ctx; // SSL context
|
||||
char *config[NUM_OPTIONS]; // Mongoose configuration parameters
|
||||
mg_event_handler_t event_handler; // User-defined callback function
|
||||
void *user_data; // User-defined data
|
||||
|
||||
struct socket *listening_sockets;
|
||||
int num_listening_sockets;
|
||||
|
||||
volatile int num_threads; // Number of threads
|
||||
pthread_mutex_t mutex; // Protects (max|num)_threads
|
||||
pthread_cond_t cond; // Condvar for tracking workers terminations
|
||||
|
||||
struct socket queue[MGSQLEN]; // Accepted sockets
|
||||
volatile int sq_head; // Head of the socket queue
|
||||
volatile int sq_tail; // Tail of the socket queue
|
||||
pthread_cond_t sq_full; // Signaled when socket is produced
|
||||
pthread_cond_t sq_empty; // Signaled when socket is consumed
|
||||
};
|
||||
|
||||
struct mg_connection {
|
||||
struct mg_request_info request_info;
|
||||
struct mg_event event;
|
||||
struct mg_context *ctx;
|
||||
SSL *ssl; // SSL descriptor
|
||||
SSL_CTX *client_ssl_ctx; // SSL context for client connections
|
||||
struct socket client; // Connected client
|
||||
time_t birth_time; // Time when request was received
|
||||
int64_t num_bytes_sent; // Total bytes sent to client
|
||||
int64_t content_len; // Content-Length header value
|
||||
int64_t num_bytes_read; // Bytes read from a remote socket
|
||||
char *buf; // Buffer for received data
|
||||
char *path_info; // PATH_INFO part of the URL
|
||||
int must_close; // 1 if connection must be closed
|
||||
int buf_size; // Buffer size
|
||||
int request_len; // Size of the request + headers in a buffer
|
||||
int data_len; // Total size of data in a buffer
|
||||
int status_code; // HTTP reply status code, e.g. 200
|
||||
int throttle; // Throttling, bytes/sec. <= 0 means no throttle
|
||||
time_t last_throttle_time; // Last time throttled data was sent
|
||||
int64_t last_throttle_bytes;// Bytes sent this second
|
||||
};
|
||||
|
||||
// Directory entry
|
||||
struct de {
|
||||
struct mg_connection *conn;
|
||||
char *file_name;
|
||||
struct file file;
|
||||
};
|
||||
|
||||
// Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||
// Copyright (c) 2013 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// This library is dual-licensed: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation. For the terms of this
|
||||
// license, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// You are free to use this library under the terms of the GNU General
|
||||
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
// See the GNU General Public License for more details.
|
||||
//
|
||||
// Alternatively, you can license this library under a commercial
|
||||
// license, as set out in <http://cesanta.com/products.html>.
|
||||
|
||||
#if defined(_WIN32)
|
||||
#undef _UNICODE
|
||||
#define _MBCS
|
||||
#if !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
#define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2005
|
||||
#endif
|
||||
#else
|
||||
#ifdef __linux__
|
||||
#define _XOPEN_SOURCE 600 // For flockfile() on Linux
|
||||
#endif
|
||||
#if !defined(_LARGEFILE_SOURCE)
|
||||
#define _LARGEFILE_SOURCE // Enable 64-bit file offsets
|
||||
#endif
|
||||
#define __STDC_FORMAT_MACROS // <inttypes.h> wants this for C++
|
||||
#define __STDC_LIMIT_MACROS // C++ wants that for INT64_MAX
|
||||
#endif
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
// conditional expression is constant: introduced by FD_SET(..)
|
||||
#pragma warning (disable : 4127)
|
||||
// non-constant aggregate initializer: issued due to missing C99 support
|
||||
#pragma warning (disable : 4204)
|
||||
#endif
|
||||
|
||||
// Disable WIN32_LEAN_AND_MEAN.
|
||||
// This makes windows.h always include winsock2.h
|
||||
#ifdef WIN32_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#if defined(__SYMBIAN32__)
|
||||
#define NO_SSL // SSL is not supported
|
||||
#define NO_CGI // CGI is not supported
|
||||
#define PATH_MAX FILENAME_MAX
|
||||
#endif // __SYMBIAN32__
|
||||
|
||||
#ifndef _WIN32_WCE // Some ANSI #includes are not available on Windows CE
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#endif // !_WIN32_WCE
|
||||
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(__SYMBIAN32__) // Windows specific
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400 // To make it link in VS2005
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
#include <process.h>
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#else // _WIN32_WCE
|
||||
#define NO_CGI // WinCE has no pipes
|
||||
|
||||
typedef long off_t;
|
||||
|
||||
#define errno GetLastError()
|
||||
#define strerror(x) _ultoa(x, (char *) _alloca(sizeof(x) *3 ), 10)
|
||||
#endif // _WIN32_WCE
|
||||
|
||||
#define MAKEUQUAD(lo, hi) ((uint64_t)(((uint32_t)(lo)) | \
|
||||
((uint64_t)((uint32_t)(hi))) << 32))
|
||||
#define RATE_DIFF 10000000 // 100 nsecs
|
||||
#define EPOCH_DIFF MAKEUQUAD(0xd53e8000, 0x019db1de)
|
||||
#define SYS2UNIX_TIME(lo, hi) \
|
||||
(time_t) ((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF)
|
||||
|
||||
// Visual Studio 6 does not know __func__ or __FUNCTION__
|
||||
// The rest of MS compilers use __FUNCTION__, not C99 __func__
|
||||
// Also use _strtoui64 on modern M$ compilers
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
#define STRX(x) #x
|
||||
#define STR(x) STRX(x)
|
||||
#define __func__ __FILE__ ":" STR(__LINE__)
|
||||
#define strtoull(x, y, z) (unsigned __int64) _atoi64(x)
|
||||
#define strtoll(x, y, z) _atoi64(x)
|
||||
#else
|
||||
#define __func__ __FUNCTION__
|
||||
#define strtoull(x, y, z) _strtoui64(x, y, z)
|
||||
#define strtoll(x, y, z) _strtoi64(x, y, z)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define ERRNO GetLastError()
|
||||
#define NO_SOCKLEN_T
|
||||
#define SSL_LIB "ssleay32.dll"
|
||||
#define CRYPTO_LIB "libeay32.dll"
|
||||
#define O_NONBLOCK 0
|
||||
#if !defined(EWOULDBLOCK)
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#endif // !EWOULDBLOCK
|
||||
#define _POSIX_
|
||||
#define INT64_FMT "I64d"
|
||||
|
||||
#define WINCDECL __cdecl
|
||||
#define SHUT_WR 1
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#define mg_sleep(x) Sleep(x)
|
||||
|
||||
#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
|
||||
#ifndef popen
|
||||
#define popen(x, y) _popen(x, y)
|
||||
#endif
|
||||
#ifndef pclose
|
||||
#define pclose(x) _pclose(x)
|
||||
#endif
|
||||
#define close(x) _close(x)
|
||||
#define dlsym(x,y) GetProcAddress((HINSTANCE) (x), (y))
|
||||
#define RTLD_LAZY 0
|
||||
#define fseeko(x, y, z) _lseeki64(_fileno(x), (y), (z))
|
||||
#define fdopen(x, y) _fdopen((x), (y))
|
||||
#define write(x, y, z) _write((x), (y), (unsigned) z)
|
||||
#define read(x, y, z) _read((x), (y), (unsigned) z)
|
||||
#define flockfile(x)
|
||||
#define funlockfile(x)
|
||||
#define sleep(x) Sleep((x) * 1000)
|
||||
#define rmdir(x) _rmdir(x)
|
||||
|
||||
#if !defined(va_copy)
|
||||
#define va_copy(x, y) x = y
|
||||
#endif // !va_copy MINGW #defines va_copy
|
||||
|
||||
#if !defined(fileno)
|
||||
#define fileno(x) _fileno(x)
|
||||
#endif // !fileno MINGW #defines fileno
|
||||
|
||||
typedef HANDLE pthread_mutex_t;
|
||||
typedef struct {HANDLE signal, broadcast;} pthread_cond_t;
|
||||
typedef DWORD pthread_t;
|
||||
#define pid_t HANDLE // MINGW typedefs pid_t to int. Using #define here.
|
||||
|
||||
static int pthread_mutex_lock(pthread_mutex_t *);
|
||||
static int pthread_mutex_unlock(pthread_mutex_t *);
|
||||
static void to_unicode(const char *path, wchar_t *wbuf, size_t wbuf_len);
|
||||
|
||||
#if defined(HAVE_STDINT)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int64 int64_t;
|
||||
#define INT64_MAX 9223372036854775807
|
||||
#endif // HAVE_STDINT
|
||||
|
||||
// POSIX dirent interface
|
||||
struct dirent {
|
||||
char d_name[PATH_MAX];
|
||||
};
|
||||
|
||||
typedef struct DIR {
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAW info;
|
||||
struct dirent result;
|
||||
} DIR;
|
||||
|
||||
#ifndef HAVE_POLL
|
||||
struct pollfd {
|
||||
SOCKET fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
#define POLLIN 1
|
||||
#endif
|
||||
|
||||
|
||||
// Mark required libraries
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#endif
|
||||
|
||||
#else // UNIX specific
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/poll.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#if !defined(NO_SSL_DL) && !defined(NO_SSL)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#if defined(__MACH__)
|
||||
#define SSL_LIB "libssl.dylib"
|
||||
#define CRYPTO_LIB "libcrypto.dylib"
|
||||
#else
|
||||
#if !defined(SSL_LIB)
|
||||
#define SSL_LIB "libssl.so"
|
||||
#endif
|
||||
#if !defined(CRYPTO_LIB)
|
||||
#define CRYPTO_LIB "libcrypto.so"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif // O_BINARY
|
||||
#define closesocket(a) close(a)
|
||||
#define mg_mkdir(x, y) mkdir(x, y)
|
||||
#define mg_remove(x) remove(x)
|
||||
#define mg_sleep(x) usleep((x) * 1000)
|
||||
#define ERRNO errno
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define INT64_FMT PRId64
|
||||
typedef int SOCKET;
|
||||
#define WINCDECL
|
||||
|
||||
#endif // End of Windows and UNIX specific includes
|
||||
|
||||
#include "mongoose.h"
|
||||
|
||||
#define MONGOOSE_VERSION "4.2"
|
||||
#define PASSWORDS_FILE_NAME ".htpasswd"
|
||||
#define CGI_ENVIRONMENT_SIZE 4096
|
||||
#define MAX_CGI_ENVIR_VARS 64
|
||||
#define MG_BUF_LEN 8192
|
||||
#define MAX_REQUEST_SIZE 16384
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#ifdef DEBUG_TRACE
|
||||
#undef DEBUG_TRACE
|
||||
#define DEBUG_TRACE(x)
|
||||
#else
|
||||
#if defined(DEBUG)
|
||||
#define DEBUG_TRACE(x) do { \
|
||||
flockfile(stdout); \
|
||||
printf("*** %lu.%p.%s.%d: ", \
|
||||
(unsigned long) time(NULL), (void *) pthread_self(), \
|
||||
__func__, __LINE__); \
|
||||
printf x; \
|
||||
putchar('\n'); \
|
||||
fflush(stdout); \
|
||||
funlockfile(stdout); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DEBUG_TRACE(x)
|
||||
#endif // DEBUG
|
||||
#endif // DEBUG_TRACE
|
||||
|
||||
// Darwin prior to 7.0 and Win32 do not have socklen_t
|
||||
#ifdef NO_SOCKLEN_T
|
||||
typedef int socklen_t;
|
||||
#endif // NO_SOCKLEN_T
|
||||
#define _DARWIN_UNLIMITED_SELECT
|
||||
|
||||
#define IP_ADDR_STR_LEN 50 // IPv6 hex string is 46 chars
|
||||
|
||||
#if !defined(MSG_NOSIGNAL)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#if !defined(SOMAXCONN)
|
||||
#define SOMAXCONN 100
|
||||
#endif
|
||||
|
||||
#if !defined(PATH_MAX)
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
// Size of the accepted socket queue
|
||||
#if !defined(MGSQLEN)
|
||||
#define MGSQLEN 20
|
||||
#endif
|
||||
|
||||
// Extra HTTP headers to send in every static file reply
|
||||
#if !defined(EXTRA_HTTP_HEADERS)
|
||||
#define EXTRA_HTTP_HEADERS ""
|
||||
#endif
|
||||
|
||||
static const char *http_500_error = "Internal Server Error";
|
||||
|
||||
#if defined(NO_SSL_DL)
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#else
|
||||
// SSL loaded dynamically from DLL.
|
||||
// I put the prototypes here to be independent from OpenSSL source installation.
|
||||
typedef struct ssl_st SSL;
|
||||
typedef struct ssl_method_st SSL_METHOD;
|
||||
typedef struct ssl_ctx_st SSL_CTX;
|
||||
|
||||
struct ssl_func {
|
||||
const char *name; // SSL function name
|
||||
void (*ptr)(void); // Function pointer
|
||||
};
|
||||
|
||||
static struct ssl_func ssl_sw[];
|
||||
|
||||
#define SSL_free (* (void (*)(SSL *)) ssl_sw[0].ptr)
|
||||
#define SSL_accept (* (int (*)(SSL *)) ssl_sw[1].ptr)
|
||||
#define SSL_connect (* (int (*)(SSL *)) ssl_sw[2].ptr)
|
||||
#define SSL_read (* (int (*)(SSL *, void *, int)) ssl_sw[3].ptr)
|
||||
#define SSL_write (* (int (*)(SSL *, const void *,int)) ssl_sw[4].ptr)
|
||||
#define SSL_get_error (* (int (*)(SSL *, int)) ssl_sw[5].ptr)
|
||||
#define SSL_set_fd (* (int (*)(SSL *, SOCKET)) ssl_sw[6].ptr)
|
||||
#define SSL_new (* (SSL * (*)(SSL_CTX *)) ssl_sw[7].ptr)
|
||||
#define SSL_CTX_new (* (SSL_CTX * (*)(SSL_METHOD *)) ssl_sw[8].ptr)
|
||||
#define SSLv23_server_method (* (SSL_METHOD * (*)(void)) ssl_sw[9].ptr)
|
||||
#define SSL_library_init (* (int (*)(void)) ssl_sw[10].ptr)
|
||||
#define SSL_CTX_use_PrivateKey_file (* (int (*)(SSL_CTX *, \
|
||||
const char *, int)) ssl_sw[11].ptr)
|
||||
#define SSL_CTX_use_certificate_file (* (int (*)(SSL_CTX *, \
|
||||
const char *, int)) ssl_sw[12].ptr)
|
||||
#define SSL_CTX_set_default_passwd_cb \
|
||||
(* (void (*)(SSL_CTX *, mg_event_handler_t)) ssl_sw[13].ptr)
|
||||
#define SSL_CTX_free (* (void (*)(SSL_CTX *)) ssl_sw[14].ptr)
|
||||
#define SSL_load_error_strings (* (void (*)(void)) ssl_sw[15].ptr)
|
||||
#define SSL_CTX_use_certificate_chain_file \
|
||||
(* (int (*)(SSL_CTX *, const char *)) ssl_sw[16].ptr)
|
||||
#define SSLv23_client_method (* (SSL_METHOD * (*)(void)) ssl_sw[17].ptr)
|
||||
#define SSL_pending (* (int (*)(SSL *)) ssl_sw[18].ptr)
|
||||
#define SSL_CTX_set_verify (* (void (*)(SSL_CTX *, int, int)) ssl_sw[19].ptr)
|
||||
#define SSL_shutdown (* (int (*)(SSL *)) ssl_sw[20].ptr)
|
||||
|
||||
#define CRYPTO_num_locks (* (int (*)(void)) crypto_sw[0].ptr)
|
||||
#define CRYPTO_set_locking_callback \
|
||||
(* (void (*)(void (*)(int, int, const char *, int))) crypto_sw[1].ptr)
|
||||
#define CRYPTO_set_id_callback \
|
||||
(* (void (*)(unsigned long (*)(void))) crypto_sw[2].ptr)
|
||||
#define ERR_get_error (* (unsigned long (*)(void)) crypto_sw[3].ptr)
|
||||
#define ERR_error_string (* (char * (*)(unsigned long,char *)) crypto_sw[4].ptr)
|
||||
#endif // NO_SSL_DL
|
||||
|
||||
// Unified socket address. For IPv6 support, add IPv6 address structure
|
||||
// in the union u.
|
||||
union usa {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
#if defined(USE_IPV6)
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Describes a string (chunk of memory).
|
||||
struct vec {
|
||||
const char *ptr;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
struct file {
|
||||
int is_directory;
|
||||
time_t modification_time;
|
||||
int64_t size;
|
||||
// set to 1 if the content is gzipped
|
||||
// in which case we need a content-encoding: gzip header
|
||||
int gzipped;
|
||||
};
|
||||
#define STRUCT_FILE_INITIALIZER { 0, 0, 0, 0 }
|
||||
|
||||
// Describes listening socket, or socket which was accept()-ed by the master
|
||||
// thread and queued for future handling by the worker thread.
|
||||
struct socket {
|
||||
SOCKET sock; // Listening socket
|
||||
union usa lsa; // Local socket address
|
||||
union usa rsa; // Remote socket address
|
||||
unsigned is_ssl:1; // Is port SSL-ed
|
||||
unsigned ssl_redir:1; // Is port supposed to redirect everything to SSL port
|
||||
};
|
||||
|
||||
// NOTE(lsm): this enum shoulds be in sync with the config_options.
|
||||
enum {
|
||||
CGI_EXTENSIONS, CGI_ENVIRONMENT, PUT_DELETE_PASSWORDS_FILE, CGI_INTERPRETER,
|
||||
PROTECT_URI, AUTHENTICATION_DOMAIN, SSI_EXTENSIONS, THROTTLE,
|
||||
ACCESS_LOG_FILE, ENABLE_DIRECTORY_LISTING, ERROR_LOG_FILE,
|
||||
GLOBAL_PASSWORDS_FILE, INDEX_FILES, ENABLE_KEEP_ALIVE, ACCESS_CONTROL_LIST,
|
||||
EXTRA_MIME_TYPES, LISTENING_PORTS, DOCUMENT_ROOT, SSL_CERTIFICATE,
|
||||
NUM_THREADS, RUN_AS_USER, REWRITE, HIDE_FILES, REQUEST_TIMEOUT,
|
||||
NUM_OPTIONS
|
||||
};
|
||||
|
||||
struct mg_context {
|
||||
volatile int stop_flag; // Should we stop event loop
|
||||
SSL_CTX *ssl_ctx; // SSL context
|
||||
char *config[NUM_OPTIONS]; // Mongoose configuration parameters
|
||||
mg_event_handler_t event_handler; // User-defined callback function
|
||||
void *user_data; // User-defined data
|
||||
|
||||
struct socket *listening_sockets;
|
||||
int num_listening_sockets;
|
||||
|
||||
volatile int num_threads; // Number of threads
|
||||
pthread_mutex_t mutex; // Protects (max|num)_threads
|
||||
pthread_cond_t cond; // Condvar for tracking workers terminations
|
||||
|
||||
struct socket queue[MGSQLEN]; // Accepted sockets
|
||||
volatile int sq_head; // Head of the socket queue
|
||||
volatile int sq_tail; // Tail of the socket queue
|
||||
pthread_cond_t sq_full; // Signaled when socket is produced
|
||||
pthread_cond_t sq_empty; // Signaled when socket is consumed
|
||||
};
|
||||
|
||||
struct mg_connection {
|
||||
struct mg_request_info request_info;
|
||||
struct mg_event event;
|
||||
struct mg_context *ctx;
|
||||
SSL *ssl; // SSL descriptor
|
||||
SSL_CTX *client_ssl_ctx; // SSL context for client connections
|
||||
struct socket client; // Connected client
|
||||
time_t birth_time; // Time when request was received
|
||||
int64_t num_bytes_sent; // Total bytes sent to client
|
||||
int64_t content_len; // Content-Length header value
|
||||
int64_t num_bytes_read; // Bytes read from a remote socket
|
||||
char *buf; // Buffer for received data
|
||||
char *path_info; // PATH_INFO part of the URL
|
||||
int must_close; // 1 if connection must be closed
|
||||
int buf_size; // Buffer size
|
||||
int request_len; // Size of the request + headers in a buffer
|
||||
int data_len; // Total size of data in a buffer
|
||||
int status_code; // HTTP reply status code, e.g. 200
|
||||
int throttle; // Throttling, bytes/sec. <= 0 means no throttle
|
||||
time_t last_throttle_time; // Last time throttled data was sent
|
||||
int64_t last_throttle_bytes;// Bytes sent this second
|
||||
};
|
||||
|
||||
// Directory entry
|
||||
struct de {
|
||||
struct mg_connection *conn;
|
||||
char *file_name;
|
||||
struct file file;
|
||||
};
|
||||
|
||||
|
||||
+4689
-4689
File diff suppressed because it is too large
Load Diff
+5148
-5148
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user