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