1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/*
* Copyright (C) 2005-2018 Team Kodi
* This file is part of Kodi - https://kodi.tv
*
* SPDX-License-Identifier: GPL-2.0-or-later
* See LICENSES/README.md for more information.
*/
#pragma once
#include "network/httprequesthandler/IHTTPRequestHandler.h"
#include "threads/CriticalSection.h"
#include "utils/logtypes.h"
#include <memory>
#include <vector>
namespace XFILE
{
class CFile;
}
class CDateTime;
class CVariant;
class CWebServer
{
public:
CWebServer();
virtual ~CWebServer() = default;
bool Start(uint16_t port, const std::string &username, const std::string &password);
bool Stop();
bool IsStarted();
static bool WebServerSupportsSSL();
void SetCredentials(const std::string &username, const std::string &password);
void RegisterRequestHandler(IHTTPRequestHandler *handler);
void UnregisterRequestHandler(IHTTPRequestHandler *handler);
protected:
typedef struct ConnectionHandler
{
std::string fullUri;
bool isNew;
std::shared_ptr<IHTTPRequestHandler> requestHandler;
struct MHD_PostProcessor *postprocessor;
int errorStatus;
explicit ConnectionHandler(const std::string& uri)
: fullUri(uri)
, isNew(true)
, requestHandler(nullptr)
, postprocessor(nullptr)
, errorStatus(MHD_HTTP_OK)
{ }
} ConnectionHandler;
virtual void LogRequest(const char* uri) const;
virtual MHD_RESULT HandlePartialRequest(struct MHD_Connection *connection, ConnectionHandler* connectionHandler, const HTTPRequest& request,
const char *upload_data, size_t *upload_data_size, void **con_cls);
virtual MHD_RESULT HandleRequest(const std::shared_ptr<IHTTPRequestHandler>& handler);
virtual MHD_RESULT FinalizeRequest(const std::shared_ptr<IHTTPRequestHandler>& handler, int responseStatus, struct MHD_Response *response);
private:
struct MHD_Daemon* StartMHD(unsigned int flags, int port);
std::shared_ptr<IHTTPRequestHandler> FindRequestHandler(const HTTPRequest& request) const;
MHD_RESULT AskForAuthentication(const HTTPRequest& request) const;
bool IsAuthenticated(const HTTPRequest& request) const;
bool IsRequestCacheable(const HTTPRequest& request) const;
bool IsRequestRanged(const HTTPRequest& request, const CDateTime &lastModified) const;
void SetupPostDataProcessing(const HTTPRequest& request, ConnectionHandler *connectionHandler, std::shared_ptr<IHTTPRequestHandler> handler, void **con_cls) const;
bool ProcessPostData(const HTTPRequest& request, ConnectionHandler *connectionHandler, const char *upload_data, size_t *upload_data_size, void **con_cls) const;
void FinalizePostDataProcessing(ConnectionHandler *connectionHandler) const;
MHD_RESULT CreateMemoryDownloadResponse(const std::shared_ptr<IHTTPRequestHandler>& handler, struct MHD_Response *&response) const;
MHD_RESULT CreateRangedMemoryDownloadResponse(const std::shared_ptr<IHTTPRequestHandler>& handler, struct MHD_Response *&response) const;
MHD_RESULT CreateRedirect(struct MHD_Connection *connection, const std::string &strURL, struct MHD_Response *&response) const;
MHD_RESULT CreateFileDownloadResponse(const std::shared_ptr<IHTTPRequestHandler>& handler, struct MHD_Response *&response) const;
MHD_RESULT CreateErrorResponse(struct MHD_Connection *connection, int responseType, HTTPMethod method, struct MHD_Response *&response) const;
MHD_RESULT CreateMemoryDownloadResponse(struct MHD_Connection *connection, const void *data, size_t size, bool free, bool copy, struct MHD_Response *&response) const;
MHD_RESULT SendResponse(const HTTPRequest& request, int responseStatus, MHD_Response *response) const;
MHD_RESULT SendErrorResponse(const HTTPRequest& request, int errorType, HTTPMethod method) const;
MHD_RESULT AddHeader(struct MHD_Response *response, const std::string &name, const std::string &value) const;
void LogRequest(const HTTPRequest& request) const;
void LogResponse(const HTTPRequest& request, int responseStatus) const;
static std::string CreateMimeTypeFromExtension(const char *ext);
// MHD callback implementations
static void* UriRequestLogger(void *cls, const char *uri);
static ssize_t ContentReaderCallback (void *cls, uint64_t pos, char *buf, size_t max);
static void ContentReaderFreeCallback(void *cls);
static MHD_RESULT AnswerToConnection (void *cls, struct MHD_Connection *connection,
const char *url, const char *method,
const char *version, const char *upload_data,
size_t *upload_data_size, void **con_cls);
static MHD_RESULT HandlePostField(void *cls, enum MHD_ValueKind kind, const char *key,
const char *filename, const char *content_type,
const char *transfer_encoding, const char *data, uint64_t off,
size_t size);
bool LoadCert(std::string &skey, std::string &scert);
static Logger GetLogger();
uint16_t m_port = 0;
struct MHD_Daemon *m_daemon_ip6 = nullptr;
struct MHD_Daemon *m_daemon_ip4 = nullptr;
bool m_running = false;
size_t m_thread_stacksize = 0;
bool m_authenticationRequired = false;
std::string m_authenticationUsername;
std::string m_authenticationPassword;
std::string m_key;
std::string m_cert;
mutable CCriticalSection m_critSection;
std::vector<IHTTPRequestHandler *> m_requestHandlers;
Logger m_logger;
};
|