Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
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,       
00044   TS_EVENT_HTTP_OS_DNS,                 
00045   TS_EVENT_HTTP_SEND_REQUEST_HDR,       
00046   TS_EVENT_HTTP_READ_CACHE_HDR,         
00047   TS_EVENT_HTTP_READ_RESPONSE_HDR,      
00048   TS_EVENT_HTTP_SEND_RESPONSE_HDR,      
00049   TS_EVENT_HTTP_REQUEST_TRANSFORM,      
00050   TS_EVENT_HTTP_RESPONSE_TRANSFORM,     
00051   TS_EVENT_HTTP_SELECT_ALT,             
00052   TS_EVENT_HTTP_TXN_START,              
00053   TS_EVENT_HTTP_TXN_CLOSE,              
00054   TS_EVENT_HTTP_SSN_START,              
00055   TS_EVENT_HTTP_SSN_CLOSE,              
00056   TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE,  
00057   TS_EVENT_HTTP_PRE_REMAP,              
00058   TS_EVENT_HTTP_POST_REMAP,             
00059   TS_EVENT_NONE,                        
00060   TS_EVENT_NONE,                        
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 * )
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   
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 }