pion
5.0.6
|
00001 // --------------------------------------------------------------------- 00002 // pion: a Boost C++ framework for building lightweight HTTP interfaces 00003 // --------------------------------------------------------------------- 00004 // Copyright (C) 2007-2014 Splunk Inc. (https://github.com/splunk/pion) 00005 // 00006 // Distributed under the Boost Software License, Version 1.0. 00007 // See http://www.boost.org/LICENSE_1_0.txt 00008 // 00009 00010 #ifndef __PION_FILESERVICE_HEADER__ 00011 #define __PION_FILESERVICE_HEADER__ 00012 00013 #include <boost/shared_ptr.hpp> 00014 #include <boost/functional/hash.hpp> 00015 #include <boost/filesystem/path.hpp> 00016 #include <boost/thread/once.hpp> 00017 #include <boost/thread/mutex.hpp> 00018 #include <boost/shared_array.hpp> 00019 #include <pion/config.hpp> 00020 #include <pion/logger.hpp> 00021 #include <pion/hash_map.hpp> 00022 #include <pion/http/plugin_service.hpp> 00023 #include <pion/http/request.hpp> 00024 #include <pion/http/response_writer.hpp> 00025 #include <pion/http/server.hpp> 00026 #include <string> 00027 #include <map> 00028 00029 00030 namespace pion { // begin namespace pion 00031 namespace plugins { // begin namespace plugins 00032 00033 00037 class DiskFile { 00038 public: 00040 DiskFile(void) 00041 : m_file_size(0), m_last_modified(0) {} 00042 00044 DiskFile(const boost::filesystem::path& path, 00045 char *content, unsigned long size, 00046 std::time_t modified, const std::string& mime) 00047 : m_file_path(path), m_file_content(content), m_file_size(size), 00048 m_last_modified(modified), m_mime_type(mime) 00049 {} 00050 00052 DiskFile(const DiskFile& f) 00053 : m_file_path(f.m_file_path), m_file_content(f.m_file_content), 00054 m_file_size(f.m_file_size), m_last_modified(f.m_last_modified), 00055 m_last_modified_string(f.m_last_modified_string), m_mime_type(f.m_mime_type) 00056 {} 00057 00059 void update(void); 00060 00062 void read(void); 00063 00069 bool checkUpdated(void); 00070 00072 inline const boost::filesystem::path& getFilePath(void) const { return m_file_path; } 00073 00075 inline char *getFileContent(void) { return m_file_content.get(); } 00076 00078 inline bool hasFileContent(void) const { return static_cast<bool>(m_file_content); } 00079 00081 inline unsigned long getFileSize(void) const { return m_file_size; } 00082 00084 inline std::time_t getLastModified(void) const { return m_last_modified; } 00085 00087 inline const std::string& getLastModifiedString(void) const { return m_last_modified_string; } 00088 00090 inline const std::string& getMimeType(void) const { return m_mime_type; } 00091 00093 inline void setFilePath(const boost::filesystem::path& p) { m_file_path = p; } 00094 00096 inline void appendFilePath(const std::string& p) { m_file_path /= p; } 00097 00099 inline void setMimeType(const std::string& t) { m_mime_type = t; } 00100 00102 inline void resetFileContent(unsigned long n = 0) { 00103 if (n == 0) m_file_content.reset(); 00104 else m_file_content.reset(new char[n]); 00105 } 00106 00107 00108 protected: 00109 00111 boost::filesystem::path m_file_path; 00112 00114 boost::shared_array<char> m_file_content; 00115 00117 std::streamsize m_file_size; 00118 00120 std::time_t m_last_modified; 00121 00123 std::string m_last_modified_string; 00124 00126 std::string m_mime_type; 00127 }; 00128 00129 00133 class DiskFileSender : 00134 public boost::enable_shared_from_this<DiskFileSender>, 00135 private boost::noncopyable 00136 { 00137 public: 00146 static inline boost::shared_ptr<DiskFileSender> 00147 create(DiskFile& file, 00148 pion::http::request_ptr& http_request_ptr, 00149 pion::tcp::connection_ptr& tcp_conn, 00150 unsigned long max_chunk_size = 0) 00151 { 00152 return boost::shared_ptr<DiskFileSender>(new DiskFileSender(file, http_request_ptr, 00153 tcp_conn, max_chunk_size)); 00154 } 00155 00157 virtual ~DiskFileSender() {} 00158 00162 void send(void); 00163 00165 inline void set_logger(logger log_ptr) { m_logger = log_ptr; } 00166 00168 inline logger get_logger(void) { return m_logger; } 00169 00170 00171 protected: 00172 00181 DiskFileSender(DiskFile& file, 00182 pion::http::request_ptr& http_request_ptr, 00183 pion::tcp::connection_ptr& tcp_conn, 00184 unsigned long max_chunk_size); 00185 00192 void handle_write(const boost::system::error_code& write_error, 00193 std::size_t bytes_written); 00194 00195 00197 logger m_logger; 00198 00199 00200 private: 00201 00203 DiskFile m_disk_file; 00204 00206 pion::http::response_writer_ptr m_writer; 00207 00209 boost::filesystem::ifstream m_file_stream; 00210 00212 boost::shared_array<char> m_content_buf; 00213 00219 unsigned long m_max_chunk_size; 00220 00222 unsigned long m_file_bytes_to_send; 00223 00225 unsigned long m_bytes_sent; 00226 }; 00227 00229 typedef boost::shared_ptr<DiskFileSender> DiskFileSenderPtr; 00230 00231 00235 class FileService : 00236 public pion::http::plugin_service 00237 { 00238 public: 00239 00240 // default constructor and destructor 00241 FileService(void); 00242 virtual ~FileService() {} 00243 00254 virtual void set_option(const std::string& name, const std::string& value); 00255 00257 virtual void operator()(pion::http::request_ptr& http_request_ptr, 00258 pion::tcp::connection_ptr& tcp_conn); 00259 00261 virtual void start(void); 00262 00264 virtual void stop(void); 00265 00267 inline void set_logger(logger log_ptr) { m_logger = log_ptr; } 00268 00270 inline logger get_logger(void) { return m_logger; } 00271 00272 00273 protected: 00274 00276 typedef PION_HASH_MAP<std::string, DiskFile, PION_HASH_STRING > CacheMap; 00277 00279 typedef PION_HASH_MAP<std::string, std::string, PION_HASH_STRING > MIMETypeMap; 00280 00286 void scanDirectory(const boost::filesystem::path& dir_path); 00287 00298 std::pair<CacheMap::iterator, bool> 00299 addCacheEntry(const std::string& relative_path, 00300 const boost::filesystem::path& file_path, 00301 const bool placeholder); 00302 00309 static std::string findMIMEType(const std::string& file_name); 00310 00311 void sendNotFoundResponse(pion::http::request_ptr& http_request_ptr, 00312 pion::tcp::connection_ptr& tcp_conn); 00313 00315 logger m_logger; 00316 00317 00318 private: 00319 00321 static void createMIMETypes(void); 00322 00323 00325 static const std::string DEFAULT_MIME_TYPE; 00326 00328 static const unsigned int DEFAULT_CACHE_SETTING; 00329 00331 static const unsigned int DEFAULT_SCAN_SETTING; 00332 00334 static const unsigned long DEFAULT_MAX_CACHE_SIZE; 00335 00337 static const unsigned long DEFAULT_MAX_CHUNK_SIZE; 00338 00340 static boost::once_flag m_mime_types_init_flag; 00341 00343 static MIMETypeMap * m_mime_types_ptr; 00344 00345 00347 boost::filesystem::path m_directory; 00348 00350 boost::filesystem::path m_file; 00351 00353 CacheMap m_cache_map; 00354 00356 boost::mutex m_cache_mutex; 00357 00364 unsigned int m_cache_setting; 00365 00373 unsigned int m_scan_setting; 00374 00379 unsigned long m_max_cache_size; 00380 00386 unsigned long m_max_chunk_size; 00387 00391 bool m_writable; 00392 }; 00393 00394 00395 } // end namespace plugins 00396 } // end namespace pion 00397 00398 #endif