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

ProxyClientSession.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   ProxyClientSession - Base class for protocol client sessions.
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 "HttpConfig.h"
00025 #include "HttpDebugNames.h"
00026 #include "ProxyClientSession.h"
00027 
00028 static int64_t next_cs_id = 0;
00029 
00030 ProxyClientSession::ProxyClientSession()
00031     : VConnection(NULL), debug_on(false), hooks_on(true)
00032 {
00033   ink_zero(this->user_args);
00034 }
00035 
00036 int64_t
00037 ProxyClientSession::next_connection_id()
00038 {
00039   return ink_atomic_increment(&next_cs_id, 1);
00040 }
00041 
00042 static const TSEvent eventmap[TS_HTTP_LAST_HOOK + 1] = {
00043   TS_EVENT_HTTP_READ_REQUEST_HDR,       // TS_HTTP_READ_REQUEST_HDR_HOOK
00044   TS_EVENT_HTTP_OS_DNS,                 // TS_HTTP_OS_DNS_HOOK
00045   TS_EVENT_HTTP_SEND_REQUEST_HDR,       // TS_HTTP_SEND_REQUEST_HDR_HOOK
00046   TS_EVENT_HTTP_READ_CACHE_HDR,         // TS_HTTP_READ_CACHE_HDR_HOOK
00047   TS_EVENT_HTTP_READ_RESPONSE_HDR,      // TS_HTTP_READ_RESPONSE_HDR_HOOK
00048   TS_EVENT_HTTP_SEND_RESPONSE_HDR,      // TS_HTTP_SEND_RESPONSE_HDR_HOOK
00049   TS_EVENT_HTTP_REQUEST_TRANSFORM,      // TS_HTTP_REQUEST_TRANSFORM_HOOK
00050   TS_EVENT_HTTP_RESPONSE_TRANSFORM,     // TS_HTTP_RESPONSE_TRANSFORM_HOOK
00051   TS_EVENT_HTTP_SELECT_ALT,             // TS_HTTP_SELECT_ALT_HOOK
00052   TS_EVENT_HTTP_TXN_START,              // TS_HTTP_TXN_START_HOOK
00053   TS_EVENT_HTTP_TXN_CLOSE,              // TS_HTTP_TXN_CLOSE_HOOK
00054   TS_EVENT_HTTP_SSN_START,              // TS_HTTP_SSN_START_HOOK
00055   TS_EVENT_HTTP_SSN_CLOSE,              // TS_HTTP_SSN_CLOSE_HOOK
00056   TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE,  // TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK
00057   TS_EVENT_HTTP_PRE_REMAP,              // TS_HTTP_PRE_REMAP_HOOK
00058   TS_EVENT_HTTP_POST_REMAP,             // TS_HTTP_POST_REMAP_HOOK
00059   TS_EVENT_NONE,                        // TS_HTTP_RESPONSE_CLIENT_HOOK
00060   TS_EVENT_NONE,                        // TS_HTTP_LAST_HOOK
00061 };
00062 
00063 static bool
00064 is_valid_hook(TSHttpHookID hookid) {
00065   return (hookid >= 0) && (hookid < TS_HTTP_LAST_HOOK);
00066 }
00067 
00068 void
00069 ProxyClientSession::cleanup()
00070 {
00071   this->api_hooks.clear();
00072   this->mutex.clear();
00073 }
00074 
00075 int
00076 ProxyClientSession::state_api_callout(int event, void * /* data ATS_UNUSED */)
00077 {
00078   switch (event) {
00079   case EVENT_NONE:
00080   case EVENT_INTERVAL:
00081   case TS_EVENT_HTTP_CONTINUE:
00082     if (likely(is_valid_hook(this->api_hookid))) {
00083       if (this->api_current == NULL && this->api_scope == API_HOOK_SCOPE_GLOBAL) {
00084         this->api_current = http_global_hooks->get(this->api_hookid);
00085         this->api_scope = API_HOOK_SCOPE_LOCAL;
00086       }
00087 
00088       if (this->api_current == NULL && this->api_scope == API_HOOK_SCOPE_LOCAL) {
00089         this->api_current = ssn_hook_get(this->api_hookid);
00090         this->api_scope = API_HOOK_SCOPE_NONE;
00091       }
00092 
00093       if (this->api_current) {
00094         bool            plugin_lock = false;
00095         APIHook *       hook = this->api_current;
00096         Ptr<ProxyMutex> plugin_mutex;
00097 
00098         if (hook->m_cont->mutex) {
00099           plugin_mutex = hook->m_cont->mutex;
00100           plugin_lock = MUTEX_TAKE_TRY_LOCK(hook->m_cont->mutex, mutex->thread_holding);
00101           if (!plugin_lock) {
00102             SET_HANDLER(&ProxyClientSession::state_api_callout);
00103             mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
00104             return 0;
00105           }
00106         }
00107 
00108         this->api_current = this->api_current->next();
00109         hook->invoke(eventmap[this->api_hookid], this);
00110 
00111         if (plugin_lock) {
00112           Mutex_unlock(plugin_mutex, this_ethread());
00113         }
00114 
00115         return 0;
00116       }
00117     }
00118 
00119     handle_api_return(event);
00120     break;
00121 
00122   case TS_EVENT_HTTP_ERROR:
00123     this->handle_api_return(event);
00124     break;
00125 
00126   // coverity[unterminated_default]
00127   default:
00128     ink_assert(false);
00129   }
00130 
00131   return 0;
00132 }
00133 
00134 void
00135 ProxyClientSession::do_api_callout(TSHttpHookID id)
00136 {
00137   ink_assert(id == TS_HTTP_SSN_START_HOOK || id == TS_HTTP_SSN_CLOSE_HOOK);
00138 
00139   this->api_hookid = id;
00140   this->api_scope = API_HOOK_SCOPE_GLOBAL;
00141   this->api_current = NULL;
00142 
00143   if (this->hooks_on && this->has_hooks()) {
00144     SET_HANDLER(&ProxyClientSession::state_api_callout);
00145     this->state_api_callout(EVENT_NONE, NULL);
00146   } else {
00147     this->handle_api_return(TS_EVENT_HTTP_CONTINUE);
00148   }
00149 }
00150 
00151 void
00152 ProxyClientSession::handle_api_return(int event)
00153 {
00154   TSHttpHookID hookid = this->api_hookid;
00155 
00156   SET_HANDLER(&ProxyClientSession::state_api_callout);
00157 
00158   this->api_hookid = TS_HTTP_LAST_HOOK;
00159   this->api_scope = API_HOOK_SCOPE_NONE;
00160   this->api_current = NULL;
00161 
00162   switch (hookid) {
00163   case TS_HTTP_SSN_START_HOOK:
00164     if (event == TS_EVENT_HTTP_ERROR) {
00165       this->do_io_close();
00166     } else {
00167       this->start();
00168     }
00169     break;
00170   case TS_HTTP_SSN_CLOSE_HOOK:
00171     this->destroy();
00172     break;
00173   default:
00174     Fatal("received invalid session hook %s (%d)", HttpDebugNames::get_api_hook_name(hookid), hookid);
00175     break;
00176   }
00177 }

Generated by  doxygen 1.7.1