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 }