00001 // Filename: virtualFileMountHTTP.cxx 00002 // Created by: drose (30Oct08) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "virtualFileMountHTTP.h" 00016 #include "virtualFileHTTP.h" 00017 #include "virtualFileSystem.h" 00018 00019 #ifdef HAVE_OPENSSL 00020 00021 TypeHandle VirtualFileMountHTTP::_type_handle; 00022 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: VirtualFileMountHTTP::Constructor 00026 // Access: Published 00027 // Description: 00028 //////////////////////////////////////////////////////////////////// 00029 VirtualFileMountHTTP:: 00030 VirtualFileMountHTTP(const URLSpec &root, HTTPClient *http) : 00031 _http(http), 00032 _root(root) 00033 { 00034 // Make sure the root ends on a slash. The implicit trailing slash 00035 // is a semi-standard internet convention. 00036 string path = _root.get_path(); 00037 if (!path.empty() && path[path.length() - 1] != '/') { 00038 path += '/'; 00039 _root.set_path(path); 00040 } 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: VirtualFileMountHTTP::Destructor 00045 // Access: Public, Virtual 00046 // Description: 00047 //////////////////////////////////////////////////////////////////// 00048 VirtualFileMountHTTP:: 00049 ~VirtualFileMountHTTP() { 00050 } 00051 00052 00053 //////////////////////////////////////////////////////////////////// 00054 // Function: VirtualFileMountHTTP::reload_vfs_mount_url 00055 // Access: Published, Static 00056 // Description: Reads all of the vfs-mount-url lines in the 00057 // Config.prc file and replaces the mount settings to 00058 // match them. 00059 // 00060 // This will mount any url's mentioned in the config 00061 // file, and unmount and unmount any url's no longer 00062 // mentioned in the config file. Normally, it is called 00063 // automatically at startup, and need not be called 00064 // again, unless you have fiddled with some config 00065 // settings. 00066 //////////////////////////////////////////////////////////////////// 00067 void VirtualFileMountHTTP:: 00068 reload_vfs_mount_url() { 00069 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00070 00071 // First, unload the existing mounts. 00072 int n = 0; 00073 while (n < vfs->get_num_mounts()) { 00074 PT(VirtualFileMount) mount = vfs->get_mount(n); 00075 if (mount->is_of_type(VirtualFileMountHTTP::get_class_type())) { 00076 vfs->unmount(mount); 00077 // Don't increment n. 00078 } else { 00079 ++n; 00080 } 00081 } 00082 00083 // Now, reload the newly specified mounts. 00084 ConfigVariableList mounts 00085 ("vfs-mount-url", 00086 PRC_DESC("vfs-mount-url http://site/path[:port] mount-point [options]")); 00087 00088 int num_unique_values = mounts.get_num_unique_values(); 00089 for (int i = 0; i < num_unique_values; i++) { 00090 string mount_desc = mounts.get_unique_value(i); 00091 00092 size_t space = mount_desc.rfind(' '); 00093 if (space == string::npos) { 00094 downloader_cat.warning() 00095 << "No space in vfs-mount-url descriptor: " << mount_desc << "\n"; 00096 00097 } else { 00098 string mount_point = mount_desc.substr(space + 1); 00099 while (space > 0 && isspace(mount_desc[space - 1])) { 00100 space--; 00101 } 00102 mount_desc = mount_desc.substr(0, space); 00103 string options; 00104 00105 space = mount_desc.rfind(' '); 00106 if (space != string::npos) { 00107 // If there's another space, we have the optional options field. 00108 options = mount_point; 00109 mount_point = mount_desc.substr(space + 1); 00110 while (space > 0 && isspace(mount_desc[space - 1])) { 00111 --space; 00112 } 00113 mount_desc = mount_desc.substr(0, space); 00114 } 00115 00116 mount_desc = ExecutionEnvironment::expand_string(mount_desc); 00117 URLSpec root(mount_desc); 00118 00119 int flags = 0; 00120 string password; 00121 00122 // Split the options up by commas. 00123 size_t p = 0; 00124 size_t q = options.find(',', p); 00125 while (q != string::npos) { 00126 vfs->parse_option(options.substr(p, q - p), 00127 flags, password); 00128 p = q + 1; 00129 q = options.find(',', p); 00130 } 00131 vfs->parse_option(options.substr(p), flags, password); 00132 00133 PT(VirtualFileMount) mount = new VirtualFileMountHTTP(root); 00134 vfs->mount(mount, mount_point, flags); 00135 } 00136 } 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: VirtualFileMountHTTP::has_file 00141 // Access: Public, Virtual 00142 // Description: Returns true if the indicated file exists within the 00143 // mount system. 00144 //////////////////////////////////////////////////////////////////// 00145 bool VirtualFileMountHTTP:: 00146 has_file(const Filename &) const { 00147 return false; 00148 } 00149 00150 //////////////////////////////////////////////////////////////////// 00151 // Function: VirtualFileMountHTTP::is_directory 00152 // Access: Public, Virtual 00153 // Description: Returns true if the indicated file exists within the 00154 // mount system and is a directory. 00155 //////////////////////////////////////////////////////////////////// 00156 bool VirtualFileMountHTTP:: 00157 is_directory(const Filename &) const { 00158 return false; 00159 } 00160 00161 //////////////////////////////////////////////////////////////////// 00162 // Function: VirtualFileMountHTTP::is_regular_file 00163 // Access: Public, Virtual 00164 // Description: Returns true if the indicated file exists within the 00165 // mount system and is a regular file. 00166 //////////////////////////////////////////////////////////////////// 00167 bool VirtualFileMountHTTP:: 00168 is_regular_file(const Filename &) const { 00169 return false; 00170 } 00171 00172 //////////////////////////////////////////////////////////////////// 00173 // Function: VirtualFileMountHTTP::make_virtual_file 00174 // Access: Public, Virtual 00175 // Description: Constructs and returns a new VirtualFile instance 00176 // that corresponds to the indicated filename within 00177 // this mount point. The returned VirtualFile object 00178 // does not imply that the given file actually exists; 00179 // but if the file does exist, then the handle can be 00180 // used to read it. 00181 //////////////////////////////////////////////////////////////////// 00182 PT(VirtualFile) VirtualFileMountHTTP:: 00183 make_virtual_file(const Filename &local_filename, 00184 const Filename &original_filename, bool implicit_pz_file, 00185 int open_flags) { 00186 PT(VirtualFileHTTP) vfile = 00187 new VirtualFileHTTP(this, local_filename, implicit_pz_file, open_flags); 00188 vfile->set_original_filename(original_filename); 00189 00190 return vfile.p(); 00191 } 00192 00193 //////////////////////////////////////////////////////////////////// 00194 // Function: VirtualFileMountHTTP::open_read_file 00195 // Access: Public, Virtual 00196 // Description: Opens the file for reading, if it exists. Returns a 00197 // newly allocated istream on success (which you should 00198 // eventually delete when you are done reading). 00199 // Returns NULL on failure. 00200 //////////////////////////////////////////////////////////////////// 00201 istream *VirtualFileMountHTTP:: 00202 open_read_file(const Filename &) const { 00203 return NULL; 00204 } 00205 00206 //////////////////////////////////////////////////////////////////// 00207 // Function: VirtualFileMountHTTP::get_file_size 00208 // Access: Published, Virtual 00209 // Description: Returns the current size on disk (or wherever it is) 00210 // of the already-open file. Pass in the stream that 00211 // was returned by open_read_file(); some 00212 // implementations may require this stream to determine 00213 // the size. 00214 //////////////////////////////////////////////////////////////////// 00215 off_t VirtualFileMountHTTP:: 00216 get_file_size(const Filename &, istream *) const { 00217 return 0; 00218 } 00219 00220 //////////////////////////////////////////////////////////////////// 00221 // Function: VirtualFileMountHTTP::get_file_size 00222 // Access: Published, Virtual 00223 // Description: Returns the current size on disk (or wherever it is) 00224 // of the file before it has been opened. 00225 //////////////////////////////////////////////////////////////////// 00226 off_t VirtualFileMountHTTP:: 00227 get_file_size(const Filename &) const { 00228 return 0; 00229 } 00230 00231 //////////////////////////////////////////////////////////////////// 00232 // Function: VirtualFileMountHTTP::get_timestamp 00233 // Access: Published, Virtual 00234 // Description: Returns a time_t value that represents the time the 00235 // file was last modified, to within whatever precision 00236 // the operating system records this information (on a 00237 // Windows95 system, for instance, this may only be 00238 // accurate to within 2 seconds). 00239 // 00240 // If the timestamp cannot be determined, either because 00241 // it is not supported by the operating system or 00242 // because there is some error (such as file not found), 00243 // returns 0. 00244 //////////////////////////////////////////////////////////////////// 00245 time_t VirtualFileMountHTTP:: 00246 get_timestamp(const Filename &) const { 00247 return 0; 00248 } 00249 00250 //////////////////////////////////////////////////////////////////// 00251 // Function: VirtualFileMountHTTP::scan_directory 00252 // Access: Public, Virtual 00253 // Description: Fills the given vector up with the list of filenames 00254 // that are local to this directory, if the filename is 00255 // a directory. Returns true if successful, or false if 00256 // the file is not a directory or cannot be read. 00257 //////////////////////////////////////////////////////////////////// 00258 bool VirtualFileMountHTTP:: 00259 scan_directory(vector_string &, const Filename &) const { 00260 return false; 00261 } 00262 00263 //////////////////////////////////////////////////////////////////// 00264 // Function: VirtualFileMountHTTP::output 00265 // Access: Public, Virtual 00266 // Description: 00267 //////////////////////////////////////////////////////////////////// 00268 void VirtualFileMountHTTP:: 00269 output(ostream &out) const { 00270 out << _root; 00271 } 00272 00273 //////////////////////////////////////////////////////////////////// 00274 // Function: VirtualFileMountHTTP::get_channel 00275 // Access: Public 00276 // Description: Returns an HTTPChannel object suitable for use for 00277 // extracting a document from the current URL root. 00278 //////////////////////////////////////////////////////////////////// 00279 PT(HTTPChannel) VirtualFileMountHTTP:: 00280 get_channel() { 00281 PT(HTTPChannel) channel; 00282 _channels_lock.acquire(); 00283 00284 if (!_channels.empty()) { 00285 // If we have some channels sitting around, grab one. Grab the 00286 // one on the end; it was most recently pushed, and therefore most 00287 // likely to be still alive. 00288 channel = _channels.back(); 00289 _channels.pop_back(); 00290 } else { 00291 // If we don't have any channels standing by, make a new one. 00292 channel = _http->make_channel(true); 00293 } 00294 00295 _channels_lock.release(); 00296 return channel; 00297 } 00298 00299 //////////////////////////////////////////////////////////////////// 00300 // Function: VirtualFileMountHTTP::recycle_channel 00301 // Access: Public 00302 // Description: Accepts an HTTPChannel that is no longer being used, 00303 // and restores it to standby duty, so that it will be 00304 // returned by a future call to get_channel(). 00305 //////////////////////////////////////////////////////////////////// 00306 void VirtualFileMountHTTP:: 00307 recycle_channel(HTTPChannel *channel) { 00308 _channels_lock.acquire(); 00309 _channels.push_back(channel); 00310 _channels_lock.release(); 00311 } 00312 00313 #endif // HAVE_OPENSSL