Panda3D

virtualFileMountHTTP.cxx

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
 All Classes Functions Variables Enumerations