mirror of
https://github.com/lammertb/libhttp.git
synced 2025-09-04 12:42:09 +03:00
Set autoformat options and autoformat all source files
This commit is contained in:
@@ -1,3 +1,14 @@
|
|||||||
BasedOnStyle: LLVM
|
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
IndentWidth: 4
|
|
||||||
Language: Cpp
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: ForIndentation
|
||||||
|
ColumnLimit: 80
|
||||||
|
|
||||||
|
Language: Cpp
|
||||||
|
|
||||||
|
AccessModifierOffset: 2
|
||||||
|
AlignAfterOpenBracket: true
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
@@ -21,8 +21,8 @@ class CivetServer;
|
|||||||
* Exception class for thrown exceptions within the CivetHandler object.
|
* Exception class for thrown exceptions within the CivetHandler object.
|
||||||
*/
|
*/
|
||||||
class CIVETWEB_API CivetException : public std::runtime_error {
|
class CIVETWEB_API CivetException : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
CivetException(const std::string &msg) : std::runtime_error(msg) {}
|
CivetException(const std::string &msg) : std::runtime_error(msg) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,56 +30,56 @@ class CIVETWEB_API CivetException : public std::runtime_error {
|
|||||||
* must be reentrant.
|
* must be reentrant.
|
||||||
*/
|
*/
|
||||||
class CIVETWEB_API CivetHandler {
|
class CIVETWEB_API CivetHandler {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
*/
|
*/
|
||||||
virtual ~CivetHandler() {}
|
virtual ~CivetHandler() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback method for GET request.
|
* Callback method for GET request.
|
||||||
*
|
*
|
||||||
* @param server - the calling server
|
* @param server - the calling server
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @returns true if implemented, false otherwise
|
* @returns true if implemented, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool handleGet(CivetServer *server, struct mg_connection *conn);
|
virtual bool handleGet(CivetServer *server, struct mg_connection *conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback method for POST request.
|
* Callback method for POST request.
|
||||||
*
|
*
|
||||||
* @param server - the calling server
|
* @param server - the calling server
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @returns true if implemented, false otherwise
|
* @returns true if implemented, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool handlePost(CivetServer *server, struct mg_connection *conn);
|
virtual bool handlePost(CivetServer *server, struct mg_connection *conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback method for PUT request.
|
* Callback method for PUT request.
|
||||||
*
|
*
|
||||||
* @param server - the calling server
|
* @param server - the calling server
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @returns true if implemented, false otherwise
|
* @returns true if implemented, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool handlePut(CivetServer *server, struct mg_connection *conn);
|
virtual bool handlePut(CivetServer *server, struct mg_connection *conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback method for DELETE request.
|
* Callback method for DELETE request.
|
||||||
*
|
*
|
||||||
* @param server - the calling server
|
* @param server - the calling server
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @returns true if implemented, false otherwise
|
* @returns true if implemented, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool handleDelete(CivetServer *server, struct mg_connection *conn);
|
virtual bool handleDelete(CivetServer *server, struct mg_connection *conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback method for OPTIONS request.
|
* Callback method for OPTIONS request.
|
||||||
*
|
*
|
||||||
* @param server - the calling server
|
* @param server - the calling server
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @returns true if implemented, false otherwise
|
* @returns true if implemented, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool handleOptions(CivetServer *server, struct mg_connection *conn);
|
virtual bool handleOptions(CivetServer *server, struct mg_connection *conn);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,277 +88,277 @@ class CIVETWEB_API CivetHandler {
|
|||||||
* Basic class for embedded web server. This has an URL mapping built-in.
|
* Basic class for embedded web server. This has an URL mapping built-in.
|
||||||
*/
|
*/
|
||||||
class CIVETWEB_API CivetServer {
|
class CIVETWEB_API CivetServer {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* This automatically starts the sever.
|
* This automatically starts the sever.
|
||||||
* It is good practice to call getContext() after this in case there
|
* It is good practice to call getContext() after this in case there
|
||||||
* were errors starting the server.
|
* were errors starting the server.
|
||||||
*
|
*
|
||||||
* @param options - the web server options.
|
* @param options - the web server options.
|
||||||
* @param callbacks - optional web server callback methods.
|
* @param callbacks - optional web server callback methods.
|
||||||
*
|
*
|
||||||
* @throws CivetException
|
* @throws CivetException
|
||||||
*/
|
*/
|
||||||
CivetServer(const char **options, const struct mg_callbacks *callbacks = 0);
|
CivetServer(const char **options, const struct mg_callbacks *callbacks = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
*/
|
*/
|
||||||
virtual ~CivetServer();
|
virtual ~CivetServer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* close()
|
* close()
|
||||||
*
|
*
|
||||||
* Stops server and frees resources.
|
* Stops server and frees resources.
|
||||||
*/
|
*/
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getContext()
|
* getContext()
|
||||||
*
|
*
|
||||||
* @return the context or 0 if not running.
|
* @return the context or 0 if not running.
|
||||||
*/
|
*/
|
||||||
const struct mg_context *getContext() const { return context; }
|
const struct mg_context *getContext() const { return context; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* addHandler(const std::string &, CivetHandler *)
|
* addHandler(const std::string &, CivetHandler *)
|
||||||
*
|
*
|
||||||
* Adds a URI handler. If there is existing URI handler, it will
|
* Adds a URI handler. If there is existing URI handler, it will
|
||||||
* be replaced with this one.
|
* be replaced with this one.
|
||||||
*
|
*
|
||||||
* URI's are ordered and prefix (REST) URI's are supported.
|
* URI's are ordered and prefix (REST) URI's are supported.
|
||||||
*
|
*
|
||||||
* @param uri - URI to match.
|
* @param uri - URI to match.
|
||||||
* @param handler - handler instance to use.
|
* @param handler - handler instance to use.
|
||||||
*/
|
*/
|
||||||
void addHandler(const std::string &uri, CivetHandler *handler);
|
void addHandler(const std::string &uri, CivetHandler *handler);
|
||||||
|
|
||||||
void addHandler(const std::string &uri, CivetHandler &handler) {
|
void addHandler(const std::string &uri, CivetHandler &handler) {
|
||||||
addHandler(uri, &handler);
|
addHandler(uri, &handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removeHandler(const std::string &)
|
* removeHandler(const std::string &)
|
||||||
*
|
*
|
||||||
* Removes a handler.
|
* Removes a handler.
|
||||||
*
|
*
|
||||||
* @param uri - the exact URL used in addHandler().
|
* @param uri - the exact URL used in addHandler().
|
||||||
*/
|
*/
|
||||||
void removeHandler(const std::string &uri);
|
void removeHandler(const std::string &uri);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getListeningPorts()
|
* getListeningPorts()
|
||||||
*
|
*
|
||||||
* Returns a list of ports that are listening
|
* Returns a list of ports that are listening
|
||||||
*
|
*
|
||||||
* @return A vector of ports
|
* @return A vector of ports
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::vector<int> getListeningPorts();
|
std::vector<int> getListeningPorts();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getCookie(struct mg_connection *conn, const std::string &cookieName,
|
* getCookie(struct mg_connection *conn, const std::string &cookieName,
|
||||||
*std::string &cookieValue)
|
*std::string &cookieValue)
|
||||||
*
|
*
|
||||||
* Puts the cookie value string that matches the cookie name in the
|
* Puts the cookie value string that matches the cookie name in the
|
||||||
*cookieValue destinaton string.
|
*cookieValue destinaton string.
|
||||||
*
|
*
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @param cookieName - cookie name to get the value from
|
* @param cookieName - cookie name to get the value from
|
||||||
* @param cookieValue - cookie value is returned using thiis reference
|
* @param cookieValue - cookie value is returned using thiis reference
|
||||||
* @returns the size of the cookie value string read.
|
* @returns the size of the cookie value string read.
|
||||||
*/
|
*/
|
||||||
static int getCookie(struct mg_connection *conn,
|
static int getCookie(struct mg_connection *conn,
|
||||||
const std::string &cookieName,
|
const std::string &cookieName,
|
||||||
std::string &cookieValue);
|
std::string &cookieValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getHeader(struct mg_connection *conn, const std::string &headerName)
|
* getHeader(struct mg_connection *conn, const std::string &headerName)
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @param headerName - header name to get the value from
|
* @param headerName - header name to get the value from
|
||||||
* @returns a char array whcih contains the header value as string
|
* @returns a char array whcih contains the header value as string
|
||||||
*/
|
*/
|
||||||
static const char *getHeader(struct mg_connection *conn,
|
static const char *getHeader(struct mg_connection *conn,
|
||||||
const std::string &headerName);
|
const std::string &headerName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getParam(struct mg_connection *conn, const char *, std::string &, size_t)
|
* getParam(struct mg_connection *conn, const char *, std::string &, size_t)
|
||||||
*
|
*
|
||||||
* Returns a query paramter contained in the supplied buffer. The
|
* Returns a query paramter contained in the supplied buffer. The
|
||||||
* occurance value is a zero-based index of a particular key name. This
|
* occurance value is a zero-based index of a particular key name. This
|
||||||
* should not be confused with the index over all of the keys. Note that
|
* should not be confused with the index over all of the keys. Note that
|
||||||
*this
|
*this
|
||||||
* function assumes that parameters are sent as text in http query string
|
* function assumes that parameters are sent as text in http query string
|
||||||
* format, which is the default for web forms. This function will work for
|
* format, which is the default for web forms. This function will work for
|
||||||
* html forms with method="GET" and method="POST" attributes. In other
|
* html forms with method="GET" and method="POST" attributes. In other
|
||||||
*cases,
|
*cases,
|
||||||
* you may use a getParam version that directly takes the data instead of
|
* you may use a getParam version that directly takes the data instead of
|
||||||
*the
|
*the
|
||||||
* connection as a first argument.
|
* connection as a first argument.
|
||||||
*
|
*
|
||||||
* @param conn - parameters are read from the data sent through this
|
* @param conn - parameters are read from the data sent through this
|
||||||
*connection
|
*connection
|
||||||
* @param name - the key to search for
|
* @param name - the key to search for
|
||||||
* @param dst - the destination string
|
* @param dst - the destination string
|
||||||
* @param occurrence - the occurrence of the selected name in the query (0
|
* @param occurrence - the occurrence of the selected name in the query (0
|
||||||
*based).
|
*based).
|
||||||
* @return true if key was found
|
* @return true if key was found
|
||||||
*/
|
*/
|
||||||
static bool getParam(struct mg_connection *conn, const char *name,
|
static bool getParam(struct mg_connection *conn, const char *name,
|
||||||
std::string &dst, size_t occurrence = 0);
|
std::string &dst, size_t occurrence = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getParam(const std::string &, const char *, std::string &, size_t)
|
* getParam(const std::string &, const char *, std::string &, size_t)
|
||||||
*
|
*
|
||||||
* Returns a query paramter contained in the supplied buffer. The
|
* Returns a query paramter contained in the supplied buffer. The
|
||||||
* occurance value is a zero-based index of a particular key name. This
|
* occurance value is a zero-based index of a particular key name. This
|
||||||
* should not be confused with the index over all of the keys.
|
* should not be confused with the index over all of the keys.
|
||||||
*
|
*
|
||||||
* @param data - the query string (text)
|
* @param data - the query string (text)
|
||||||
* @param name - the key to search for
|
* @param name - the key to search for
|
||||||
* @param dst - the destination string
|
* @param dst - the destination string
|
||||||
* @param occurrence - the occurrence of the selected name in the query (0
|
* @param occurrence - the occurrence of the selected name in the query (0
|
||||||
*based).
|
*based).
|
||||||
* @return true if key was found
|
* @return true if key was found
|
||||||
*/
|
*/
|
||||||
static bool getParam(const std::string &data, const char *name,
|
static bool getParam(const std::string &data, const char *name,
|
||||||
std::string &dst, size_t occurrence = 0) {
|
std::string &dst, size_t occurrence = 0) {
|
||||||
return getParam(data.c_str(), data.length(), name, dst, occurrence);
|
return getParam(data.c_str(), data.length(), name, dst, occurrence);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getParam(const char *, size_t, const char *, std::string &, size_t)
|
* getParam(const char *, size_t, const char *, std::string &, size_t)
|
||||||
*
|
*
|
||||||
* Returns a query paramter contained in the supplied buffer. The
|
* Returns a query paramter contained in the supplied buffer. The
|
||||||
* occurance value is a zero-based index of a particular key name. This
|
* occurance value is a zero-based index of a particular key name. This
|
||||||
* should not be confused with the index over all of the keys.
|
* should not be confused with the index over all of the keys.
|
||||||
*
|
*
|
||||||
* @param data the - query string (text)
|
* @param data the - query string (text)
|
||||||
* @param data_len - length of the query string
|
* @param data_len - length of the query string
|
||||||
* @param name - the key to search for
|
* @param name - the key to search for
|
||||||
* @param dst - the destination string
|
* @param dst - the destination string
|
||||||
* @param occurrence - the occurrence of the selected name in the query (0
|
* @param occurrence - the occurrence of the selected name in the query (0
|
||||||
*based).
|
*based).
|
||||||
* @return true if key was found
|
* @return true if key was found
|
||||||
*/
|
*/
|
||||||
static bool getParam(const char *data, size_t data_len, const char *name,
|
static bool getParam(const char *data, size_t data_len, const char *name,
|
||||||
std::string &dst, size_t occurrence = 0);
|
std::string &dst, size_t occurrence = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* urlDecode(const std::string &, std::string &, bool)
|
* urlDecode(const std::string &, std::string &, bool)
|
||||||
*
|
*
|
||||||
* @param src - string to be decoded
|
* @param src - string to be decoded
|
||||||
* @param dst - destination string
|
* @param dst - destination string
|
||||||
* @param is_form_url_encoded - true if form url encoded
|
* @param is_form_url_encoded - true if form url encoded
|
||||||
* form-url-encoded data differs from URI encoding in a way that it
|
* form-url-encoded data differs from URI encoding in a way that it
|
||||||
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
||||||
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
||||||
*/
|
*/
|
||||||
static void urlDecode(const std::string &src, std::string &dst,
|
static void urlDecode(const std::string &src, std::string &dst,
|
||||||
bool is_form_url_encoded = true) {
|
bool is_form_url_encoded = true) {
|
||||||
urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
|
urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* urlDecode(const char *, size_t, std::string &, bool)
|
* urlDecode(const char *, size_t, std::string &, bool)
|
||||||
*
|
*
|
||||||
* @param src - buffer to be decoded
|
* @param src - buffer to be decoded
|
||||||
* @param src_len - length of buffer to be decoded
|
* @param src_len - length of buffer to be decoded
|
||||||
* @param dst - destination string
|
* @param dst - destination string
|
||||||
* @param is_form_url_encoded - true if form url encoded
|
* @param is_form_url_encoded - true if form url encoded
|
||||||
* form-url-encoded data differs from URI encoding in a way that it
|
* form-url-encoded data differs from URI encoding in a way that it
|
||||||
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
||||||
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
||||||
*/
|
*/
|
||||||
static void urlDecode(const char *src, size_t src_len, std::string &dst,
|
static void urlDecode(const char *src, size_t src_len, std::string &dst,
|
||||||
bool is_form_url_encoded = true);
|
bool is_form_url_encoded = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* urlDecode(const char *, std::string &, bool)
|
* urlDecode(const char *, std::string &, bool)
|
||||||
*
|
*
|
||||||
* @param src - buffer to be decoded (0 terminated)
|
* @param src - buffer to be decoded (0 terminated)
|
||||||
* @param dst - destination string
|
* @param dst - destination string
|
||||||
* @param is_form_url_encoded true - if form url encoded
|
* @param is_form_url_encoded true - if form url encoded
|
||||||
* form-url-encoded data differs from URI encoding in a way that it
|
* form-url-encoded data differs from URI encoding in a way that it
|
||||||
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
* uses '+' as character for space, see RFC 1866 section 8.2.1
|
||||||
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
* http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
|
||||||
*/
|
*/
|
||||||
static void urlDecode(const char *src, std::string &dst,
|
static void urlDecode(const char *src, std::string &dst,
|
||||||
bool is_form_url_encoded = true);
|
bool is_form_url_encoded = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* urlEncode(const std::string &, std::string &, bool)
|
* urlEncode(const std::string &, std::string &, bool)
|
||||||
*
|
*
|
||||||
* @param src - buffer to be encoded
|
* @param src - buffer to be encoded
|
||||||
* @param dst - destination string
|
* @param dst - destination string
|
||||||
* @param append - true if string should not be cleared before encoding.
|
* @param append - true if string should not be cleared before encoding.
|
||||||
*/
|
*/
|
||||||
static void urlEncode(const std::string &src, std::string &dst,
|
static void urlEncode(const std::string &src, std::string &dst,
|
||||||
bool append = false) {
|
bool append = false) {
|
||||||
urlEncode(src.c_str(), src.length(), dst, append);
|
urlEncode(src.c_str(), src.length(), dst, append);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* urlEncode(const char *, size_t, std::string &, bool)
|
* urlEncode(const char *, size_t, std::string &, bool)
|
||||||
*
|
*
|
||||||
* @param src - buffer to be encoded (0 terminated)
|
* @param src - buffer to be encoded (0 terminated)
|
||||||
* @param dst - destination string
|
* @param dst - destination string
|
||||||
* @param append - true if string should not be cleared before encoding.
|
* @param append - true if string should not be cleared before encoding.
|
||||||
*/
|
*/
|
||||||
static void urlEncode(const char *src, std::string &dst,
|
static void urlEncode(const char *src, std::string &dst,
|
||||||
bool append = false);
|
bool append = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* urlEncode(const char *, size_t, std::string &, bool)
|
* urlEncode(const char *, size_t, std::string &, bool)
|
||||||
*
|
*
|
||||||
* @param src - buffer to be encoded
|
* @param src - buffer to be encoded
|
||||||
* @param src_len - length of buffer to be decoded
|
* @param src_len - length of buffer to be decoded
|
||||||
* @param dst - destination string
|
* @param dst - destination string
|
||||||
* @param append - true if string should not be cleared before encoding.
|
* @param append - true if string should not be cleared before encoding.
|
||||||
*/
|
*/
|
||||||
static void urlEncode(const char *src, size_t src_len, std::string &dst,
|
static void urlEncode(const char *src, size_t src_len, std::string &dst,
|
||||||
bool append = false);
|
bool append = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
class CivetConnection {
|
class CivetConnection {
|
||||||
public:
|
public:
|
||||||
char *postData;
|
char *postData;
|
||||||
unsigned long postDataLen;
|
unsigned long postDataLen;
|
||||||
|
|
||||||
CivetConnection();
|
CivetConnection();
|
||||||
~CivetConnection();
|
~CivetConnection();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mg_context *context;
|
struct mg_context *context;
|
||||||
std::map<struct mg_connection *, class CivetConnection> connections;
|
std::map<struct mg_connection *, class CivetConnection> connections;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* requestHandler(struct mg_connection *, void *cbdata)
|
* requestHandler(struct mg_connection *, void *cbdata)
|
||||||
*
|
*
|
||||||
* Handles the incomming request.
|
* Handles the incomming request.
|
||||||
*
|
*
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
* @param cbdata - pointer to the CivetHandler instance.
|
* @param cbdata - pointer to the CivetHandler instance.
|
||||||
* @returns 0 if implemented, false otherwise
|
* @returns 0 if implemented, false otherwise
|
||||||
*/
|
*/
|
||||||
static int requestHandler(struct mg_connection *conn, void *cbdata);
|
static int requestHandler(struct mg_connection *conn, void *cbdata);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* closeHandler(struct mg_connection *)
|
* closeHandler(struct mg_connection *)
|
||||||
*
|
*
|
||||||
* Handles closing a request (internal handler)
|
* Handles closing a request (internal handler)
|
||||||
*
|
*
|
||||||
* @param conn - the connection information
|
* @param conn - the connection information
|
||||||
*/
|
*/
|
||||||
static void closeHandler(const struct mg_connection *conn);
|
static void closeHandler(const struct mg_connection *conn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the user provided close handler
|
* Stores the user provided close handler
|
||||||
*/
|
*/
|
||||||
void (*userCloseHandler)(const struct mg_connection *conn);
|
void (*userCloseHandler)(const struct mg_connection *conn);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
@@ -51,146 +51,145 @@ struct mg_connection; /* Handle for the individual connection */
|
|||||||
|
|
||||||
/* This structure contains information about the HTTP request. */
|
/* This structure contains information about the HTTP request. */
|
||||||
struct mg_request_info {
|
struct mg_request_info {
|
||||||
const char *request_method; /* "GET", "POST", etc */
|
const char *request_method; /* "GET", "POST", etc */
|
||||||
const char *uri; /* URL-decoded URI */
|
const char *uri; /* URL-decoded URI */
|
||||||
const char *http_version; /* E.g. "1.0", "1.1" */
|
const char *http_version; /* E.g. "1.0", "1.1" */
|
||||||
const char *query_string; /* URL part after '?', not including '?', or
|
const char *query_string; /* URL part after '?', not including '?', or
|
||||||
NULL */
|
NULL */
|
||||||
const char *remote_user; /* Authenticated user, or NULL if no auth
|
const char *remote_user; /* Authenticated user, or NULL if no auth
|
||||||
used */
|
used */
|
||||||
char remote_addr[48]; /* Client's IP address as a string. */
|
char remote_addr[48]; /* Client's IP address as a string. */
|
||||||
long
|
long remote_ip; /* Client's IP address. Deprecated: use remote_addr instead
|
||||||
remote_ip; /* Client's IP address. Deprecated: use remote_addr instead
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
long long content_length; /* Length (in bytes) of the request body,
|
long long content_length; /* Length (in bytes) of the request body,
|
||||||
can be -1 if no length was given. */
|
can be -1 if no length was given. */
|
||||||
int remote_port; /* Client's port */
|
int remote_port; /* Client's port */
|
||||||
int is_ssl; /* 1 if SSL-ed, 0 if not */
|
int is_ssl; /* 1 if SSL-ed, 0 if not */
|
||||||
void *user_data; /* User data pointer passed to mg_start() */
|
void *user_data; /* User data pointer passed to mg_start() */
|
||||||
void *conn_data; /* Connection-specific user data */
|
void *conn_data; /* Connection-specific user data */
|
||||||
|
|
||||||
int num_headers; /* Number of HTTP headers */
|
int num_headers; /* Number of HTTP headers */
|
||||||
struct mg_header {
|
struct mg_header {
|
||||||
const char *name; /* HTTP header name */
|
const char *name; /* HTTP header name */
|
||||||
const char *value; /* HTTP header value */
|
const char *value; /* HTTP header value */
|
||||||
} http_headers[64]; /* Maximum 64 headers */
|
} http_headers[64]; /* Maximum 64 headers */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure needs to be passed to mg_start(), to let civetweb know
|
/* This structure needs to be passed to mg_start(), to let civetweb know
|
||||||
which callbacks to invoke. For a detailed description, see
|
which callbacks to invoke. For a detailed description, see
|
||||||
https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md */
|
https://github.com/bel2125/civetweb/blob/master/docs/UserManual.md */
|
||||||
struct mg_callbacks {
|
struct mg_callbacks {
|
||||||
/* Called when civetweb has received new HTTP request.
|
/* Called when civetweb has received new HTTP request.
|
||||||
If the callback returns one, it must process the request
|
If the callback returns one, it must process the request
|
||||||
by sending valid HTTP headers and a body. Civetweb will not do
|
by sending valid HTTP headers and a body. Civetweb will not do
|
||||||
any further processing. Otherwise it must return zero.
|
any further processing. Otherwise it must return zero.
|
||||||
Note that since V1.7 the "begin_request" function is called
|
Note that since V1.7 the "begin_request" function is called
|
||||||
before an authorization check. If an authorization check is
|
before an authorization check. If an authorization check is
|
||||||
required, use a request_handler instead.
|
required, use a request_handler instead.
|
||||||
Return value:
|
Return value:
|
||||||
0: civetweb will process the request itself. In this case,
|
0: civetweb will process the request itself. In this case,
|
||||||
the callback must not send any data to the client.
|
the callback must not send any data to the client.
|
||||||
1: callback already processed the request. Civetweb will
|
1: callback already processed the request. Civetweb will
|
||||||
not send any data after the callback returned. */
|
not send any data after the callback returned. */
|
||||||
int (*begin_request)(struct mg_connection *);
|
int (*begin_request)(struct mg_connection *);
|
||||||
|
|
||||||
/* Called when civetweb has finished processing request. */
|
/* Called when civetweb has finished processing request. */
|
||||||
void (*end_request)(const struct mg_connection *, int reply_status_code);
|
void (*end_request)(const struct mg_connection *, int reply_status_code);
|
||||||
|
|
||||||
/* Called when civetweb is about to log a message. If callback returns
|
/* Called when civetweb is about to log a message. If callback returns
|
||||||
non-zero, civetweb does not log anything. */
|
non-zero, civetweb does not log anything. */
|
||||||
int (*log_message)(const struct mg_connection *, const char *message);
|
int (*log_message)(const struct mg_connection *, const char *message);
|
||||||
|
|
||||||
/* Called when civetweb is about to log access. If callback returns
|
/* Called when civetweb is about to log access. If callback returns
|
||||||
non-zero, civetweb does not log anything. */
|
non-zero, civetweb does not log anything. */
|
||||||
int (*log_access)(const struct mg_connection *, const char *message);
|
int (*log_access)(const struct mg_connection *, const char *message);
|
||||||
|
|
||||||
/* Called when civetweb initializes SSL library.
|
/* Called when civetweb initializes SSL library.
|
||||||
Parameters:
|
Parameters:
|
||||||
user_data: parameter user_data passed when starting the server.
|
user_data: parameter user_data passed when starting the server.
|
||||||
Return value:
|
Return value:
|
||||||
0: civetweb will set up the SSL certificate.
|
0: civetweb will set up the SSL certificate.
|
||||||
1: civetweb assumes the callback already set up the certificate.
|
1: civetweb assumes the callback already set up the certificate.
|
||||||
-1: initializing ssl fails. */
|
-1: initializing ssl fails. */
|
||||||
int (*init_ssl)(void *ssl_context, void *user_data);
|
int (*init_ssl)(void *ssl_context, void *user_data);
|
||||||
|
|
||||||
/* Called when websocket request is received, before websocket handshake.
|
/* Called when websocket request is received, before websocket handshake.
|
||||||
Return value:
|
Return value:
|
||||||
0: civetweb proceeds with websocket handshake.
|
0: civetweb proceeds with websocket handshake.
|
||||||
1: connection is closed immediately.
|
1: connection is closed immediately.
|
||||||
This callback is deprecated, use mg_set_websocket_handler instead. */
|
This callback is deprecated, use mg_set_websocket_handler instead. */
|
||||||
int (*websocket_connect)(const struct mg_connection *);
|
int (*websocket_connect)(const struct mg_connection *);
|
||||||
|
|
||||||
/* Called when websocket handshake is successfully completed, and
|
/* Called when websocket handshake is successfully completed, and
|
||||||
connection is ready for data exchange.
|
connection is ready for data exchange.
|
||||||
This callback is deprecated, use mg_set_websocket_handler instead. */
|
This callback is deprecated, use mg_set_websocket_handler instead. */
|
||||||
void (*websocket_ready)(struct mg_connection *);
|
void (*websocket_ready)(struct mg_connection *);
|
||||||
|
|
||||||
/* Called when data frame has been received from the client.
|
/* Called when data frame has been received from the client.
|
||||||
Parameters:
|
Parameters:
|
||||||
bits: first byte of the websocket frame, see websocket RFC at
|
bits: first byte of the websocket frame, see websocket RFC at
|
||||||
http://tools.ietf.org/html/rfc6455, section 5.2
|
http://tools.ietf.org/html/rfc6455, section 5.2
|
||||||
data, data_len: payload, with mask (if any) already applied.
|
data, data_len: payload, with mask (if any) already applied.
|
||||||
Return value:
|
Return value:
|
||||||
1: keep this websocket connection open.
|
1: keep this websocket connection open.
|
||||||
0: close this websocket connection.
|
0: close this websocket connection.
|
||||||
This callback is deprecated, use mg_set_websocket_handler instead. */
|
This callback is deprecated, use mg_set_websocket_handler instead. */
|
||||||
int (*websocket_data)(struct mg_connection *, int bits, char *data,
|
int (*websocket_data)(struct mg_connection *, int bits, char *data,
|
||||||
size_t data_len);
|
size_t data_len);
|
||||||
|
|
||||||
/* Called when civetweb is closing a connection. The per-context mutex is
|
/* Called when civetweb is closing a connection. The per-context mutex is
|
||||||
locked when this is invoked. This is primarily useful for noting when
|
locked when this is invoked. This is primarily useful for noting when
|
||||||
a websocket is closing and removing it from any application-maintained
|
a websocket is closing and removing it from any application-maintained
|
||||||
list of clients.
|
list of clients.
|
||||||
Using this callback for websocket connections is deprecated, use
|
Using this callback for websocket connections is deprecated, use
|
||||||
mg_set_websocket_handler instead. */
|
mg_set_websocket_handler instead. */
|
||||||
void (*connection_close)(const struct mg_connection *);
|
void (*connection_close)(const struct mg_connection *);
|
||||||
|
|
||||||
/* Called when civetweb tries to open a file. Used to intercept file open
|
/* Called when civetweb tries to open a file. Used to intercept file open
|
||||||
calls, and serve file data from memory instead.
|
calls, and serve file data from memory instead.
|
||||||
Parameters:
|
Parameters:
|
||||||
path: Full path to the file to open.
|
path: Full path to the file to open.
|
||||||
data_len: Placeholder for the file size, if file is served from
|
data_len: Placeholder for the file size, if file is served from
|
||||||
memory.
|
memory.
|
||||||
Return value:
|
Return value:
|
||||||
NULL: do not serve file from memory, proceed with normal file open.
|
NULL: do not serve file from memory, proceed with normal file open.
|
||||||
non-NULL: pointer to the file contents in memory. data_len must be
|
non-NULL: pointer to the file contents in memory. data_len must be
|
||||||
initilized with the size of the memory block. */
|
initilized with the size of the memory block. */
|
||||||
const char *(*open_file)(const struct mg_connection *, const char *path,
|
const char *(*open_file)(const struct mg_connection *, const char *path,
|
||||||
size_t *data_len);
|
size_t *data_len);
|
||||||
|
|
||||||
/* Called when civetweb is about to serve Lua server page, if
|
/* Called when civetweb is about to serve Lua server page, if
|
||||||
Lua support is enabled.
|
Lua support is enabled.
|
||||||
Parameters:
|
Parameters:
|
||||||
lua_context: "lua_State *" pointer. */
|
lua_context: "lua_State *" pointer. */
|
||||||
void (*init_lua)(const struct mg_connection *, void *lua_context);
|
void (*init_lua)(const struct mg_connection *, void *lua_context);
|
||||||
|
|
||||||
/* Called when civetweb has uploaded a file to a temporary directory as a
|
/* Called when civetweb has uploaded a file to a temporary directory as a
|
||||||
result of mg_upload() call.
|
result of mg_upload() call.
|
||||||
Parameters:
|
Parameters:
|
||||||
file_name: full path name to the uploaded file. */
|
file_name: full path name to the uploaded file. */
|
||||||
void (*upload)(struct mg_connection *, const char *file_name);
|
void (*upload)(struct mg_connection *, const char *file_name);
|
||||||
|
|
||||||
/* Called when civetweb is about to send HTTP error to the client.
|
/* Called when civetweb is about to send HTTP error to the client.
|
||||||
Implementing this callback allows to create custom error pages.
|
Implementing this callback allows to create custom error pages.
|
||||||
Parameters:
|
Parameters:
|
||||||
status: HTTP error status code.
|
status: HTTP error status code.
|
||||||
Return value:
|
Return value:
|
||||||
1: run civetweb error handler.
|
1: run civetweb error handler.
|
||||||
0: callback already handled the error. */
|
0: callback already handled the error. */
|
||||||
int (*http_error)(struct mg_connection *, int status);
|
int (*http_error)(struct mg_connection *, int status);
|
||||||
|
|
||||||
/* Called after civetweb context has been created, before requests
|
/* Called after civetweb context has been created, before requests
|
||||||
are processed.
|
are processed.
|
||||||
Parameters:
|
Parameters:
|
||||||
ctx: context handle */
|
ctx: context handle */
|
||||||
void (*init_context)(const struct mg_context *ctx);
|
void (*init_context)(const struct mg_context *ctx);
|
||||||
|
|
||||||
/* Called when civetweb context is deleted.
|
/* Called when civetweb context is deleted.
|
||||||
Parameters:
|
Parameters:
|
||||||
ctx: context handle */
|
ctx: context handle */
|
||||||
void (*exit_context)(const struct mg_context *ctx);
|
void (*exit_context)(const struct mg_context *ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Start web server.
|
/* Start web server.
|
||||||
@@ -347,19 +346,19 @@ CIVETWEB_API const char **mg_get_valid_option_names(void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct mg_option {
|
struct mg_option {
|
||||||
const char *name;
|
const char *name;
|
||||||
int type;
|
int type;
|
||||||
const char *default_value;
|
const char *default_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CONFIG_TYPE_UNKNOWN = 0x0,
|
CONFIG_TYPE_UNKNOWN = 0x0,
|
||||||
CONFIG_TYPE_NUMBER = 0x1,
|
CONFIG_TYPE_NUMBER = 0x1,
|
||||||
CONFIG_TYPE_STRING = 0x2,
|
CONFIG_TYPE_STRING = 0x2,
|
||||||
CONFIG_TYPE_FILE = 0x3,
|
CONFIG_TYPE_FILE = 0x3,
|
||||||
CONFIG_TYPE_DIRECTORY = 0x4,
|
CONFIG_TYPE_DIRECTORY = 0x4,
|
||||||
CONFIG_TYPE_BOOLEAN = 0x5,
|
CONFIG_TYPE_BOOLEAN = 0x5,
|
||||||
CONFIG_TYPE_EXT_PATTERN = 0x6
|
CONFIG_TYPE_EXT_PATTERN = 0x6
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return array of struct mg_option, representing all valid configuration
|
/* Return array of struct mg_option, representing all valid configuration
|
||||||
@@ -439,12 +438,12 @@ CIVETWEB_API void mg_unlock_context(struct mg_context *ctx);
|
|||||||
|
|
||||||
/* Opcodes, from http://tools.ietf.org/html/rfc6455 */
|
/* Opcodes, from http://tools.ietf.org/html/rfc6455 */
|
||||||
enum {
|
enum {
|
||||||
WEBSOCKET_OPCODE_CONTINUATION = 0x0,
|
WEBSOCKET_OPCODE_CONTINUATION = 0x0,
|
||||||
WEBSOCKET_OPCODE_TEXT = 0x1,
|
WEBSOCKET_OPCODE_TEXT = 0x1,
|
||||||
WEBSOCKET_OPCODE_BINARY = 0x2,
|
WEBSOCKET_OPCODE_BINARY = 0x2,
|
||||||
WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
|
WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
|
||||||
WEBSOCKET_OPCODE_PING = 0x9,
|
WEBSOCKET_OPCODE_PING = 0x9,
|
||||||
WEBSOCKET_OPCODE_PONG = 0xa
|
WEBSOCKET_OPCODE_PONG = 0xa
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Macros for enabling compiler-specific checks for printf-like arguments. */
|
/* Macros for enabling compiler-specific checks for printf-like arguments. */
|
||||||
|
@@ -16,288 +16,288 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn) {
|
bool CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn) {
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn) {
|
bool CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn) {
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn) {
|
bool CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn) {
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handleDelete(CivetServer *server,
|
bool CivetHandler::handleDelete(CivetServer *server,
|
||||||
struct mg_connection *conn) {
|
struct mg_connection *conn) {
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetHandler::handleOptions(CivetServer *server,
|
bool CivetHandler::handleOptions(CivetServer *server,
|
||||||
struct mg_connection *conn) {
|
struct mg_connection *conn) {
|
||||||
UNUSED_PARAMETER(server);
|
UNUSED_PARAMETER(server);
|
||||||
UNUSED_PARAMETER(conn);
|
UNUSED_PARAMETER(conn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CivetServer::requestHandler(struct mg_connection *conn, void *cbdata) {
|
int CivetServer::requestHandler(struct mg_connection *conn, void *cbdata) {
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
assert(request_info != NULL);
|
assert(request_info != NULL);
|
||||||
CivetServer *me = (CivetServer *)(request_info->user_data);
|
CivetServer *me = (CivetServer *)(request_info->user_data);
|
||||||
assert(me != NULL);
|
assert(me != NULL);
|
||||||
|
|
||||||
// Happens when a request hits the server before the context is saved
|
// Happens when a request hits the server before the context is saved
|
||||||
if (me->context == NULL)
|
if (me->context == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mg_lock_context(me->context);
|
mg_lock_context(me->context);
|
||||||
me->connections[conn] = CivetConnection();
|
me->connections[conn] = CivetConnection();
|
||||||
mg_unlock_context(me->context);
|
mg_unlock_context(me->context);
|
||||||
|
|
||||||
CivetHandler *handler = (CivetHandler *)cbdata;
|
CivetHandler *handler = (CivetHandler *)cbdata;
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
if (strcmp(request_info->request_method, "GET") == 0) {
|
if (strcmp(request_info->request_method, "GET") == 0) {
|
||||||
return handler->handleGet(me, conn) ? 1 : 0;
|
return handler->handleGet(me, conn) ? 1 : 0;
|
||||||
} else if (strcmp(request_info->request_method, "POST") == 0) {
|
} else if (strcmp(request_info->request_method, "POST") == 0) {
|
||||||
return handler->handlePost(me, conn) ? 1 : 0;
|
return handler->handlePost(me, conn) ? 1 : 0;
|
||||||
} else if (strcmp(request_info->request_method, "PUT") == 0) {
|
} else if (strcmp(request_info->request_method, "PUT") == 0) {
|
||||||
return handler->handlePut(me, conn) ? 1 : 0;
|
return handler->handlePut(me, conn) ? 1 : 0;
|
||||||
} else if (strcmp(request_info->request_method, "DELETE") == 0) {
|
} else if (strcmp(request_info->request_method, "DELETE") == 0) {
|
||||||
return handler->handleDelete(me, conn) ? 1 : 0;
|
return handler->handleDelete(me, conn) ? 1 : 0;
|
||||||
} else if (strcmp(request_info->request_method, "OPTIONS") == 0) {
|
} else if (strcmp(request_info->request_method, "OPTIONS") == 0) {
|
||||||
return handler->handleOptions(me, conn) ? 1 : 0;
|
return handler->handleOptions(me, conn) ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; // No handler found
|
return 0; // No handler found
|
||||||
}
|
}
|
||||||
|
|
||||||
CivetServer::CivetServer(const char **options,
|
CivetServer::CivetServer(const char **options,
|
||||||
const struct mg_callbacks *_callbacks)
|
const struct mg_callbacks *_callbacks)
|
||||||
: context(0) {
|
: context(0) {
|
||||||
struct mg_callbacks callbacks;
|
struct mg_callbacks callbacks;
|
||||||
memset(&callbacks, 0, sizeof(callbacks));
|
memset(&callbacks, 0, sizeof(callbacks));
|
||||||
|
|
||||||
if (_callbacks) {
|
if (_callbacks) {
|
||||||
callbacks = *_callbacks;
|
callbacks = *_callbacks;
|
||||||
userCloseHandler = _callbacks->connection_close;
|
userCloseHandler = _callbacks->connection_close;
|
||||||
} else {
|
} else {
|
||||||
userCloseHandler = NULL;
|
userCloseHandler = NULL;
|
||||||
}
|
}
|
||||||
callbacks.connection_close = closeHandler;
|
callbacks.connection_close = closeHandler;
|
||||||
context = mg_start(&callbacks, this, options);
|
context = mg_start(&callbacks, this, options);
|
||||||
if (context == NULL)
|
if (context == NULL)
|
||||||
throw CivetException("null context when constructing CivetServer. "
|
throw CivetException("null context when constructing CivetServer. "
|
||||||
"Possible problem binding to port.");
|
"Possible problem binding to port.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CivetServer::~CivetServer() { close(); }
|
CivetServer::~CivetServer() { close(); }
|
||||||
|
|
||||||
void CivetServer::closeHandler(const struct mg_connection *conn) {
|
void CivetServer::closeHandler(const struct mg_connection *conn) {
|
||||||
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
const struct mg_request_info *request_info = mg_get_request_info(conn);
|
||||||
assert(request_info != NULL);
|
assert(request_info != NULL);
|
||||||
CivetServer *me = (CivetServer *)(request_info->user_data);
|
CivetServer *me = (CivetServer *)(request_info->user_data);
|
||||||
assert(me != NULL);
|
assert(me != NULL);
|
||||||
|
|
||||||
// Happens when a request hits the server before the context is saved
|
// Happens when a request hits the server before the context is saved
|
||||||
if (me->context == NULL)
|
if (me->context == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (me->userCloseHandler)
|
if (me->userCloseHandler)
|
||||||
me->userCloseHandler(conn);
|
me->userCloseHandler(conn);
|
||||||
mg_lock_context(me->context);
|
mg_lock_context(me->context);
|
||||||
me->connections.erase(const_cast<struct mg_connection *>(conn));
|
me->connections.erase(const_cast<struct mg_connection *>(conn));
|
||||||
mg_unlock_context(me->context);
|
mg_unlock_context(me->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::addHandler(const std::string &uri, CivetHandler *handler) {
|
void CivetServer::addHandler(const std::string &uri, CivetHandler *handler) {
|
||||||
mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
|
mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::removeHandler(const std::string &uri) {
|
void CivetServer::removeHandler(const std::string &uri) {
|
||||||
mg_set_request_handler(context, uri.c_str(), NULL, NULL);
|
mg_set_request_handler(context, uri.c_str(), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::close() {
|
void CivetServer::close() {
|
||||||
if (context) {
|
if (context) {
|
||||||
mg_stop(context);
|
mg_stop(context);
|
||||||
context = 0;
|
context = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CivetServer::getCookie(struct mg_connection *conn,
|
int CivetServer::getCookie(struct mg_connection *conn,
|
||||||
const std::string &cookieName,
|
const std::string &cookieName,
|
||||||
std::string &cookieValue) {
|
std::string &cookieValue) {
|
||||||
// Maximum cookie length as per microsoft is 4096.
|
// Maximum cookie length as per microsoft is 4096.
|
||||||
// http://msdn.microsoft.com/en-us/library/ms178194.aspx
|
// http://msdn.microsoft.com/en-us/library/ms178194.aspx
|
||||||
char _cookieValue[4096];
|
char _cookieValue[4096];
|
||||||
const char *cookie = mg_get_header(conn, "Cookie");
|
const char *cookie = mg_get_header(conn, "Cookie");
|
||||||
int lRead = mg_get_cookie(cookie, cookieName.c_str(), _cookieValue,
|
int lRead = mg_get_cookie(cookie, cookieName.c_str(), _cookieValue,
|
||||||
sizeof(_cookieValue));
|
sizeof(_cookieValue));
|
||||||
cookieValue.clear();
|
cookieValue.clear();
|
||||||
cookieValue.append(_cookieValue);
|
cookieValue.append(_cookieValue);
|
||||||
return lRead;
|
return lRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *CivetServer::getHeader(struct mg_connection *conn,
|
const char *CivetServer::getHeader(struct mg_connection *conn,
|
||||||
const std::string &headerName) {
|
const std::string &headerName) {
|
||||||
return mg_get_header(conn, headerName.c_str());
|
return mg_get_header(conn, headerName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlDecode(const char *src, std::string &dst,
|
void CivetServer::urlDecode(const char *src, std::string &dst,
|
||||||
bool is_form_url_encoded) {
|
bool is_form_url_encoded) {
|
||||||
urlDecode(src, strlen(src), dst, is_form_url_encoded);
|
urlDecode(src, strlen(src), dst, is_form_url_encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlDecode(const char *src, size_t src_len, std::string &dst,
|
void CivetServer::urlDecode(const char *src, size_t src_len, std::string &dst,
|
||||||
bool is_form_url_encoded) {
|
bool is_form_url_encoded) {
|
||||||
int i, j, a, b;
|
int i, j, a, b;
|
||||||
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
|
||||||
|
|
||||||
dst.clear();
|
dst.clear();
|
||||||
for (i = j = 0; i < (int)src_len; i++, j++) {
|
for (i = j = 0; i < (int)src_len; i++, j++) {
|
||||||
if (i < (int)src_len - 2 && src[i] == '%' &&
|
if (i < (int)src_len - 2 && src[i] == '%' &&
|
||||||
isxdigit(*(const unsigned char *)(src + i + 1)) &&
|
isxdigit(*(const unsigned char *)(src + i + 1)) &&
|
||||||
isxdigit(*(const unsigned char *)(src + i + 2))) {
|
isxdigit(*(const unsigned char *)(src + i + 2))) {
|
||||||
a = tolower(*(const unsigned char *)(src + i + 1));
|
a = tolower(*(const unsigned char *)(src + i + 1));
|
||||||
b = tolower(*(const unsigned char *)(src + i + 2));
|
b = tolower(*(const unsigned char *)(src + i + 2));
|
||||||
dst.push_back((char)((HEXTOI(a) << 4) | HEXTOI(b)));
|
dst.push_back((char)((HEXTOI(a) << 4) | HEXTOI(b)));
|
||||||
i += 2;
|
i += 2;
|
||||||
} else if (is_form_url_encoded && src[i] == '+') {
|
} else if (is_form_url_encoded && src[i] == '+') {
|
||||||
dst.push_back(' ');
|
dst.push_back(' ');
|
||||||
} else {
|
} else {
|
||||||
dst.push_back(src[i]);
|
dst.push_back(src[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetServer::getParam(struct mg_connection *conn, const char *name,
|
bool CivetServer::getParam(struct mg_connection *conn, const char *name,
|
||||||
std::string &dst, size_t occurrence) {
|
std::string &dst, size_t occurrence) {
|
||||||
const char *formParams = NULL;
|
const char *formParams = NULL;
|
||||||
const struct mg_request_info *ri = mg_get_request_info(conn);
|
const struct mg_request_info *ri = mg_get_request_info(conn);
|
||||||
assert(ri != NULL);
|
assert(ri != NULL);
|
||||||
CivetServer *me = (CivetServer *)(ri->user_data);
|
CivetServer *me = (CivetServer *)(ri->user_data);
|
||||||
assert(me != NULL);
|
assert(me != NULL);
|
||||||
mg_lock_context(me->context);
|
mg_lock_context(me->context);
|
||||||
CivetConnection &conobj = me->connections[conn];
|
CivetConnection &conobj = me->connections[conn];
|
||||||
mg_lock_connection(conn);
|
mg_lock_connection(conn);
|
||||||
mg_unlock_context(me->context);
|
mg_unlock_context(me->context);
|
||||||
|
|
||||||
if (conobj.postData != NULL) {
|
if (conobj.postData != NULL) {
|
||||||
formParams = conobj.postData;
|
formParams = conobj.postData;
|
||||||
} else {
|
} else {
|
||||||
const char *con_len_str = mg_get_header(conn, "Content-Length");
|
const char *con_len_str = mg_get_header(conn, "Content-Length");
|
||||||
if (con_len_str) {
|
if (con_len_str) {
|
||||||
unsigned long con_len = atoi(con_len_str);
|
unsigned long con_len = atoi(con_len_str);
|
||||||
if (con_len > 0) {
|
if (con_len > 0) {
|
||||||
// Add one extra character: in case the post-data is a text, it
|
// Add one extra character: in case the post-data is a text, it
|
||||||
// is required as 0-termination.
|
// is required as 0-termination.
|
||||||
// Do not increment con_len, since the 0 terminating is not part
|
// Do not increment con_len, since the 0 terminating is not part
|
||||||
// of the content (text or binary).
|
// of the content (text or binary).
|
||||||
conobj.postData = (char *)malloc(con_len + 1);
|
conobj.postData = (char *)malloc(con_len + 1);
|
||||||
if (conobj.postData != NULL) {
|
if (conobj.postData != NULL) {
|
||||||
// malloc may fail for huge requests
|
// malloc may fail for huge requests
|
||||||
mg_read(conn, conobj.postData, con_len);
|
mg_read(conn, conobj.postData, con_len);
|
||||||
conobj.postData[con_len] = 0;
|
conobj.postData[con_len] = 0;
|
||||||
formParams = conobj.postData;
|
formParams = conobj.postData;
|
||||||
conobj.postDataLen = con_len;
|
conobj.postDataLen = con_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (formParams == NULL) {
|
if (formParams == NULL) {
|
||||||
// get requests do store html <form> field values in the http
|
// get requests do store html <form> field values in the http
|
||||||
// query_string
|
// query_string
|
||||||
formParams = ri->query_string;
|
formParams = ri->query_string;
|
||||||
}
|
}
|
||||||
mg_unlock_connection(conn);
|
mg_unlock_connection(conn);
|
||||||
|
|
||||||
if (formParams != NULL) {
|
if (formParams != NULL) {
|
||||||
return getParam(formParams, strlen(formParams), name, dst, occurrence);
|
return getParam(formParams, strlen(formParams), name, dst, occurrence);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CivetServer::getParam(const char *data, size_t data_len, const char *name,
|
bool CivetServer::getParam(const char *data, size_t data_len, const char *name,
|
||||||
std::string &dst, size_t occurrence) {
|
std::string &dst, size_t occurrence) {
|
||||||
const char *p, *e, *s;
|
const char *p, *e, *s;
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
|
|
||||||
dst.clear();
|
dst.clear();
|
||||||
if (data == NULL || name == NULL || data_len == 0) {
|
if (data == NULL || name == NULL || data_len == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
name_len = strlen(name);
|
name_len = strlen(name);
|
||||||
e = data + data_len;
|
e = data + data_len;
|
||||||
|
|
||||||
// data is "var1=val1&var2=val2...". Find variable first
|
// data is "var1=val1&var2=val2...". Find variable first
|
||||||
for (p = data; p + name_len < e; p++) {
|
for (p = data; p + name_len < e; p++) {
|
||||||
if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
|
if ((p == data || p[-1] == '&') && p[name_len] == '=' &&
|
||||||
!mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
|
!mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
|
||||||
|
|
||||||
// Point p to variable value
|
// Point p to variable value
|
||||||
p += name_len + 1;
|
p += name_len + 1;
|
||||||
|
|
||||||
// Point s to the end of the value
|
// Point s to the end of the value
|
||||||
s = (const char *)memchr(p, '&', (size_t)(e - p));
|
s = (const char *)memchr(p, '&', (size_t)(e - p));
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
s = e;
|
s = e;
|
||||||
}
|
}
|
||||||
assert(s >= p);
|
assert(s >= p);
|
||||||
|
|
||||||
// Decode variable into destination buffer
|
// Decode variable into destination buffer
|
||||||
urlDecode(p, (int)(s - p), dst, true);
|
urlDecode(p, (int)(s - p), dst, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlEncode(const char *src, std::string &dst, bool append) {
|
void CivetServer::urlEncode(const char *src, std::string &dst, bool append) {
|
||||||
urlEncode(src, strlen(src), dst, append);
|
urlEncode(src, strlen(src), dst, append);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CivetServer::urlEncode(const char *src, size_t src_len, std::string &dst,
|
void CivetServer::urlEncode(const char *src, size_t src_len, std::string &dst,
|
||||||
bool append) {
|
bool append) {
|
||||||
static const char *dont_escape = "._-$,;~()";
|
static const char *dont_escape = "._-$,;~()";
|
||||||
static const char *hex = "0123456789abcdef";
|
static const char *hex = "0123456789abcdef";
|
||||||
|
|
||||||
if (!append)
|
if (!append)
|
||||||
dst.clear();
|
dst.clear();
|
||||||
|
|
||||||
for (; src_len > 0; src++, src_len--) {
|
for (; src_len > 0; src++, src_len--) {
|
||||||
if (isalnum(*(const unsigned char *)src) ||
|
if (isalnum(*(const unsigned char *)src) ||
|
||||||
strchr(dont_escape, *(const unsigned char *)src) != NULL) {
|
strchr(dont_escape, *(const unsigned char *)src) != NULL) {
|
||||||
dst.push_back(*src);
|
dst.push_back(*src);
|
||||||
} else {
|
} else {
|
||||||
dst.push_back('%');
|
dst.push_back('%');
|
||||||
dst.push_back(hex[(*(const unsigned char *)src) >> 4]);
|
dst.push_back(hex[(*(const unsigned char *)src) >> 4]);
|
||||||
dst.push_back(hex[(*(const unsigned char *)src) & 0xf]);
|
dst.push_back(hex[(*(const unsigned char *)src) & 0xf]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> CivetServer::getListeningPorts() {
|
std::vector<int> CivetServer::getListeningPorts() {
|
||||||
std::vector<int> ports(10);
|
std::vector<int> ports(10);
|
||||||
std::vector<int> ssl(10);
|
std::vector<int> ssl(10);
|
||||||
size_t size = mg_get_ports(context, ports.size(), &ports[0], &ssl[0]);
|
size_t size = mg_get_ports(context, ports.size(), &ports[0], &ssl[0]);
|
||||||
ports.resize(size);
|
ports.resize(size);
|
||||||
ssl.resize(size);
|
ssl.resize(size);
|
||||||
return ports;
|
return ports;
|
||||||
}
|
}
|
||||||
|
|
||||||
CivetServer::CivetConnection::CivetConnection() {
|
CivetServer::CivetConnection::CivetConnection() {
|
||||||
postData = NULL;
|
postData = NULL;
|
||||||
postDataLen = 0;
|
postDataLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CivetServer::CivetConnection::~CivetConnection() { free(postData); }
|
CivetServer::CivetConnection::~CivetConnection() { free(postData); }
|
||||||
|
12335
src/civetweb.c
12335
src/civetweb.c
File diff suppressed because it is too large
Load Diff
2596
src/main.c
2596
src/main.c
File diff suppressed because it is too large
Load Diff
481
src/md5.inl
481
src/md5.inl
@@ -35,7 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef md5_INCLUDED
|
#ifndef md5_INCLUDED
|
||||||
# define md5_INCLUDED
|
#define md5_INCLUDED
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This package supports both compile-time and run-time determination of CPU
|
* This package supports both compile-time and run-time determination of CPU
|
||||||
@@ -48,31 +48,31 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
||||||
typedef unsigned int md5_word_t; /* 32-bit word */
|
typedef unsigned int md5_word_t; /* 32-bit word */
|
||||||
|
|
||||||
/* Define the state of the MD5 Algorithm. */
|
/* Define the state of the MD5 Algorithm. */
|
||||||
typedef struct md5_state_s {
|
typedef struct md5_state_s {
|
||||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||||
md5_word_t abcd[4]; /* digest buffer */
|
md5_word_t abcd[4]; /* digest buffer */
|
||||||
md5_byte_t buf[64]; /* accumulate block */
|
md5_byte_t buf[64]; /* accumulate block */
|
||||||
} md5_state_t;
|
} md5_state_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Initialize the algorithm. */
|
/* Initialize the algorithm. */
|
||||||
MD5_STATIC void md5_init(md5_state_t *pms);
|
MD5_STATIC void md5_init(md5_state_t *pms);
|
||||||
|
|
||||||
/* Append a string to the message. */
|
/* Append a string to the message. */
|
||||||
MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
|
MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data,
|
||||||
|
int nbytes);
|
||||||
|
|
||||||
/* Finish the message and return the digest. */
|
/* Finish the message and return the digest. */
|
||||||
MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* end extern "C" */
|
} /* end extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* md5_INCLUDED */
|
#endif /* md5_INCLUDED */
|
||||||
@@ -134,330 +134,321 @@ MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||||
#ifdef ARCH_IS_BIG_ENDIAN
|
#ifdef ARCH_IS_BIG_ENDIAN
|
||||||
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
#define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||||
#else
|
#else
|
||||||
# define BYTE_ORDER 0
|
#define BYTE_ORDER 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define T_MASK ((md5_word_t)~0)
|
#define T_MASK ((md5_word_t)~0)
|
||||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||||
#define T3 0x242070db
|
#define T3 0x242070db
|
||||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||||
#define T6 0x4787c62a
|
#define T6 0x4787c62a
|
||||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||||
#define T9 0x698098d8
|
#define T9 0x698098d8
|
||||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||||
#define T13 0x6b901122
|
#define T13 0x6b901122
|
||||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||||
#define T16 0x49b40821
|
#define T16 0x49b40821
|
||||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||||
#define T19 0x265e5a51
|
#define T19 0x265e5a51
|
||||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||||
#define T22 0x02441453
|
#define T22 0x02441453
|
||||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||||
#define T25 0x21e1cde6
|
#define T25 0x21e1cde6
|
||||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||||
#define T28 0x455a14ed
|
#define T28 0x455a14ed
|
||||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||||
#define T31 0x676f02d9
|
#define T31 0x676f02d9
|
||||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||||
#define T35 0x6d9d6122
|
#define T35 0x6d9d6122
|
||||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||||
#define T38 0x4bdecfa9
|
#define T38 0x4bdecfa9
|
||||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||||
#define T41 0x289b7ec6
|
#define T41 0x289b7ec6
|
||||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||||
#define T44 0x04881d05
|
#define T44 0x04881d05
|
||||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||||
#define T47 0x1fa27cf8
|
#define T47 0x1fa27cf8
|
||||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||||
#define T50 0x432aff97
|
#define T50 0x432aff97
|
||||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||||
#define T53 0x655b59c3
|
#define T53 0x655b59c3
|
||||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||||
#define T57 0x6fa87e4f
|
#define T57 0x6fa87e4f
|
||||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||||
#define T60 0x4e0811a1
|
#define T60 0x4e0811a1
|
||||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||||
#define T63 0x2ad7d2bb
|
#define T63 0x2ad7d2bb
|
||||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||||
|
|
||||||
|
static void md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) {
|
||||||
static void
|
md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2],
|
||||||
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
d = pms->abcd[3];
|
||||||
{
|
md5_word_t t;
|
||||||
md5_word_t
|
|
||||||
a = pms->abcd[0], b = pms->abcd[1],
|
|
||||||
c = pms->abcd[2], d = pms->abcd[3];
|
|
||||||
md5_word_t t;
|
|
||||||
#if BYTE_ORDER > 0
|
#if BYTE_ORDER > 0
|
||||||
/* Define storage only for big-endian CPUs. */
|
/* Define storage only for big-endian CPUs. */
|
||||||
md5_word_t X[16];
|
md5_word_t X[16];
|
||||||
#else
|
#else
|
||||||
/* Define storage for little-endian or both types of CPUs. */
|
/* Define storage for little-endian or both types of CPUs. */
|
||||||
md5_word_t xbuf[16];
|
md5_word_t xbuf[16];
|
||||||
const md5_word_t *X;
|
const md5_word_t *X;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
#if BYTE_ORDER == 0
|
#if BYTE_ORDER == 0
|
||||||
/*
|
/*
|
||||||
* Determine dynamically whether this is a big-endian or
|
* Determine dynamically whether this is a big-endian or
|
||||||
* little-endian machine, since we can use a more efficient
|
* little-endian machine, since we can use a more efficient
|
||||||
* algorithm on the latter.
|
* algorithm on the latter.
|
||||||
*/
|
*/
|
||||||
static const int w = 1;
|
static const int w = 1;
|
||||||
|
|
||||||
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
|
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
|
||||||
#endif
|
#endif
|
||||||
#if BYTE_ORDER <= 0 /* little-endian */
|
#if BYTE_ORDER <= 0 /* little-endian */
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* On little-endian machines, we can process properly aligned
|
* On little-endian machines, we can process properly aligned
|
||||||
* data without copying it.
|
* data without copying it.
|
||||||
*/
|
*/
|
||||||
if (!((data - (const md5_byte_t *)0) & 3)) {
|
if (!((data - (const md5_byte_t *)0) & 3)) {
|
||||||
/* data are properly aligned, a direct assignment is possible */
|
/* data are properly aligned, a direct assignment is possible */
|
||||||
/* cast through a (void *) should avoid a compiler warning,
|
/* cast through a (void *) should avoid a compiler warning,
|
||||||
see https://github.com/bel2125/civetweb/issues/94#issuecomment-98112861 */
|
see
|
||||||
X = (const md5_word_t *)(void *)data;
|
https://github.com/bel2125/civetweb/issues/94#issuecomment-98112861
|
||||||
} else {
|
*/
|
||||||
/* not aligned */
|
X = (const md5_word_t *)(void *)data;
|
||||||
memcpy(xbuf, data, 64);
|
} else {
|
||||||
X = xbuf;
|
/* not aligned */
|
||||||
}
|
memcpy(xbuf, data, 64);
|
||||||
}
|
X = xbuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if BYTE_ORDER == 0
|
#if BYTE_ORDER == 0
|
||||||
else /* dynamic big-endian */
|
else /* dynamic big-endian */
|
||||||
#endif
|
#endif
|
||||||
#if BYTE_ORDER >= 0 /* big-endian */
|
#if BYTE_ORDER >= 0 /* big-endian */
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* On big-endian machines, we must arrange the bytes in the
|
* On big-endian machines, we must arrange the bytes in the
|
||||||
* right order.
|
* right order.
|
||||||
*/
|
*/
|
||||||
const md5_byte_t *xp = data;
|
const md5_byte_t *xp = data;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
# if BYTE_ORDER == 0
|
#if BYTE_ORDER == 0
|
||||||
X = xbuf; /* (dynamic only) */
|
X = xbuf; /* (dynamic only) */
|
||||||
# else
|
#else
|
||||||
# define xbuf X /* (static only) */
|
#define xbuf X /* (static only) */
|
||||||
# endif
|
|
||||||
for (i = 0; i < 16; ++i, xp += 4)
|
|
||||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
for (i = 0; i < 16; ++i, xp += 4)
|
||||||
|
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||||
|
|
||||||
/* Round 1. */
|
/* Round 1. */
|
||||||
/* Let [abcd k s i] denote the operation
|
/* Let [abcd k s i] denote the operation
|
||||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||||
#define SET(a, b, c, d, k, s, Ti)\
|
#define SET(a, b, c, d, k, s, Ti) \
|
||||||
t = a + F(b,c,d) + X[k] + Ti;\
|
t = a + F(b, c, d) + X[k] + Ti; \
|
||||||
a = ROTATE_LEFT(t, s) + b
|
a = ROTATE_LEFT(t, s) + b
|
||||||
/* Do the following 16 operations. */
|
/* Do the following 16 operations. */
|
||||||
SET(a, b, c, d, 0, 7, T1);
|
SET(a, b, c, d, 0, 7, T1);
|
||||||
SET(d, a, b, c, 1, 12, T2);
|
SET(d, a, b, c, 1, 12, T2);
|
||||||
SET(c, d, a, b, 2, 17, T3);
|
SET(c, d, a, b, 2, 17, T3);
|
||||||
SET(b, c, d, a, 3, 22, T4);
|
SET(b, c, d, a, 3, 22, T4);
|
||||||
SET(a, b, c, d, 4, 7, T5);
|
SET(a, b, c, d, 4, 7, T5);
|
||||||
SET(d, a, b, c, 5, 12, T6);
|
SET(d, a, b, c, 5, 12, T6);
|
||||||
SET(c, d, a, b, 6, 17, T7);
|
SET(c, d, a, b, 6, 17, T7);
|
||||||
SET(b, c, d, a, 7, 22, T8);
|
SET(b, c, d, a, 7, 22, T8);
|
||||||
SET(a, b, c, d, 8, 7, T9);
|
SET(a, b, c, d, 8, 7, T9);
|
||||||
SET(d, a, b, c, 9, 12, T10);
|
SET(d, a, b, c, 9, 12, T10);
|
||||||
SET(c, d, a, b, 10, 17, T11);
|
SET(c, d, a, b, 10, 17, T11);
|
||||||
SET(b, c, d, a, 11, 22, T12);
|
SET(b, c, d, a, 11, 22, T12);
|
||||||
SET(a, b, c, d, 12, 7, T13);
|
SET(a, b, c, d, 12, 7, T13);
|
||||||
SET(d, a, b, c, 13, 12, T14);
|
SET(d, a, b, c, 13, 12, T14);
|
||||||
SET(c, d, a, b, 14, 17, T15);
|
SET(c, d, a, b, 14, 17, T15);
|
||||||
SET(b, c, d, a, 15, 22, T16);
|
SET(b, c, d, a, 15, 22, T16);
|
||||||
#undef SET
|
#undef SET
|
||||||
|
|
||||||
/* Round 2. */
|
/* Round 2. */
|
||||||
/* Let [abcd k s i] denote the operation
|
/* Let [abcd k s i] denote the operation
|
||||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||||
#define SET(a, b, c, d, k, s, Ti)\
|
#define SET(a, b, c, d, k, s, Ti) \
|
||||||
t = a + G(b,c,d) + X[k] + Ti;\
|
t = a + G(b, c, d) + X[k] + Ti; \
|
||||||
a = ROTATE_LEFT(t, s) + b
|
a = ROTATE_LEFT(t, s) + b
|
||||||
/* Do the following 16 operations. */
|
/* Do the following 16 operations. */
|
||||||
SET(a, b, c, d, 1, 5, T17);
|
SET(a, b, c, d, 1, 5, T17);
|
||||||
SET(d, a, b, c, 6, 9, T18);
|
SET(d, a, b, c, 6, 9, T18);
|
||||||
SET(c, d, a, b, 11, 14, T19);
|
SET(c, d, a, b, 11, 14, T19);
|
||||||
SET(b, c, d, a, 0, 20, T20);
|
SET(b, c, d, a, 0, 20, T20);
|
||||||
SET(a, b, c, d, 5, 5, T21);
|
SET(a, b, c, d, 5, 5, T21);
|
||||||
SET(d, a, b, c, 10, 9, T22);
|
SET(d, a, b, c, 10, 9, T22);
|
||||||
SET(c, d, a, b, 15, 14, T23);
|
SET(c, d, a, b, 15, 14, T23);
|
||||||
SET(b, c, d, a, 4, 20, T24);
|
SET(b, c, d, a, 4, 20, T24);
|
||||||
SET(a, b, c, d, 9, 5, T25);
|
SET(a, b, c, d, 9, 5, T25);
|
||||||
SET(d, a, b, c, 14, 9, T26);
|
SET(d, a, b, c, 14, 9, T26);
|
||||||
SET(c, d, a, b, 3, 14, T27);
|
SET(c, d, a, b, 3, 14, T27);
|
||||||
SET(b, c, d, a, 8, 20, T28);
|
SET(b, c, d, a, 8, 20, T28);
|
||||||
SET(a, b, c, d, 13, 5, T29);
|
SET(a, b, c, d, 13, 5, T29);
|
||||||
SET(d, a, b, c, 2, 9, T30);
|
SET(d, a, b, c, 2, 9, T30);
|
||||||
SET(c, d, a, b, 7, 14, T31);
|
SET(c, d, a, b, 7, 14, T31);
|
||||||
SET(b, c, d, a, 12, 20, T32);
|
SET(b, c, d, a, 12, 20, T32);
|
||||||
#undef SET
|
#undef SET
|
||||||
|
|
||||||
/* Round 3. */
|
/* Round 3. */
|
||||||
/* Let [abcd k s t] denote the operation
|
/* Let [abcd k s t] denote the operation
|
||||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||||
#define SET(a, b, c, d, k, s, Ti)\
|
#define SET(a, b, c, d, k, s, Ti) \
|
||||||
t = a + H(b,c,d) + X[k] + Ti;\
|
t = a + H(b, c, d) + X[k] + Ti; \
|
||||||
a = ROTATE_LEFT(t, s) + b
|
a = ROTATE_LEFT(t, s) + b
|
||||||
/* Do the following 16 operations. */
|
/* Do the following 16 operations. */
|
||||||
SET(a, b, c, d, 5, 4, T33);
|
SET(a, b, c, d, 5, 4, T33);
|
||||||
SET(d, a, b, c, 8, 11, T34);
|
SET(d, a, b, c, 8, 11, T34);
|
||||||
SET(c, d, a, b, 11, 16, T35);
|
SET(c, d, a, b, 11, 16, T35);
|
||||||
SET(b, c, d, a, 14, 23, T36);
|
SET(b, c, d, a, 14, 23, T36);
|
||||||
SET(a, b, c, d, 1, 4, T37);
|
SET(a, b, c, d, 1, 4, T37);
|
||||||
SET(d, a, b, c, 4, 11, T38);
|
SET(d, a, b, c, 4, 11, T38);
|
||||||
SET(c, d, a, b, 7, 16, T39);
|
SET(c, d, a, b, 7, 16, T39);
|
||||||
SET(b, c, d, a, 10, 23, T40);
|
SET(b, c, d, a, 10, 23, T40);
|
||||||
SET(a, b, c, d, 13, 4, T41);
|
SET(a, b, c, d, 13, 4, T41);
|
||||||
SET(d, a, b, c, 0, 11, T42);
|
SET(d, a, b, c, 0, 11, T42);
|
||||||
SET(c, d, a, b, 3, 16, T43);
|
SET(c, d, a, b, 3, 16, T43);
|
||||||
SET(b, c, d, a, 6, 23, T44);
|
SET(b, c, d, a, 6, 23, T44);
|
||||||
SET(a, b, c, d, 9, 4, T45);
|
SET(a, b, c, d, 9, 4, T45);
|
||||||
SET(d, a, b, c, 12, 11, T46);
|
SET(d, a, b, c, 12, 11, T46);
|
||||||
SET(c, d, a, b, 15, 16, T47);
|
SET(c, d, a, b, 15, 16, T47);
|
||||||
SET(b, c, d, a, 2, 23, T48);
|
SET(b, c, d, a, 2, 23, T48);
|
||||||
#undef SET
|
#undef SET
|
||||||
|
|
||||||
/* Round 4. */
|
/* Round 4. */
|
||||||
/* Let [abcd k s t] denote the operation
|
/* Let [abcd k s t] denote the operation
|
||||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||||
#define SET(a, b, c, d, k, s, Ti)\
|
#define SET(a, b, c, d, k, s, Ti) \
|
||||||
t = a + I(b,c,d) + X[k] + Ti;\
|
t = a + I(b, c, d) + X[k] + Ti; \
|
||||||
a = ROTATE_LEFT(t, s) + b
|
a = ROTATE_LEFT(t, s) + b
|
||||||
/* Do the following 16 operations. */
|
/* Do the following 16 operations. */
|
||||||
SET(a, b, c, d, 0, 6, T49);
|
SET(a, b, c, d, 0, 6, T49);
|
||||||
SET(d, a, b, c, 7, 10, T50);
|
SET(d, a, b, c, 7, 10, T50);
|
||||||
SET(c, d, a, b, 14, 15, T51);
|
SET(c, d, a, b, 14, 15, T51);
|
||||||
SET(b, c, d, a, 5, 21, T52);
|
SET(b, c, d, a, 5, 21, T52);
|
||||||
SET(a, b, c, d, 12, 6, T53);
|
SET(a, b, c, d, 12, 6, T53);
|
||||||
SET(d, a, b, c, 3, 10, T54);
|
SET(d, a, b, c, 3, 10, T54);
|
||||||
SET(c, d, a, b, 10, 15, T55);
|
SET(c, d, a, b, 10, 15, T55);
|
||||||
SET(b, c, d, a, 1, 21, T56);
|
SET(b, c, d, a, 1, 21, T56);
|
||||||
SET(a, b, c, d, 8, 6, T57);
|
SET(a, b, c, d, 8, 6, T57);
|
||||||
SET(d, a, b, c, 15, 10, T58);
|
SET(d, a, b, c, 15, 10, T58);
|
||||||
SET(c, d, a, b, 6, 15, T59);
|
SET(c, d, a, b, 6, 15, T59);
|
||||||
SET(b, c, d, a, 13, 21, T60);
|
SET(b, c, d, a, 13, 21, T60);
|
||||||
SET(a, b, c, d, 4, 6, T61);
|
SET(a, b, c, d, 4, 6, T61);
|
||||||
SET(d, a, b, c, 11, 10, T62);
|
SET(d, a, b, c, 11, 10, T62);
|
||||||
SET(c, d, a, b, 2, 15, T63);
|
SET(c, d, a, b, 2, 15, T63);
|
||||||
SET(b, c, d, a, 9, 21, T64);
|
SET(b, c, d, a, 9, 21, T64);
|
||||||
#undef SET
|
#undef SET
|
||||||
|
|
||||||
/* Then perform the following additions. (That is increment each
|
/* Then perform the following additions. (That is increment each
|
||||||
of the four registers by the value it had before this block
|
of the four registers by the value it had before this block
|
||||||
was started.) */
|
was started.) */
|
||||||
pms->abcd[0] += a;
|
pms->abcd[0] += a;
|
||||||
pms->abcd[1] += b;
|
pms->abcd[1] += b;
|
||||||
pms->abcd[2] += c;
|
pms->abcd[2] += c;
|
||||||
pms->abcd[3] += d;
|
pms->abcd[3] += d;
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5_STATIC void
|
MD5_STATIC void md5_init(md5_state_t *pms) {
|
||||||
md5_init(md5_state_t *pms)
|
pms->count[0] = pms->count[1] = 0;
|
||||||
{
|
pms->abcd[0] = 0x67452301;
|
||||||
pms->count[0] = pms->count[1] = 0;
|
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||||
pms->abcd[0] = 0x67452301;
|
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
pms->abcd[3] = 0x10325476;
|
||||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
|
||||||
pms->abcd[3] = 0x10325476;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5_STATIC void
|
MD5_STATIC void md5_append(md5_state_t *pms, const md5_byte_t *data,
|
||||||
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
|
int nbytes) {
|
||||||
{
|
const md5_byte_t *p = data;
|
||||||
const md5_byte_t *p = data;
|
int left = nbytes;
|
||||||
int left = nbytes;
|
int offset = (pms->count[0] >> 3) & 63;
|
||||||
int offset = (pms->count[0] >> 3) & 63;
|
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
||||||
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
|
||||||
|
|
||||||
if (nbytes <= 0)
|
if (nbytes <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Update the message length. */
|
/* Update the message length. */
|
||||||
pms->count[1] += nbytes >> 29;
|
pms->count[1] += nbytes >> 29;
|
||||||
pms->count[0] += nbits;
|
pms->count[0] += nbits;
|
||||||
if (pms->count[0] < nbits)
|
if (pms->count[0] < nbits)
|
||||||
pms->count[1]++;
|
pms->count[1]++;
|
||||||
|
|
||||||
/* Process an initial partial block. */
|
/* Process an initial partial block. */
|
||||||
if (offset) {
|
if (offset) {
|
||||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||||
|
|
||||||
memcpy(pms->buf + offset, p, copy);
|
memcpy(pms->buf + offset, p, copy);
|
||||||
if (offset + copy < 64)
|
if (offset + copy < 64)
|
||||||
return;
|
return;
|
||||||
p += copy;
|
p += copy;
|
||||||
left -= copy;
|
left -= copy;
|
||||||
md5_process(pms, pms->buf);
|
md5_process(pms, pms->buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process full blocks. */
|
/* Process full blocks. */
|
||||||
for (; left >= 64; p += 64, left -= 64)
|
for (; left >= 64; p += 64, left -= 64)
|
||||||
md5_process(pms, p);
|
md5_process(pms, p);
|
||||||
|
|
||||||
/* Process a final partial block. */
|
/* Process a final partial block. */
|
||||||
if (left)
|
if (left)
|
||||||
memcpy(pms->buf, p, left);
|
memcpy(pms->buf, p, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5_STATIC void
|
MD5_STATIC void md5_finish(md5_state_t *pms, md5_byte_t digest[16]) {
|
||||||
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
static const md5_byte_t pad[64] = {
|
||||||
{
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
static const md5_byte_t pad[64] = {
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
md5_byte_t data[8];
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
int i;
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
md5_byte_t data[8];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Save the length before padding. */
|
/* Save the length before padding. */
|
||||||
for (i = 0; i < 8; ++i)
|
for (i = 0; i < 8; ++i)
|
||||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||||
/* Pad to 56 bytes mod 64. */
|
/* Pad to 56 bytes mod 64. */
|
||||||
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||||
/* Append the length. */
|
/* Append the length. */
|
||||||
md5_append(pms, data, 8);
|
md5_append(pms, data, 8);
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||||
}
|
}
|
||||||
|
2275
src/mod_lua.inl
2275
src/mod_lua.inl
File diff suppressed because it is too large
Load Diff
227
src/timer.inl
227
src/timer.inl
@@ -1,131 +1,128 @@
|
|||||||
|
|
||||||
#if !defined(MAX_TIMERS)
|
|
||||||
#define MAX_TIMERS MAX_WORKER_THREADS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef int (*taction)(void *arg);
|
|
||||||
|
|
||||||
struct ttimer {
|
|
||||||
double time;
|
|
||||||
double period;
|
|
||||||
taction action;
|
|
||||||
void * arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ttimers {
|
|
||||||
pthread_t threadid; /* Timer thread ID */
|
|
||||||
pthread_mutex_t mutex; /* Protects timer lists */
|
|
||||||
struct ttimer timers[MAX_TIMERS]; /* List of timers */
|
|
||||||
unsigned timer_count; /* Current size of timer list */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int timer_add(struct mg_context * ctx, double next_time, double period, int is_relative, taction action, void * arg)
|
#if !defined(MAX_TIMERS)
|
||||||
{
|
#define MAX_TIMERS MAX_WORKER_THREADS
|
||||||
unsigned u, v;
|
|
||||||
int error = 0;
|
|
||||||
struct timespec now;
|
|
||||||
|
|
||||||
if (ctx->stop_flag) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_relative) {
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
next_time += now.tv_sec;
|
|
||||||
next_time += now.tv_nsec * 1.0E-9;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&ctx->timers->mutex);
|
|
||||||
if (ctx->timers->timer_count == MAX_TIMERS) {
|
|
||||||
error = 1;
|
|
||||||
} else {
|
|
||||||
for (u=0; u<ctx->timers->timer_count; u++) {
|
|
||||||
if (ctx->timers->timers[u].time < next_time) {
|
|
||||||
for (v=ctx->timers->timer_count; v>u; v--) {
|
|
||||||
ctx->timers->timers[v] = ctx->timers->timers[v-1];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ctx->timers->timers[u].time = next_time;
|
|
||||||
ctx->timers->timers[u].period = period;
|
|
||||||
ctx->timers->timers[u].action = action;
|
|
||||||
ctx->timers->timers[u].arg = arg;
|
|
||||||
ctx->timers->timer_count++;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&ctx->timers->mutex);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timer_thread_run(void *thread_func_param)
|
|
||||||
{
|
|
||||||
struct mg_context *ctx = (struct mg_context *) thread_func_param;
|
|
||||||
struct timespec now;
|
|
||||||
double d;
|
|
||||||
unsigned u;
|
|
||||||
int re_schedule;
|
|
||||||
struct ttimer t;
|
|
||||||
|
|
||||||
#if defined(HAVE_CLOCK_NANOSLEEP) /* Linux with librt */
|
|
||||||
/* TODO */
|
|
||||||
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &request, &request)==EINTR) {/*nop*/;}
|
|
||||||
#else
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
d = (double)now.tv_sec + (double)now.tv_nsec * 1.0E-9;
|
|
||||||
while (ctx->stop_flag == 0) {
|
|
||||||
pthread_mutex_lock(&ctx->timers->mutex);
|
|
||||||
if (ctx->timers->timer_count > 0 && d >= ctx->timers->timers[0].time) {
|
|
||||||
t = ctx->timers->timers[0];
|
|
||||||
for (u=1; u<ctx->timers->timer_count; u++) {
|
|
||||||
ctx->timers->timers[u-1] = ctx->timers->timers[u];
|
|
||||||
}
|
|
||||||
ctx->timers->timer_count--;
|
|
||||||
pthread_mutex_unlock(&ctx->timers->mutex);
|
|
||||||
re_schedule = t.action(t.arg);
|
|
||||||
if (re_schedule && (t.period>0)) {
|
|
||||||
timer_add(ctx, t.time+t.period, t.period, 0, t.action, t.arg);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
pthread_mutex_unlock(&ctx->timers->mutex);
|
|
||||||
}
|
|
||||||
mg_sleep(1);
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
||||||
d = (double)now.tv_sec + (double)now.tv_nsec * 1.0E-9;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef int (*taction)(void *arg);
|
||||||
|
|
||||||
|
struct ttimer {
|
||||||
|
double time;
|
||||||
|
double period;
|
||||||
|
taction action;
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ttimers {
|
||||||
|
pthread_t threadid; /* Timer thread ID */
|
||||||
|
pthread_mutex_t mutex; /* Protects timer lists */
|
||||||
|
struct ttimer timers[MAX_TIMERS]; /* List of timers */
|
||||||
|
unsigned timer_count; /* Current size of timer list */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int timer_add(struct mg_context *ctx, double next_time, double period,
|
||||||
|
int is_relative, taction action, void *arg) {
|
||||||
|
unsigned u, v;
|
||||||
|
int error = 0;
|
||||||
|
struct timespec now;
|
||||||
|
|
||||||
|
if (ctx->stop_flag) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_relative) {
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
next_time += now.tv_sec;
|
||||||
|
next_time += now.tv_nsec * 1.0E-9;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ctx->timers->mutex);
|
||||||
|
if (ctx->timers->timer_count == MAX_TIMERS) {
|
||||||
|
error = 1;
|
||||||
|
} else {
|
||||||
|
for (u = 0; u < ctx->timers->timer_count; u++) {
|
||||||
|
if (ctx->timers->timers[u].time < next_time) {
|
||||||
|
for (v = ctx->timers->timer_count; v > u; v--) {
|
||||||
|
ctx->timers->timers[v] = ctx->timers->timers[v - 1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx->timers->timers[u].time = next_time;
|
||||||
|
ctx->timers->timers[u].period = period;
|
||||||
|
ctx->timers->timers[u].action = action;
|
||||||
|
ctx->timers->timers[u].arg = arg;
|
||||||
|
ctx->timers->timer_count++;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&ctx->timers->mutex);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_thread_run(void *thread_func_param) {
|
||||||
|
struct mg_context *ctx = (struct mg_context *)thread_func_param;
|
||||||
|
struct timespec now;
|
||||||
|
double d;
|
||||||
|
unsigned u;
|
||||||
|
int re_schedule;
|
||||||
|
struct ttimer t;
|
||||||
|
|
||||||
|
#if defined(HAVE_CLOCK_NANOSLEEP) /* Linux with librt */
|
||||||
|
/* TODO */
|
||||||
|
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &request,
|
||||||
|
&request) == EINTR) { /*nop*/
|
||||||
|
;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
d = (double)now.tv_sec + (double)now.tv_nsec * 1.0E-9;
|
||||||
|
while (ctx->stop_flag == 0) {
|
||||||
|
pthread_mutex_lock(&ctx->timers->mutex);
|
||||||
|
if (ctx->timers->timer_count > 0 && d >= ctx->timers->timers[0].time) {
|
||||||
|
t = ctx->timers->timers[0];
|
||||||
|
for (u = 1; u < ctx->timers->timer_count; u++) {
|
||||||
|
ctx->timers->timers[u - 1] = ctx->timers->timers[u];
|
||||||
|
}
|
||||||
|
ctx->timers->timer_count--;
|
||||||
|
pthread_mutex_unlock(&ctx->timers->mutex);
|
||||||
|
re_schedule = t.action(t.arg);
|
||||||
|
if (re_schedule && (t.period > 0)) {
|
||||||
|
timer_add(ctx, t.time + t.period, t.period, 0, t.action, t.arg);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
pthread_mutex_unlock(&ctx->timers->mutex);
|
||||||
|
}
|
||||||
|
mg_sleep(1);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
d = (double)now.tv_sec + (double)now.tv_nsec * 1.0E-9;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static unsigned __stdcall timer_thread(void *thread_func_param)
|
static unsigned __stdcall timer_thread(void *thread_func_param) {
|
||||||
{
|
timer_thread_run(thread_func_param);
|
||||||
timer_thread_run(thread_func_param);
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void *timer_thread(void *thread_func_param)
|
static void *timer_thread(void *thread_func_param) {
|
||||||
{
|
timer_thread_run(thread_func_param);
|
||||||
timer_thread_run(thread_func_param);
|
return NULL;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
static int timers_init(struct mg_context * ctx)
|
static int timers_init(struct mg_context *ctx) {
|
||||||
{
|
ctx->timers = (struct ttimers *)mg_calloc(sizeof(struct ttimers), 1);
|
||||||
ctx->timers = (struct ttimers*) mg_calloc(sizeof(struct ttimers), 1);
|
(void)pthread_mutex_init(&ctx->timers->mutex, NULL);
|
||||||
(void) pthread_mutex_init(&ctx->timers->mutex, NULL);
|
|
||||||
|
|
||||||
/* Start timer thread */
|
/* Start timer thread */
|
||||||
mg_start_thread_with_id(timer_thread, ctx, &ctx->timers->threadid);
|
mg_start_thread_with_id(timer_thread, ctx, &ctx->timers->threadid);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timers_exit(struct mg_context * ctx)
|
static void timers_exit(struct mg_context *ctx) {
|
||||||
{
|
if (ctx->timers) {
|
||||||
if (ctx->timers) {
|
(void)pthread_mutex_destroy(&ctx->timers->mutex);
|
||||||
(void) pthread_mutex_destroy(&ctx->timers->mutex);
|
mg_free(ctx->timers);
|
||||||
mg_free(ctx->timers);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user