00001
00002
00003
00004
00005
00006
00007
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 {
00031 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 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
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 }
00396 }
00397
00398 #endif