• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

RemapPlugins.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   Class to execute one (or more) remap plugin(s).
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #include "RemapPlugins.h"
00025 
00026 ClassAllocator<RemapPlugins> pluginAllocator("RemapPluginsAlloc");
00027 
00028 TSRemapStatus
00029 RemapPlugins::run_plugin(remap_plugin_info* plugin)
00030 {
00031   TSRemapStatus plugin_retcode;
00032   TSRemapRequestInfo rri;
00033   url_mapping *map = _s->url_map.getMapping();
00034   URL * map_from = _s->url_map.getFromURL();
00035   URL * map_to = _s->url_map.getToURL();
00036 
00037   // This is the equivalent of TSHttpTxnClientReqGet(), which every remap plugin would
00038   // have to call.
00039   rri.requestBufp = reinterpret_cast<TSMBuffer>(_request_header);
00040   rri.requestHdrp = reinterpret_cast<TSMLoc>(_request_header->m_http);
00041 
00042   // Read-only URL's (TSMLoc's to the SDK)
00043   rri.mapFromUrl = reinterpret_cast<TSMLoc>(map_from->m_url_impl);
00044   rri.mapToUrl = reinterpret_cast<TSMLoc>(map_to->m_url_impl);
00045   rri.requestUrl = reinterpret_cast<TSMLoc>(_request_url->m_url_impl);
00046 
00047   rri.redirect = 0;
00048 
00049   // These are made to reflect the "defaults" that will be used in
00050   // the case where the plugins don't modify them. It's semi-weird
00051   // that the "from" and "to" URLs changes when chaining happens, but
00052   // it is necessary to get predictable behavior.
00053 #if 0
00054   if (_cur == 0) {
00055     rri.remap_from_host = map_from->host_get(&rri.remap_from_host_size);
00056     rri.remap_from_port = map_from->port_get();
00057     rri.remap_from_path = map_from->path_get(&rri.remap_from_path_size);
00058     rri.from_scheme = map_from->scheme_get(&rri.from_scheme_len);
00059   } else {
00060     rri.remap_from_host = _request_url->host_get(&rri.remap_from_host_size);
00061     rri.remap_from_port = _request_url->port_get();
00062     rri.remap_from_path = _request_url->path_get(&rri.remap_from_path_size);
00063     rri.from_scheme = _request_url->scheme_get(&rri.from_scheme_len);
00064   }
00065 #endif
00066 
00067   void* ih = map->get_instance(_cur);
00068 
00069   // Prepare State for the future
00070   if (_s && _cur == 0) {
00071     _s->fp_tsremap_os_response = plugin->fp_tsremap_os_response;
00072     _s->remap_plugin_instance = ih;
00073   }
00074 
00075   plugin_retcode = plugin->fp_tsremap_do_remap(ih, _s ? reinterpret_cast<TSHttpTxn>(_s->state_machine) : NULL, &rri);
00076   // TODO: Deal with negative return codes here
00077   if (plugin_retcode < 0)
00078     plugin_retcode = TSREMAP_NO_REMAP;
00079 
00080   // First step after plugin remap must be "redirect url" check
00081   if ((TSREMAP_DID_REMAP == plugin_retcode || TSREMAP_DID_REMAP_STOP == plugin_retcode) && rri.redirect)
00082     _s->remap_redirect = _request_url->string_get(NULL);
00083 
00084   return plugin_retcode;
00085 }
00086 
00087 /**
00088   This is the equivalent of the old DoRemap().
00089 
00090   @return 1 when you are done doing crap (otherwise, you get re-called
00091     with schedule_imm and i hope you have something more to do), else
00092     0 if you have something more do do (this isnt strict and we check
00093     there actually *is* something to do).
00094 
00095 */
00096 int
00097 RemapPlugins::run_single_remap()
00098 {
00099 
00100   url_mapping *       map = _s->url_map.getMapping();
00101   remap_plugin_info * plugin = map->get_plugin(_cur);    //get the nth plugin in our list of plugins
00102   TSRemapStatus       plugin_retcode = TSREMAP_NO_REMAP;
00103 
00104   Debug("url_rewrite", "running single remap rule id %d for the %d%s time",
00105       map->map_id, _cur, _cur == 1 ? "st" : _cur == 2 ? "nd" : _cur == 3 ? "rd" : "th");
00106 
00107   // There might not be a plugin if we are a regular non-plugin map rule. In that case, we will fall through
00108   // and do the default mapping and then stop.
00109   if (plugin) {
00110     plugin_retcode = run_plugin(plugin);
00111   }
00112 
00113   _cur++;
00114 
00115   // If the plugin redirected, we need to end the remap chain now.
00116   if (_s->remap_redirect) {
00117     return 1;
00118   }
00119 
00120   if (TSREMAP_NO_REMAP == plugin_retcode || TSREMAP_NO_REMAP_STOP == plugin_retcode) {
00121     // After running the first plugin, rewrite the request URL. This is doing the default rewrite rule
00122     // to handle the case where no plugin ever rewrites.
00123     //
00124     // XXX we could probably optimize this a bit more by keeping a flag and only rewriting the request URL
00125     // if no plugin has rewritten it already.
00126     if ((_cur == 1) && (HTTP_WKSIDX_CONNECT != _s->hdr_info.client_request.method_get_wksidx())) {
00127       Debug("url_rewrite", "plugin did not change host, port or path, copying from mapping rule");
00128       url_rewrite_remap_request(_s->url_map, _request_url);
00129     }
00130   }
00131 
00132   if (TSREMAP_NO_REMAP_STOP == plugin_retcode || TSREMAP_DID_REMAP_STOP == plugin_retcode) {
00133       Debug("url_rewrite", "breaking remap plugin chain since last plugin said we should stop");
00134       return 1;
00135   }
00136 
00137   if (_cur > MAX_REMAP_PLUGIN_CHAIN) {
00138     Error("called %s more than %u times; stopping this remap insanity now", __func__, MAX_REMAP_PLUGIN_CHAIN);
00139     return 1;
00140   }
00141 
00142   if (_cur >= map->_plugin_count) {
00143     // Normally, we would callback into this function but we dont have anything more to do!
00144     Debug("url_rewrite", "completed all remap plugins for rule id %d", map->map_id);
00145     return 1;
00146   }
00147 
00148   Debug("url_rewrite", "completed single remap, attempting another via immediate callback");
00149   return 0;
00150 }
00151 
00152 int
00153 RemapPlugins::run_remap(int event, Event* e)
00154 {
00155   Debug("url_rewrite", "Inside RemapPlugins::run_remap with cur = %d", _cur);
00156 
00157   ink_assert(action.continuation);
00158   ink_assert(action.continuation);
00159 
00160   int ret = 0;
00161 
00162   /* make sure we weren't cancelled */
00163   if (action.cancelled) {
00164     mutex.clear();
00165     pluginAllocator.free(this); //ugly
00166     return EVENT_DONE;
00167   }
00168 
00169   switch (event) {
00170   case EVENT_IMMEDIATE:
00171     Debug("url_rewrite", "handling immediate event inside RemapPlugins::run_remap");
00172     ret = run_single_remap();
00173     /**
00174      * If ret !=0 then we are done with this processor and we call back into the SM;
00175      * otherwise, we call this function again immediately (which really isn't immediate)
00176      * thru the eventProcessor, thus forcing another run of run_single_remap() which will
00177      * then operate on _request_url, etc performing additional remaps (mainly another plugin run)
00178      **/
00179     if (ret) {
00180       action.continuation->handleEvent(EVENT_REMAP_COMPLETE, NULL);
00181       mutex.clear();
00182       action.mutex.clear();
00183       mutex = NULL;
00184       action.mutex = NULL;
00185       //THREAD_FREE(this, pluginAllocator, t);
00186       pluginAllocator.free(this);       //ugly
00187       return EVENT_DONE;
00188     } else {
00189       e->schedule_imm(event);
00190       return EVENT_CONT;
00191     }
00192 
00193     break;
00194   default:
00195     ink_assert(!"unknown event type");
00196     break;
00197   };
00198   return EVENT_DONE;
00199 }

Generated by  doxygen 1.7.1