00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "HttpSM.h"
00026 #include "ProxyConfig.h"
00027 #include "HttpClientSession.h"
00028 #include "HttpServerSession.h"
00029 #include "HttpDebugNames.h"
00030 #include "HttpSessionManager.h"
00031 #include "P_Cache.h"
00032 #include "P_Net.h"
00033 #include "StatPages.h"
00034 #include "Log.h"
00035 #include "LogAccessHttp.h"
00036 #include "ICP.h"
00037 #include "PluginVC.h"
00038 #include "ReverseProxy.h"
00039 #include "RemapProcessor.h"
00040 #include "Transform.h"
00041
00042 #include "HttpPages.h"
00043
00044
00045
00046 #include "congest/Congestion.h"
00047
00048 #define DEFAULT_RESPONSE_BUFFER_SIZE_INDEX 6 // 8K
00049 #define DEFAULT_REQUEST_BUFFER_SIZE_INDEX 6 // 8K
00050 #define MIN_CONFIG_BUFFER_SIZE_INDEX 5 // 4K
00051
00052 #define hsm_release_assert(EX) \
00053 { \
00054 if (!(EX)) \
00055 { \
00056 this->dump_state_on_assert(); \
00057 _ink_assert(#EX, __FILE__, __LINE__); \
00058 } \
00059 }
00060
00061
00062
00063
00064
00065
00066 #define USE_NEW_EMPTY_MIOBUFFER
00067
00068
00069
00070 DLL<HttpSM> debug_sm_list;
00071 ink_mutex debug_sm_list_mutex;
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 #define MAX_SCATTER_LEN (sizeof(HttpSM)/sizeof(uint32_t) + 1)
00087 static uint32_t val[MAX_SCATTER_LEN];
00088 static uint16_t to[MAX_SCATTER_LEN];
00089 static int scat_count = 0;
00090
00091 static const int sub_header_size = sizeof("Content-type: ") - 1 + 2 + sizeof("Content-range: bytes ") - 1 + 4;
00092 static const int boundary_size = 2 + sizeof("RANGE_SEPARATOR") - 1 + 2;
00093
00094 static const char *str_100_continue_response = "HTTP/1.1 100 Continue\r\n\r\n";
00095 static const int len_100_continue_response = strlen(str_100_continue_response);
00096
00097
00098
00099
00100
00101
00102
00103 static double
00104 milestone_difference(const ink_hrtime start, const ink_hrtime end)
00105 {
00106 if (end == 0) {
00107 return -1;
00108 }
00109 return (double) (end - start) / 1000000000;
00110 }
00111
00112 static double
00113 milestone_difference_msec(const ink_hrtime start, const ink_hrtime end)
00114 {
00115 if (end == 0) {
00116 return -1;
00117 }
00118 return (double) (end - start) / 1000000;
00119 }
00120
00121 void
00122 HttpSM::_make_scatter_list(HttpSM * prototype)
00123 {
00124 int j;
00125 int total_len = sizeof(HttpSM);
00126
00127 uint32_t *p = (uint32_t *) prototype;
00128 int n = total_len / sizeof(uint32_t);
00129 scat_count = 0;
00130 for (j = 0; j < n; j++) {
00131 if (p[j]) {
00132 to[scat_count] = j;
00133 val[scat_count] = p[j];
00134 scat_count++;
00135 }
00136 }
00137 }
00138
00139 void
00140 HttpSM::_instantiate_func(HttpSM * prototype, HttpSM * new_instance)
00141 {
00142 int history_len = sizeof(prototype->history);
00143 int total_len = sizeof(HttpSM);
00144 int pre_history_len = (char *) (&(prototype->history)) - (char *) prototype;
00145 int post_history_len = total_len - history_len - pre_history_len;
00146 int post_offset = pre_history_len + history_len;
00147 int j;
00148
00149 memset(((char *) new_instance), 0, pre_history_len);
00150 memset(((char *) new_instance) + post_offset, 0, post_history_len);
00151
00152 uint32_t *pd = (uint32_t *) new_instance;
00153
00154 for (j = 0; j < scat_count; j++) {
00155 pd[to[j]] = val[j];
00156 }
00157
00158 ink_assert((memcmp((char *) new_instance, (char *) prototype, pre_history_len) == 0) &&
00159 (memcmp(((char *) new_instance) + post_offset, ((char *) prototype) + post_offset, post_history_len) == 0));
00160 }
00161
00162 SparseClassAllocator<HttpSM> httpSMAllocator("httpSMAllocator", 128, 16, HttpSM::_instantiate_func);
00163
00164 #define HTTP_INCREMENT_TRANS_STAT(X) HttpTransact::update_stat(&t_state, X, 1);
00165
00166 HttpVCTable::HttpVCTable()
00167 {
00168 memset(&vc_table, 0, sizeof(vc_table));
00169 }
00170
00171 HttpVCTableEntry *
00172 HttpVCTable::new_entry()
00173 {
00174 for (int i = 0; i < vc_table_max_entries; i++) {
00175 if (vc_table[i].vc == NULL) {
00176 return vc_table + i;
00177 }
00178 }
00179
00180 ink_release_assert(0);
00181 return NULL;
00182 }
00183
00184 HttpVCTableEntry *
00185 HttpVCTable::find_entry(VConnection * vc)
00186 {
00187 for (int i = 0; i < vc_table_max_entries; i++) {
00188 if (vc_table[i].vc == vc) {
00189 return vc_table + i;
00190 }
00191 }
00192
00193 return NULL;
00194 }
00195
00196 HttpVCTableEntry *
00197 HttpVCTable::find_entry(VIO * vio)
00198 {
00199 for (int i = 0; i < vc_table_max_entries; i++) {
00200 if (vc_table[i].read_vio == vio || vc_table[i].write_vio == vio) {
00201 ink_assert(vc_table[i].vc != NULL);
00202 return vc_table + i;
00203 }
00204 }
00205
00206 return NULL;
00207 }
00208
00209
00210
00211
00212
00213
00214
00215 void
00216 HttpVCTable::remove_entry(HttpVCTableEntry * e)
00217 {
00218 ink_assert(e->vc == NULL || e->in_tunnel);
00219 e->vc = NULL;
00220 e->eos = false;
00221 if (e->read_buffer) {
00222 free_MIOBuffer(e->read_buffer);
00223 e->read_buffer = NULL;
00224 }
00225 if (e->write_buffer) {
00226 free_MIOBuffer(e->write_buffer);
00227 e->write_buffer = NULL;
00228 }
00229 e->read_vio = NULL;
00230 e->write_vio = NULL;
00231 e->vc_handler = NULL;
00232 e->vc_type = HTTP_UNKNOWN;
00233 e->in_tunnel = false;
00234 }
00235
00236
00237
00238
00239
00240
00241 void
00242 HttpVCTable::cleanup_entry(HttpVCTableEntry * e)
00243 {
00244 ink_assert(e->vc);
00245 if (e->in_tunnel == false) {
00246
00247 switch (e->vc_type) {
00248 case HTTP_UA_VC:
00249
00250 break;
00251 default:
00252
00253
00254
00255 break;
00256 }
00257
00258 e->vc->do_io_close();
00259 e->vc = NULL;
00260 }
00261 remove_entry(e);
00262 }
00263
00264 void
00265 HttpVCTable::cleanup_all()
00266 {
00267 for (int i = 0; i < vc_table_max_entries; i++) {
00268 if (vc_table[i].vc != NULL) {
00269 cleanup_entry(vc_table + i);
00270 }
00271 }
00272 }
00273
00274 #define REMEMBER_EVENT_FILTER(e) 1
00275
00276 #define __REMEMBER(x) #x
00277 #define _REMEMBER(x) __REMEMBER(x)
00278
00279 #define RECORD_FILE_LINE() \
00280 history[pos].fileline = __FILE__ ":" _REMEMBER (__LINE__);
00281
00282 #define REMEMBER(e,r) \
00283 { if (REMEMBER_EVENT_FILTER(e)) { \
00284 add_history_entry(__FILE__ ":" _REMEMBER (__LINE__), e, r); }}
00285
00286 #define DebugSM(tag, ...) DebugSpecific(debug_on, tag, __VA_ARGS__)
00287
00288 #ifdef STATE_ENTER
00289 #undef STATE_ENTER
00290 #endif
00291 #define STATE_ENTER(state_name, event) { \
00292 REMEMBER (event, reentrancy_count); \
00293 DebugSM("http", "[%" PRId64 "] [%s, %s]", sm_id, \
00294 #state_name, HttpDebugNames::get_event_name(event)); }
00295
00296 #define HTTP_SM_SET_DEFAULT_HANDLER(_h) \
00297 { \
00298 REMEMBER(-1,reentrancy_count); \
00299 default_handler = _h; }
00300
00301
00302 static int next_sm_id = 0;
00303
00304
00305 HttpSM::HttpSM()
00306 : Continuation(NULL), sm_id(-1), magic(HTTP_SM_MAGIC_DEAD),
00307
00308 enable_redirection(false), redirect_url(NULL), redirect_url_len(0), redirection_tries(0),
00309 transfered_bytes(0), post_failed(false), debug_on(false),
00310 plugin_tunnel_type(HTTP_NO_PLUGIN_TUNNEL),
00311 plugin_tunnel(NULL), reentrancy_count(0),
00312 history_pos(0), tunnel(), ua_entry(NULL),
00313 ua_session(NULL), background_fill(BACKGROUND_FILL_NONE),
00314 ua_raw_buffer_reader(NULL),
00315 server_entry(NULL), server_session(NULL), shared_session_retries(0),
00316 server_buffer_reader(NULL),
00317 transform_info(), post_transform_info(), has_active_plugin_agents(false),
00318 second_cache_sm(NULL),
00319 default_handler(NULL), pending_action(NULL), historical_action(NULL),
00320 last_action(HttpTransact::SM_ACTION_UNDEFINED),
00321
00322 client_request_hdr_bytes(0), client_request_body_bytes(0),
00323 server_request_hdr_bytes(0), server_request_body_bytes(0),
00324 server_response_hdr_bytes(0), server_response_body_bytes(0),
00325 client_response_hdr_bytes(0), client_response_body_bytes(0),
00326 cache_response_hdr_bytes(0), cache_response_body_bytes(0),
00327 pushed_response_hdr_bytes(0), pushed_response_body_bytes(0),
00328 plugin_tag(0), plugin_id(0),
00329 hooks_set(false), cur_hook_id(TS_HTTP_LAST_HOOK), cur_hook(NULL),
00330 cur_hooks(0), callout_state(HTTP_API_NO_CALLOUT), terminate_sm(false), kill_this_async_done(false)
00331 {
00332 static int scatter_init = 0;
00333
00334 memset(&history, 0, sizeof(history));
00335 memset(&vc_table, 0, sizeof(vc_table));
00336 memset(&http_parser, 0, sizeof(http_parser));
00337
00338 if (!scatter_init) {
00339 _make_scatter_list(this);
00340 scatter_init = 1;
00341 }
00342 }
00343
00344 void
00345 HttpSM::cleanup()
00346 {
00347 t_state.destroy();
00348 api_hooks.clear();
00349 http_parser_clear(&http_parser);
00350
00351
00352
00353 HttpConfig::release(t_state.http_config_param);
00354
00355 mutex.clear();
00356 tunnel.mutex.clear();
00357 cache_sm.mutex.clear();
00358 transform_cache_sm.mutex.clear();
00359 if (second_cache_sm) {
00360 second_cache_sm->mutex.clear();
00361 delete second_cache_sm;
00362 }
00363 magic = HTTP_SM_MAGIC_DEAD;
00364 debug_on = false;
00365 }
00366
00367 void
00368 HttpSM::destroy()
00369 {
00370 cleanup();
00371 httpSMAllocator.free(this);
00372 }
00373
00374 void
00375 HttpSM::init()
00376 {
00377 milestones.sm_start = ink_get_hrtime();
00378
00379 magic = HTTP_SM_MAGIC_ALIVE;
00380 sm_id = 0;
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 sm_id = (int64_t) ink_atomic_increment((&next_sm_id), 1);
00391 t_state.state_machine_id = sm_id;
00392 t_state.state_machine = this;
00393
00394 t_state.http_config_param = HttpConfig::acquire();
00395
00396
00397
00398 t_state.txn_conf = &t_state.http_config_param->oride;
00399
00400
00401
00402 t_state.cache_info.config.cache_global_user_agent_header = t_state.txn_conf->global_user_agent_header ? true : false;
00403 t_state.cache_info.config.ignore_accept_mismatch = t_state.http_config_param->ignore_accept_mismatch;
00404 t_state.cache_info.config.ignore_accept_language_mismatch = t_state.http_config_param->ignore_accept_language_mismatch ;
00405 t_state.cache_info.config.ignore_accept_encoding_mismatch = t_state.http_config_param->ignore_accept_encoding_mismatch;
00406 t_state.cache_info.config.ignore_accept_charset_mismatch = t_state.http_config_param->ignore_accept_charset_mismatch;
00407 t_state.cache_info.config.cache_enable_default_vary_headers = t_state.http_config_param->cache_enable_default_vary_headers ? true : false;
00408
00409 t_state.cache_info.config.cache_vary_default_text = t_state.http_config_param->cache_vary_default_text;
00410 t_state.cache_info.config.cache_vary_default_images = t_state.http_config_param->cache_vary_default_images;
00411 t_state.cache_info.config.cache_vary_default_other = t_state.http_config_param->cache_vary_default_other;
00412
00413 t_state.init();
00414 t_state.srv_lookup = hostdb_srv_enabled;
00415
00416
00417
00418
00419 t_state.force_dns = (ip_rule_in_CacheControlTable() || t_state.parent_params->ParentTable->ipMatch ||
00420 !(t_state.txn_conf->doc_in_cache_skip_dns) || !(t_state.txn_conf->cache_http));
00421
00422 http_parser_init(&http_parser);
00423
00424 SET_HANDLER(&HttpSM::main_handler);
00425
00426 #ifdef USE_HTTP_DEBUG_LISTS
00427 ink_mutex_acquire(&debug_sm_list_mutex);
00428 debug_sm_list.push(this, this->debug_link);
00429 ink_mutex_release(&debug_sm_list_mutex);
00430 #endif
00431
00432 }
00433
00434 void
00435 HttpSM::set_ua_half_close_flag()
00436 {
00437 ua_session->set_half_close_flag();
00438 }
00439
00440 inline void
00441 HttpSM::do_api_callout()
00442 {
00443 if (hooks_set) {
00444 do_api_callout_internal();
00445 } else {
00446 handle_api_return();
00447 }
00448 }
00449
00450 int
00451 HttpSM::state_add_to_list(int event, void * )
00452 {
00453
00454
00455
00456 if (t_state.http_config_param->enable_http_info) {
00457 STATE_ENTER(&HttpSM::state_add_to_list, event);
00458 ink_assert(event == EVENT_NONE || event == EVENT_INTERVAL);
00459
00460 int bucket = ((unsigned int) sm_id % HTTP_LIST_BUCKETS);
00461
00462 MUTEX_TRY_LOCK(lock, HttpSMList[bucket].mutex, mutex->thread_holding);
00463
00464
00465
00466 if (lock)
00467 HttpSMList[bucket].sm_list.push(this);
00468 }
00469
00470 t_state.api_next_action = HttpTransact::SM_ACTION_API_SM_START;
00471 do_api_callout();
00472 return EVENT_DONE;
00473 }
00474
00475 int
00476 HttpSM::state_remove_from_list(int event, void * )
00477 {
00478
00479
00480
00481
00482
00483 if (t_state.http_config_param->enable_http_info) {
00484 STATE_ENTER(&HttpSM::state_remove_from_list, event);
00485 ink_assert(event == EVENT_NONE || event == EVENT_INTERVAL);
00486
00487 int bucket = ((unsigned int) sm_id % HTTP_LIST_BUCKETS);
00488
00489 MUTEX_TRY_LOCK(lock, HttpSMList[bucket].mutex, mutex->thread_holding);
00490 if (!lock) {
00491 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_remove_from_list);
00492 mutex->thread_holding->schedule_in(this, HTTP_LIST_RETRY);
00493 return EVENT_DONE;
00494 }
00495
00496 HttpSMList[bucket].sm_list.remove(this);
00497 }
00498
00499 return this->kill_this_async_hook(EVENT_NONE, NULL);
00500 }
00501
00502 int
00503 HttpSM::kill_this_async_hook(int , void * )
00504 {
00505
00506
00507
00508
00509 terminate_sm = true;
00510 kill_this_async_done = true;
00511
00512 return EVENT_DONE;
00513 }
00514
00515
00516 void
00517 HttpSM::start_sub_sm()
00518 {
00519 tunnel.init(this, mutex);
00520 cache_sm.init(this, mutex);
00521 transform_cache_sm.init(this, mutex);
00522 }
00523
00524 void
00525 HttpSM::attach_client_session(HttpClientSession * client_vc, IOBufferReader * buffer_reader)
00526 {
00527 milestones.ua_begin = ink_get_hrtime();
00528 ink_assert(client_vc != NULL);
00529
00530 ua_session = client_vc;
00531 mutex = client_vc->mutex;
00532 if (ua_session->debug()) debug_on = true;
00533
00534 start_sub_sm();
00535
00536
00537
00538 ua_entry = vc_table.new_entry();
00539 ua_entry->vc = client_vc;
00540 ua_entry->vc_type = HTTP_UA_VC;
00541
00542 NetVConnection* netvc = client_vc->get_netvc();
00543
00544 ats_ip_copy(&t_state.client_info.addr, netvc->get_remote_addr());
00545 t_state.client_info.port = netvc->get_local_port();
00546 t_state.client_info.is_transparent = netvc->get_is_transparent();
00547 t_state.backdoor_request = !client_vc->hooks_enabled();
00548 t_state.client_info.port_attribute = static_cast<HttpProxyPort::TransportType>(netvc->attributes);
00549
00550 HTTP_INCREMENT_DYN_STAT(http_current_client_transactions_stat);
00551
00552
00553 hooks_set = client_vc->has_hooks();
00554
00555
00556 ua_buffer_reader = buffer_reader;
00557 ua_entry->vc_handler = &HttpSM::state_read_client_request_header;
00558 t_state.hdr_info.client_request.destroy();
00559 t_state.hdr_info.client_request.create(HTTP_TYPE_REQUEST);
00560 http_parser_init(&http_parser);
00561
00562
00563 if (is_transparent_passthrough_allowed()) {
00564 ua_raw_buffer_reader = buffer_reader->clone();
00565 }
00566
00567
00568
00569
00570
00571 ua_entry->read_vio = client_vc->do_io_read(this, 0, buffer_reader->mbuf);
00572
00573
00574
00575
00576 client_vc->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(HttpConfig::m_master.accept_no_activity_timeout));
00577 client_vc->get_netvc()->set_active_timeout(HRTIME_SECONDS(HttpConfig::m_master.transaction_active_timeout_in));
00578
00579 ++reentrancy_count;
00580
00581 state_add_to_list(EVENT_NONE, NULL);
00582
00583
00584
00585 if (terminate_sm == true && reentrancy_count == 1) {
00586 kill_this();
00587 } else {
00588 --reentrancy_count;
00589 ink_assert(reentrancy_count >= 0);
00590 }
00591 }
00592
00593
00594 void
00595 HttpSM::setup_client_read_request_header()
00596 {
00597 ink_assert(ua_entry->vc_handler == &HttpSM::state_read_client_request_header);
00598
00599 ua_entry->read_vio = ua_session->do_io_read(this, INT64_MAX, ua_buffer_reader->mbuf);
00600
00601
00602 if (ua_buffer_reader->read_avail() > 0)
00603 handleEvent(VC_EVENT_READ_READY, ua_entry->read_vio);
00604 }
00605
00606 void
00607 HttpSM::setup_blind_tunnel_port()
00608 {
00609
00610
00611 call_transact_and_set_next_state(HttpTransact::HandleBlindTunnel);
00612 }
00613
00614 int
00615 HttpSM::state_read_client_request_header(int event, void *data)
00616 {
00617 STATE_ENTER(&HttpSM::state_read_client_request_header, event);
00618
00619 ink_assert(ua_entry->read_vio == (VIO *) data);
00620 ink_assert(server_entry == NULL);
00621 ink_assert(server_session == NULL);
00622
00623 int bytes_used = 0;
00624 ink_assert(ua_entry->eos == false);
00625
00626 switch (event) {
00627 case VC_EVENT_READ_READY:
00628 case VC_EVENT_READ_COMPLETE:
00629
00630 break;
00631
00632 case VC_EVENT_EOS:
00633 ua_entry->eos = true;
00634 if (client_request_hdr_bytes !=0)
00635 break;
00636
00637 case VC_EVENT_ERROR:
00638 case VC_EVENT_INACTIVITY_TIMEOUT:
00639 case VC_EVENT_ACTIVE_TIMEOUT:
00640
00641
00642 vc_table.cleanup_entry(ua_entry);
00643 ua_entry = NULL;
00644 t_state.client_info.abort = HttpTransact::ABORTED;
00645 terminate_sm = true;
00646 return 0;
00647 }
00648
00649
00650
00651
00652
00653 if (client_request_hdr_bytes == 0) {
00654 ua_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_in));
00655 }
00656
00657
00658
00659
00660 MIMEParseResult state = t_state.hdr_info.client_request.parse_req(&http_parser,
00661 ua_buffer_reader,
00662 &bytes_used,
00663 ua_entry->eos);
00664
00665 client_request_hdr_bytes += bytes_used;
00666
00667
00668 if (client_request_hdr_bytes > t_state.txn_conf->request_hdr_max_size) {
00669 DebugSM("http", "client header bytes were over max header size; treating as a bad request");
00670 state = PARSE_ERROR;
00671 }
00672
00673 if (event == VC_EVENT_READ_READY &&
00674 state == PARSE_ERROR &&
00675 is_transparent_passthrough_allowed() &&
00676 ua_raw_buffer_reader != NULL) {
00677
00678 DebugSM("http", "[%" PRId64 "] first request on connection failed parsing, switching to passthrough.", sm_id);
00679
00680 t_state.transparent_passthrough = true;
00681 http_parser_clear(&http_parser);
00682
00683
00684
00685 ua_session->get_netvc()->do_io_read(this, 0, NULL);
00686
00687
00688 setup_blind_tunnel_port();
00689 return 0;
00690 }
00691
00692
00693 if (state != PARSE_CONT || ua_entry->eos ||
00694 (state == PARSE_CONT && event == VC_EVENT_READ_COMPLETE)) {
00695 if (ua_raw_buffer_reader != NULL) {
00696 ua_raw_buffer_reader->dealloc();
00697 ua_raw_buffer_reader = NULL;
00698 }
00699 http_parser_clear(&http_parser);
00700 ua_entry->vc_handler = &HttpSM::state_watch_for_client_abort;
00701 milestones.ua_read_header_done = ink_get_hrtime();
00702 }
00703
00704 switch (state) {
00705 case PARSE_ERROR:
00706 DebugSM("http", "[%" PRId64 "] error parsing client request header", sm_id);
00707
00708
00709 ua_entry->read_vio->nbytes = ua_entry->read_vio->ndone;
00710
00711 call_transact_and_set_next_state(HttpTransact::BadRequest);
00712 break;
00713
00714 case PARSE_CONT:
00715 if (ua_entry->eos) {
00716 DebugSM("http_seq", "[%" PRId64 "] EOS before client request parsing finished", sm_id);
00717 set_ua_abort(HttpTransact::ABORTED, event);
00718
00719
00720 ua_entry->read_vio->nbytes = ua_entry->read_vio->ndone;
00721
00722 call_transact_and_set_next_state(HttpTransact::BadRequest);
00723 break;
00724 } else if (event == VC_EVENT_READ_COMPLETE) {
00725 DebugSM("http_parse", "[%" PRId64 "] VC_EVENT_READ_COMPLETE and PARSE CONT state", sm_id);
00726 break;
00727 } else {
00728 if (is_transparent_passthrough_allowed() &&
00729 ua_raw_buffer_reader != NULL &&
00730 ua_raw_buffer_reader->get_current_block()->write_avail() <= 0) {
00731
00732
00733 ua_raw_buffer_reader->dealloc();
00734 ua_raw_buffer_reader = NULL;
00735 }
00736 ua_entry->read_vio->reenable();
00737 return VC_EVENT_CONT;
00738 }
00739 case PARSE_DONE:
00740 DebugSM("http", "[%" PRId64 "] done parsing client request header", sm_id);
00741
00742 if (ua_session->m_active == false) {
00743 ua_session->m_active = true;
00744 HTTP_INCREMENT_DYN_STAT(http_current_active_client_connections_stat);
00745 }
00746 if (t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_TRACE ||
00747 (t_state.hdr_info.request_content_length == 0 &&
00748 t_state.client_info.transfer_encoding != HttpTransact::CHUNKED_ENCODING)) {
00749
00750
00751 ua_entry->read_vio->reenable();
00752 } else {
00753
00754
00755
00756
00757 ua_entry->read_vio->nbytes = ua_entry->read_vio->ndone;
00758 }
00759
00760
00761 if ((HttpConfig::m_master.number_of_redirections > 0) ||
00762 (t_state.method == HTTP_WKSIDX_POST && HttpConfig::m_master.post_copy_size))
00763 enable_redirection = HttpConfig::m_master.redirection_enabled;
00764
00765 call_transact_and_set_next_state(HttpTransact::ModifyRequest);
00766
00767 break;
00768 default:
00769 ink_assert(!"not reached");
00770 }
00771
00772 return 0;
00773 }
00774
00775 #ifdef PROXY_DRAIN
00776 int
00777 HttpSM::state_drain_client_request_body(int event, void *data)
00778 {
00779 STATE_ENTER(&HttpSM::state_drain_client_request_body, event);
00780
00781 ink_assert(ua_entry->read_vio == (VIO *) data);
00782 ink_assert(ua_entry->vc == ua_session);
00783
00784 switch (event) {
00785 case VC_EVENT_EOS:
00786 case VC_EVENT_ERROR:
00787 case VC_EVENT_ACTIVE_TIMEOUT:
00788 case VC_EVENT_INACTIVITY_TIMEOUT:
00789 {
00790
00791 terminate_sm = true;
00792 break;
00793 }
00794 case VC_EVENT_READ_READY:
00795 {
00796 int64_t avail = ua_buffer_reader->read_avail();
00797 int64_t left = t_state.hdr_info.request_content_length - client_request_body_bytes;
00798
00799
00800
00801 ink_assert(avail < left);
00802
00803 client_request_body_bytes += avail;
00804 ua_buffer_reader->consume(avail);
00805 ua_entry->read_vio->reenable_re();
00806 break;
00807 }
00808 case VC_EVENT_READ_COMPLETE:
00809 {
00810
00811 int64_t avail = ua_buffer_reader->read_avail();
00812
00813 ua_buffer_reader->consume(avail);
00814 client_request_body_bytes += avail;
00815 ink_assert(client_request_body_bytes == t_state.hdr_info.request_content_length);
00816
00817 ua_buffer_reader->mbuf->size_index = HTTP_HEADER_BUFFER_SIZE_INDEX;
00818 ua_entry->vc_handler = &HttpSM::state_watch_for_client_abort;
00819 ua_entry->read_vio = ua_entry->vc->do_io_read(this, INT64_MAX, ua_buffer_reader->mbuf);
00820 call_transact_and_set_next_state(NULL);
00821 break;
00822 }
00823 default:
00824 ink_release_assert(0);
00825 }
00826
00827 return EVENT_DONE;
00828 }
00829 #endif
00830
00831
00832 int
00833 HttpSM::state_watch_for_client_abort(int event, void *data)
00834 {
00835 STATE_ENTER(&HttpSM::state_watch_for_client_abort, event);
00836
00837 ink_assert(ua_entry->read_vio == (VIO *) data);
00838 ink_assert(ua_entry->vc == ua_session);
00839
00840 switch (event) {
00841 case VC_EVENT_EOS:
00842 case VC_EVENT_ERROR:
00843 case VC_EVENT_ACTIVE_TIMEOUT:
00844 case VC_EVENT_INACTIVITY_TIMEOUT:
00845 {
00846 if (tunnel.is_tunnel_active()) {
00847
00848
00849
00850
00851 HttpTunnelConsumer *c = tunnel.get_consumer(ua_session);
00852 if (c && c->alive) {
00853 DebugSM("http", "[%" PRId64 "] [watch_for_client_abort] "
00854 "forwarding event %s to tunnel", sm_id, HttpDebugNames::get_event_name(event));
00855 tunnel.handleEvent(event, c->write_vio);
00856 return 0;
00857 } else {
00858 tunnel.kill_tunnel();
00859 }
00860 }
00861
00862 if (ua_entry->read_vio) {
00863 ua_entry->read_vio->nbytes = ua_entry->read_vio->ndone;
00864 }
00865 mark_server_down_on_client_abort();
00866 milestones.ua_close = ink_get_hrtime();
00867 set_ua_abort(HttpTransact::ABORTED, event);
00868 terminate_sm = true;
00869 break;
00870 }
00871 case VC_EVENT_READ_COMPLETE:
00872
00873 case VC_EVENT_READ_READY:
00874
00875
00876 break;
00877 default:
00878 ink_release_assert(0);
00879 break;
00880 }
00881
00882 return 0;
00883 }
00884
00885 void
00886 HttpSM::setup_push_read_response_header()
00887 {
00888 ink_assert(server_session == NULL);
00889 ink_assert(server_entry == NULL);
00890 ink_assert(ua_session != NULL);
00891 ink_assert(t_state.method == HTTP_WKSIDX_PUSH);
00892
00893
00894 ua_entry->vc_handler = &HttpSM::state_read_push_response_header;
00895
00896
00897
00898
00899 pushed_response_hdr_bytes = 0;
00900 client_request_body_bytes = 0;
00901
00902
00903
00904 t_state.hdr_info.server_response.destroy();
00905 t_state.hdr_info.server_response.create(HTTP_TYPE_RESPONSE);
00906 http_parser_clear(&http_parser);
00907
00908
00909
00910 ink_assert(ua_entry->read_vio);
00911
00912
00913
00914
00915 int resp_hdr_state = VC_EVENT_CONT;
00916 if (ua_buffer_reader->read_avail() > 0) {
00917 if (ua_entry->eos) {
00918 resp_hdr_state = state_read_push_response_header(VC_EVENT_EOS, ua_entry->read_vio);
00919 } else {
00920 resp_hdr_state = state_read_push_response_header(VC_EVENT_READ_READY, ua_entry->read_vio);
00921 }
00922 }
00923
00924
00925
00926
00927 if (resp_hdr_state == VC_EVENT_CONT) {
00928 ink_assert(ua_entry->eos == false);
00929 ua_entry->read_vio = ua_session->do_io_read(this, INT64_MAX, ua_buffer_reader->mbuf);
00930 }
00931 }
00932
00933 int
00934 HttpSM::state_read_push_response_header(int event, void *data)
00935 {
00936 STATE_ENTER(&HttpSM::state_read_push_response_header, event);
00937 ink_assert(ua_entry->read_vio == (VIO *) data);
00938 ink_assert(t_state.current.server == NULL);
00939
00940 int64_t data_size = 0;
00941 int64_t bytes_used = 0;
00942
00943
00944
00945
00946
00947 switch (event) {
00948 case VC_EVENT_EOS:
00949 ua_entry->eos = true;
00950
00951
00952 case VC_EVENT_READ_READY:
00953 case VC_EVENT_READ_COMPLETE:
00954
00955 break;
00956
00957 case VC_EVENT_ERROR:
00958 case VC_EVENT_INACTIVITY_TIMEOUT:
00959 case VC_EVENT_ACTIVE_TIMEOUT:
00960
00961 t_state.client_info.abort = HttpTransact::ABORTED;
00962 call_transact_and_set_next_state(HttpTransact::HandleBadPushRespHdr);
00963 return 0;
00964 }
00965
00966 int state = PARSE_CONT;
00967 while (ua_buffer_reader->read_avail() && state == PARSE_CONT) {
00968 const char *start = ua_buffer_reader->start();
00969 const char *tmp = start;
00970 data_size = ua_buffer_reader->block_read_avail();
00971 ink_assert(data_size >= 0);
00972
00973
00974
00975
00976 state = t_state.hdr_info.server_response.parse_resp(&http_parser, &tmp, tmp + data_size, false
00977 );
00978
00979 bytes_used = tmp - start;
00980
00981 ink_release_assert(bytes_used <= data_size);
00982 ua_buffer_reader->consume(bytes_used);
00983 pushed_response_hdr_bytes += bytes_used;
00984 client_request_body_bytes += bytes_used;
00985 }
00986
00987
00988
00989
00990 if (ua_entry->eos) {
00991 const char *end = ua_buffer_reader->start();
00992 state = t_state.hdr_info.server_response.parse_resp(&http_parser, &end, end, true
00993 );
00994 ink_release_assert(state == PARSE_DONE || state == PARSE_ERROR);
00995 }
00996
00997
00998 if (state == PARSE_DONE && t_state.hdr_info.server_response.version_get() == HTTPVersion(0, 9)) {
00999 state = PARSE_ERROR;
01000 }
01001
01002 if (state != PARSE_CONT) {
01003
01004 ua_entry->read_vio->nbytes = ua_entry->read_vio->ndone;
01005 http_parser_clear(&http_parser);
01006 milestones.server_read_header_done = ink_get_hrtime();
01007 }
01008
01009 switch (state) {
01010 case PARSE_ERROR:
01011 DebugSM("http", "[%" PRId64 "] error parsing push response header", sm_id);
01012 call_transact_and_set_next_state(HttpTransact::HandleBadPushRespHdr);
01013 break;
01014
01015 case PARSE_CONT:
01016 ua_entry->read_vio->reenable();
01017 return VC_EVENT_CONT;
01018
01019 case PARSE_DONE:
01020 DebugSM("http", "[%" PRId64 "] done parsing push response header", sm_id);
01021 call_transact_and_set_next_state(HttpTransact::HandlePushResponseHdr);
01022 break;
01023 default:
01024 ink_assert(!"not reached");
01025 }
01026
01027 return VC_EVENT_DONE;
01028 }
01029
01030
01031
01032
01033
01034
01035 int
01036 HttpSM::state_raw_http_server_open(int event, void *data)
01037 {
01038 STATE_ENTER(&HttpSM::state_raw_http_server_open, event);
01039 ink_assert(server_entry == NULL);
01040 milestones.server_connect_end = ink_get_hrtime();
01041 NetVConnection *netvc = NULL;
01042
01043 pending_action = NULL;
01044 switch (event) {
01045 case NET_EVENT_OPEN:
01046
01047 if (t_state.pCongestionEntry != NULL) {
01048 t_state.pCongestionEntry->connection_opened();
01049 t_state.congestion_connection_opened = 1;
01050 }
01051
01052 server_entry = vc_table.new_entry();
01053 server_entry->vc = netvc = (NetVConnection *) data;
01054 server_entry->vc_type = HTTP_RAW_SERVER_VC;
01055 t_state.current.state = HttpTransact::CONNECTION_ALIVE;
01056
01057 netvc->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_out));
01058 netvc->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_active_timeout_out));
01059 break;
01060
01061 case VC_EVENT_ERROR:
01062 case NET_EVENT_OPEN_FAILED:
01063 if (t_state.pCongestionEntry != NULL) {
01064 t_state.current.state = HttpTransact::CONNECTION_ERROR;
01065 call_transact_and_set_next_state(HttpTransact::HandleResponse);
01066 return 0;
01067 } else {
01068 t_state.current.state = HttpTransact::OPEN_RAW_ERROR;
01069
01070 t_state.hdr_info.response_error = HttpTransact::STATUS_CODE_SERVER_ERROR;
01071 }
01072 break;
01073 case CONGESTION_EVENT_CONGESTED_ON_F:
01074 t_state.current.state = HttpTransact::CONGEST_CONTROL_CONGESTED_ON_F;
01075 break;
01076 case CONGESTION_EVENT_CONGESTED_ON_M:
01077 t_state.current.state = HttpTransact::CONGEST_CONTROL_CONGESTED_ON_M;
01078 break;
01079
01080 case EVENT_INTERVAL:
01081 Error("[HttpSM::state_raw_http_server_open] event: EVENT_INTERVAL state: %d server_entry: %p",
01082 t_state.current.state, server_entry);
01083 return 0;
01084
01085 default:
01086 ink_release_assert(0);
01087 break;
01088 }
01089
01090 call_transact_and_set_next_state(HttpTransact::OriginServerRawOpen);
01091 return 0;
01092
01093 }
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 int
01104 HttpSM::state_request_wait_for_transform_read(int event, void *data)
01105 {
01106 STATE_ENTER(&HttpSM::state_request_wait_for_transform_read, event);
01107 int64_t size = *((int64_t*)data);
01108
01109 switch (event) {
01110 case TRANSFORM_READ_READY:
01111 if (size != INT64_MAX && size >= 0) {
01112
01113
01114 t_state.hdr_info.transform_request_cl = size;
01115 t_state.hdr_info.server_request.value_set_int64(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH, size);
01116 setup_server_send_request_api();
01117 break;
01118 } else {
01119
01120
01121
01122
01123 event = VC_EVENT_ERROR;
01124 Log::error("Request transformation failed to set content length");
01125 }
01126
01127 default:
01128 state_common_wait_for_transform_read(&post_transform_info, &HttpSM::tunnel_handler_post, event, data);
01129 break;
01130 }
01131
01132 return 0;
01133 }
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143 int
01144 HttpSM::state_response_wait_for_transform_read(int event, void *data)
01145 {
01146 STATE_ENTER(&HttpSM::state_response_wait_for_transform_read, event);
01147 int64_t size = *((int64_t*)data);
01148
01149 switch (event) {
01150 case TRANSFORM_READ_READY:
01151 if (size != INT64_MAX && size >= 0) {
01152
01153 t_state.hdr_info.transform_response_cl = size;
01154 t_state.hdr_info.transform_response.value_set_int64(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH, size);
01155 } else {
01156 t_state.hdr_info.transform_response_cl = HTTP_UNDEFINED_CL;
01157 }
01158 call_transact_and_set_next_state(HttpTransact::handle_transform_ready);
01159 break;
01160 default:
01161 state_common_wait_for_transform_read(&transform_info, &HttpSM::tunnel_handler, event, data);
01162 break;
01163 }
01164
01165 return 0;
01166 }
01167
01168
01169
01170
01171
01172
01173
01174 int
01175 HttpSM::state_common_wait_for_transform_read(HttpTransformInfo * t_info, HttpSMHandler tunnel_handler, int event, void *data)
01176 {
01177 STATE_ENTER(&HttpSM::state_common_wait_for_transform_read, event);
01178 HttpTunnelConsumer *c = 0;
01179
01180 switch (event) {
01181 case HTTP_TUNNEL_EVENT_DONE:
01182
01183
01184
01185
01186
01187
01188 c = tunnel.get_consumer(t_info->vc);
01189 ink_assert(c != NULL);
01190 ink_assert(c->vc == t_info->entry->vc);
01191
01192 if (c->handler_state == HTTP_SM_TRANSFORM_FAIL) {
01193
01194
01195 ink_assert(c->write_success == false);
01196 } else if (c->producer->read_success == false) {
01197
01198 if (c->producer->vc_type == HT_HTTP_CLIENT) {
01199
01200
01201
01202 ink_assert(t_info == &post_transform_info);
01203 return (this->*tunnel_handler) (event, data);
01204 } else {
01205
01206
01207
01208 ink_assert(t_info == &transform_info);
01209 t_state.api_info.cache_transformed = false;
01210 return 0;
01211 }
01212 } else {
01213
01214 return 0;
01215 }
01216
01217 case VC_EVENT_ERROR:
01218
01219 if (!c) {
01220 c = tunnel.get_consumer(t_info->vc);
01221 ink_assert(c != NULL);
01222 }
01223 vc_table.cleanup_entry(t_info->entry);
01224 t_info->entry = NULL;
01225
01226
01227
01228 if (c->handler_state != HTTP_SM_TRANSFORM_FAIL) {
01229 t_info->vc = NULL;
01230 }
01231 tunnel.kill_tunnel();
01232 call_transact_and_set_next_state(HttpTransact::HandleApiErrorJump);
01233 break;
01234 default:
01235 ink_release_assert(0);
01236 }
01237
01238 return 0;
01239 }
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249 int
01250 HttpSM::state_api_callback(int event, void *data)
01251 {
01252 ink_release_assert(magic == HTTP_SM_MAGIC_ALIVE);
01253
01254 ink_assert(reentrancy_count >= 0);
01255 reentrancy_count++;
01256
01257 STATE_ENTER(&HttpSM::state_api_callback, event);
01258
01259 state_api_callout(event, data);
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 if (terminate_sm == true && reentrancy_count == 1) {
01271 kill_this();
01272 } else {
01273 reentrancy_count--;
01274 ink_assert(reentrancy_count >= 0);
01275 }
01276
01277 return VC_EVENT_CONT;
01278 }
01279
01280 int
01281 HttpSM::state_api_callout(int event, void *data)
01282 {
01283
01284
01285 enum AfterApiReturn_t
01286 {
01287 API_RETURN_UNKNOWN = 0,
01288 API_RETURN_CONTINUE,
01289 API_RETURN_DEFERED_CLOSE,
01290 API_RETURN_DEFERED_SERVER_ERROR,
01291 API_RETURN_ERROR_JUMP,
01292 API_RETURN_SHUTDOWN,
01293 API_RETURN_INVALIDATE_ERROR
01294 };
01295 AfterApiReturn_t api_next = API_RETURN_UNKNOWN;
01296
01297 if (event != EVENT_NONE) {
01298 STATE_ENTER(&HttpSM::state_api_callout, event);
01299 }
01300
01301 switch (event) {
01302 case EVENT_INTERVAL:
01303 ink_assert(pending_action == data);
01304 pending_action = NULL;
01305
01306 case EVENT_NONE:
01307 case HTTP_API_CONTINUE:
01308 if ((cur_hook_id >= 0) && (cur_hook_id < TS_HTTP_LAST_HOOK)) {
01309 if (!cur_hook) {
01310 if (cur_hooks == 0) {
01311 cur_hook = http_global_hooks->get(cur_hook_id);
01312 cur_hooks++;
01313 }
01314 }
01315
01316
01317
01318 if (!cur_hook) {
01319 if (cur_hooks == 1) {
01320 if (ua_session) {
01321 cur_hook = ua_session->ssn_hook_get(cur_hook_id);
01322 }
01323 cur_hooks++;
01324 }
01325 }
01326 if (!cur_hook) {
01327 if (cur_hooks == 2) {
01328 cur_hook = api_hooks.get(cur_hook_id);
01329 cur_hooks++;
01330 }
01331 }
01332 if (cur_hook) {
01333 if (callout_state == HTTP_API_NO_CALLOUT) {
01334 callout_state = HTTP_API_IN_CALLOUT;
01335 }
01336
01337
01338
01339
01340
01341
01342
01343
01344 bool plugin_lock;
01345 Ptr<ProxyMutex> plugin_mutex;
01346 if (cur_hook->m_cont->mutex) {
01347 plugin_mutex = cur_hook->m_cont->mutex;
01348 plugin_lock = MUTEX_TAKE_TRY_LOCK(cur_hook->m_cont->mutex, mutex->thread_holding);
01349
01350 if (!plugin_lock) {
01351 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_api_callout);
01352 ink_assert(pending_action == NULL);
01353 pending_action = mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
01354 return 0;
01355 }
01356 } else {
01357 plugin_lock = false;
01358 }
01359
01360 DebugSM("http", "[%" PRId64 "] calling plugin on hook %s at hook %p",
01361 sm_id, HttpDebugNames::get_api_hook_name(cur_hook_id), cur_hook);
01362
01363 APIHook *hook = cur_hook;
01364 cur_hook = cur_hook->next();
01365
01366 hook->invoke(TS_EVENT_HTTP_READ_REQUEST_HDR + cur_hook_id, this);
01367
01368 if (plugin_lock) {
01369 Mutex_unlock(plugin_mutex, mutex->thread_holding);
01370 }
01371
01372 return 0;
01373 }
01374 }
01375
01376 switch (callout_state) {
01377 case HTTP_API_NO_CALLOUT:
01378 case HTTP_API_IN_CALLOUT:
01379 if (t_state.api_modifiable_cached_resp &&
01380 t_state.api_update_cached_object == HttpTransact::UPDATE_CACHED_OBJECT_PREPARE) {
01381 t_state.api_update_cached_object = HttpTransact::UPDATE_CACHED_OBJECT_CONTINUE;
01382 }
01383 api_next = API_RETURN_CONTINUE;
01384 break;
01385 case HTTP_API_DEFERED_CLOSE:
01386 api_next = API_RETURN_DEFERED_CLOSE;
01387 break;
01388 case HTTP_API_DEFERED_SERVER_ERROR:
01389 api_next = API_RETURN_DEFERED_SERVER_ERROR;
01390 break;
01391 default:
01392 ink_release_assert(0);
01393 }
01394 break;
01395
01396 case HTTP_API_ERROR:
01397 if (callout_state == HTTP_API_DEFERED_CLOSE) {
01398 api_next = API_RETURN_DEFERED_CLOSE;
01399 } else if (cur_hook_id == TS_HTTP_TXN_CLOSE_HOOK) {
01400
01401
01402 api_next = API_RETURN_CONTINUE;
01403 } else if (t_state.api_http_sm_shutdown) {
01404 t_state.api_http_sm_shutdown = false;
01405 t_state.cache_info.object_read = NULL;
01406 cache_sm.close_read();
01407 transform_cache_sm.close_read();
01408 release_server_session();
01409 terminate_sm = true;
01410 api_next = API_RETURN_SHUTDOWN;
01411 t_state.squid_codes.log_code = SQUID_LOG_TCP_DENIED;
01412 } else if (t_state.api_modifiable_cached_resp &&
01413 t_state.api_update_cached_object == HttpTransact::UPDATE_CACHED_OBJECT_PREPARE) {
01414 t_state.api_update_cached_object = HttpTransact::UPDATE_CACHED_OBJECT_ERROR;
01415 api_next = API_RETURN_INVALIDATE_ERROR;
01416 } else {
01417 api_next = API_RETURN_ERROR_JUMP;
01418 }
01419 break;
01420
01421
01422
01423 case HTTP_TUNNEL_EVENT_DONE:
01424 state_common_wait_for_transform_read(&transform_info, &HttpSM::tunnel_handler, event, data);
01425 return 0;
01426
01427 default:
01428 ink_assert(false);
01429 terminate_sm = true;
01430 return 0;
01431 }
01432
01433
01434
01435 callout_state = HTTP_API_NO_CALLOUT;
01436 switch (api_next) {
01437 case API_RETURN_CONTINUE:
01438 if (t_state.api_next_action == HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR) {
01439 do_redirect();
01440 }
01441 handle_api_return();
01442 break;
01443 case API_RETURN_DEFERED_CLOSE:
01444 ink_assert(t_state.api_next_action == HttpTransact::SM_ACTION_API_SM_SHUTDOWN);
01445 do_api_callout();
01446 break;
01447 case API_RETURN_DEFERED_SERVER_ERROR:
01448 ink_assert(t_state.api_next_action == HttpTransact::SM_ACTION_API_SEND_REQUEST_HDR);
01449 ink_assert(t_state.current.state != HttpTransact::CONNECTION_ALIVE);
01450 call_transact_and_set_next_state(HttpTransact::HandleResponse);
01451 break;
01452 case API_RETURN_ERROR_JUMP:
01453 call_transact_and_set_next_state(HttpTransact::HandleApiErrorJump);
01454 break;
01455 case API_RETURN_SHUTDOWN:
01456 break;
01457 case API_RETURN_INVALIDATE_ERROR:
01458 do_cache_prepare_update();
01459 break;
01460 default:
01461 case API_RETURN_UNKNOWN:
01462 ink_release_assert(0);
01463
01464 }
01465
01466 return 0;
01467 }
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 void
01478 HttpSM::handle_api_return()
01479 {
01480 switch (t_state.api_next_action) {
01481 case HttpTransact::SM_ACTION_API_SM_START:
01482 if (t_state.client_info.port_attribute == HttpProxyPort::TRANSPORT_BLIND_TUNNEL) {
01483 setup_blind_tunnel_port();
01484 } else {
01485 setup_client_read_request_header();
01486 }
01487 return;
01488 case HttpTransact::SM_ACTION_API_PRE_REMAP:
01489 case HttpTransact::SM_ACTION_API_POST_REMAP:
01490 case HttpTransact::SM_ACTION_API_READ_REQUEST_HDR:
01491 case HttpTransact::SM_ACTION_API_OS_DNS:
01492 case HttpTransact::SM_ACTION_API_READ_CACHE_HDR:
01493 case HttpTransact::SM_ACTION_API_READ_RESPONSE_HDR:
01494 case HttpTransact::SM_ACTION_API_CACHE_LOOKUP_COMPLETE:
01495
01496 if (t_state.api_next_action == HttpTransact::SM_ACTION_API_READ_RESPONSE_HDR && t_state.api_release_server_session) {
01497 t_state.api_release_server_session = false;
01498 release_server_session();
01499 } else if (t_state.api_next_action == HttpTransact::SM_ACTION_API_CACHE_LOOKUP_COMPLETE &&
01500 t_state.api_cleanup_cache_read &&
01501 t_state.api_update_cached_object != HttpTransact::UPDATE_CACHED_OBJECT_PREPARE) {
01502 t_state.api_cleanup_cache_read = false;
01503 t_state.cache_info.object_read = NULL;
01504 t_state.request_sent_time = UNDEFINED_TIME;
01505 t_state.response_received_time = UNDEFINED_TIME;
01506 cache_sm.close_read();
01507 transform_cache_sm.close_read();
01508 }
01509 call_transact_and_set_next_state(NULL);
01510 return;
01511 case HttpTransact::SM_ACTION_API_SEND_REQUEST_HDR:
01512 setup_server_send_request();
01513 return;
01514 case HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR:
01515
01516 if (ua_session) {
01517 ua_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_in));
01518 }
01519
01520
01521 break;
01522 case HttpTransact::SM_ACTION_API_SM_SHUTDOWN:
01523 state_remove_from_list(EVENT_NONE, NULL);
01524 return;
01525 default:
01526 ink_release_assert("! Not reached");
01527 break;
01528 }
01529
01530 switch (t_state.next_action) {
01531 case HttpTransact::SM_ACTION_TRANSFORM_READ:
01532 {
01533 HttpTunnelProducer *p = setup_transfer_from_transform();
01534 perform_transform_cache_write_action();
01535 tunnel.tunnel_run(p);
01536 break;
01537 }
01538 case HttpTransact::SM_ACTION_SERVER_READ:
01539 {
01540 if (unlikely(t_state.did_upgrade_succeed)) {
01541
01542
01543 if(t_state.is_websocket) {
01544 HTTP_INCREMENT_DYN_STAT(http_websocket_current_active_client_connections_stat);
01545 }
01546
01547 setup_blind_tunnel(true);
01548 } else {
01549 setup_server_transfer();
01550 perform_cache_write_action();
01551 tunnel.tunnel_run();
01552 }
01553 break;
01554 }
01555 case HttpTransact::SM_ACTION_SERVE_FROM_CACHE:
01556 {
01557 setup_cache_read_transfer();
01558 tunnel.tunnel_run();
01559 break;
01560 }
01561
01562 case HttpTransact::SM_ACTION_INTERNAL_CACHE_WRITE:
01563 {
01564 if (cache_sm.cache_write_vc) {
01565 setup_internal_transfer(&HttpSM::tunnel_handler_cache_fill);
01566 } else {
01567 setup_internal_transfer(&HttpSM::tunnel_handler);
01568 }
01569 break;
01570 }
01571
01572 case HttpTransact::SM_ACTION_INTERNAL_CACHE_NOOP:
01573 case HttpTransact::SM_ACTION_INTERNAL_CACHE_DELETE:
01574 case HttpTransact::SM_ACTION_INTERNAL_CACHE_UPDATE_HEADERS:
01575 case HttpTransact::SM_ACTION_SEND_ERROR_CACHE_NOOP:
01576 {
01577 setup_internal_transfer(&HttpSM::tunnel_handler);
01578 break;
01579 }
01580
01581 case HttpTransact::SM_ACTION_REDIRECT_READ:
01582 {
01583 call_transact_and_set_next_state(HttpTransact::HandleRequest);
01584 break;
01585 }
01586
01587 default:
01588 {
01589 ink_release_assert(!"Should not get here");
01590 }
01591 }
01592 }
01593
01594
01595
01596
01597
01598
01599 int
01600 HttpSM::state_http_server_open(int event, void *data)
01601 {
01602 DebugSM("http_track", "entered inside state_http_server_open");
01603 STATE_ENTER(&HttpSM::state_http_server_open, event);
01604
01605
01606 pending_action = NULL;
01607 milestones.server_connect_end = ink_get_hrtime();
01608 HttpServerSession *session;
01609
01610 switch (event) {
01611 case NET_EVENT_OPEN:
01612 session = (TS_SERVER_SESSION_SHARING_POOL_THREAD == t_state.txn_conf->server_session_sharing_pool) ?
01613 THREAD_ALLOC_INIT(httpServerSessionAllocator, mutex->thread_holding) :
01614 httpServerSessionAllocator.alloc();
01615 session->sharing_pool = static_cast<TSServerSessionSharingPoolType>(t_state.txn_conf->server_session_sharing_pool);
01616 session->sharing_match = static_cast<TSServerSessionSharingMatchType>(t_state.txn_conf->server_session_sharing_match);
01617
01618
01619
01620
01621
01622
01623
01624 if (t_state.txn_conf->origin_max_connections > 0 ||
01625 t_state.http_config_param->origin_min_keep_alive_connections > 0) {
01626 DebugSM("http_ss", "[%" PRId64 "] max number of connections: %" PRIu64, sm_id, t_state.txn_conf->origin_max_connections);
01627 session->enable_origin_connection_limiting = true;
01628 }
01629
01630
01631
01632
01633 ats_ip_copy(&session->server_ip, &t_state.current.server->addr);
01634 session->new_connection((NetVConnection *) data);
01635 ats_ip_port_cast(&session->server_ip) = htons(t_state.current.server->port);
01636 session->state = HSS_ACTIVE;
01637
01638 attach_server_session(session);
01639 if (t_state.current.request_to == HttpTransact::PARENT_PROXY) {
01640 session->to_parent_proxy = true;
01641 HTTP_INCREMENT_DYN_STAT(http_current_parent_proxy_connections_stat);
01642 HTTP_INCREMENT_DYN_STAT(http_total_parent_proxy_connections_stat);
01643
01644 } else {
01645 session->to_parent_proxy = false;
01646 }
01647 handle_http_server_open();
01648 return 0;
01649 case EVENT_INTERVAL:
01650 do_http_server_open();
01651 break;
01652 case VC_EVENT_ERROR:
01653 case NET_EVENT_OPEN_FAILED:
01654 t_state.current.state = HttpTransact::CONNECTION_ERROR;
01655
01656 t_state.current.server->set_connect_fail(event == NET_EVENT_OPEN_FAILED ? -reinterpret_cast<intptr_t>(data) : ECONNABORTED);
01657
01658
01659
01660
01661
01662
01663
01664
01665 if (EADDRNOTAVAIL == t_state.current.server->connect_result) {
01666 if (is_debug_tag_set("http_tproxy")) {
01667 ip_port_text_buffer ip_c, ip_s;
01668 Debug("http_tproxy", "Force close of client connect (%s->%s) due to EADDRNOTAVAIL [%" PRId64 "]"
01669 , ats_ip_nptop(&t_state.client_info.addr.sa, ip_c, sizeof ip_c)
01670 , ats_ip_nptop(&t_state.server_info.addr.sa, ip_s, sizeof ip_s)
01671 , sm_id
01672 );
01673 }
01674 t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
01675 terminate_sm = true;
01676 } else {
01677 call_transact_and_set_next_state(HttpTransact::HandleResponse);
01678 }
01679 return 0;
01680 case CONGESTION_EVENT_CONGESTED_ON_F:
01681 t_state.current.state = HttpTransact::CONGEST_CONTROL_CONGESTED_ON_F;
01682 call_transact_and_set_next_state(HttpTransact::HandleResponse);
01683 return 0;
01684 case CONGESTION_EVENT_CONGESTED_ON_M:
01685 t_state.current.state = HttpTransact::CONGEST_CONTROL_CONGESTED_ON_M;
01686 call_transact_and_set_next_state(HttpTransact::HandleResponse);
01687 return 0;
01688
01689 default:
01690 Error("[HttpSM::state_http_server_open] Unknown event: %d", event);
01691 ink_release_assert(0);
01692 return 0;
01693 }
01694
01695 return 0;
01696 }
01697
01698
01699 int
01700 HttpSM::state_read_server_response_header(int event, void *data)
01701 {
01702 STATE_ENTER(&HttpSM::state_read_server_response_header, event);
01703 ink_assert(server_entry->read_vio == (VIO *) data);
01704 ink_assert(t_state.current.server->state == HttpTransact::STATE_UNDEFINED);
01705 ink_assert(t_state.current.state == HttpTransact::STATE_UNDEFINED);
01706
01707 int bytes_used = 0;
01708 VIO *vio = (VIO *) data;
01709
01710 switch (event) {
01711 case VC_EVENT_EOS:
01712 server_entry->eos = true;
01713
01714
01715
01716
01717
01718
01719 if (vio->ndone == 0) {
01720
01721 handle_server_setup_error(event, data);
01722 return 0;
01723 }
01724
01725 case VC_EVENT_READ_READY:
01726 case VC_EVENT_READ_COMPLETE:
01727
01728 break;
01729
01730 case VC_EVENT_ERROR:
01731 case VC_EVENT_INACTIVITY_TIMEOUT:
01732 case VC_EVENT_ACTIVE_TIMEOUT:
01733
01734 handle_server_setup_error(event, data);
01735 return 0;
01736 }
01737
01738
01739
01740
01741
01742 if (server_response_hdr_bytes == 0) {
01743 milestones.server_first_read = ink_get_hrtime();
01744
01745 if (t_state.api_txn_no_activity_timeout_value != -1) {
01746 server_session->get_netvc()->set_inactivity_timeout(HRTIME_MSECONDS(t_state.api_txn_no_activity_timeout_value));
01747 } else {
01748 server_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_out));
01749 }
01750
01751
01752 if (ua_session && t_state.hdr_info.request_content_length) {
01753 ua_session->get_netvc()->cancel_inactivity_timeout();
01754 }
01755 }
01756
01757
01758
01759 int state = t_state.hdr_info.server_response.parse_resp(&http_parser, server_buffer_reader,
01760 &bytes_used, server_entry->eos);
01761
01762 server_response_hdr_bytes += bytes_used;
01763
01764
01765
01766
01767
01768 if (state == PARSE_DONE &&
01769 t_state.hdr_info.server_response.version_get() == HTTPVersion(0, 9) && server_session->transact_count > 1) {
01770 state = PARSE_ERROR;
01771 }
01772
01773 if (server_response_hdr_bytes > t_state.txn_conf->response_hdr_max_size) {
01774 state = PARSE_ERROR;
01775 }
01776
01777 if (state != PARSE_CONT) {
01778
01779 server_entry->read_vio->nbytes = server_entry->read_vio->ndone;
01780 http_parser_clear(&http_parser);
01781 milestones.server_read_header_done = ink_get_hrtime();
01782 }
01783
01784 switch (state) {
01785 case PARSE_ERROR:
01786 {
01787
01788
01789
01790
01791
01792 bool allow_error = false;
01793 if (t_state.hdr_info.server_response.type_get() == HTTP_TYPE_RESPONSE &&
01794 t_state.hdr_info.server_response.status_get() == HTTP_STATUS_MOVED_TEMPORARILY) {
01795 if (t_state.hdr_info.server_response.field_find(MIME_FIELD_LOCATION, MIME_LEN_LOCATION)) {
01796 allow_error = true;
01797 }
01798 }
01799
01800 if (allow_error == false) {
01801 DebugSM("http_seq", "Error parsing server response header");
01802 t_state.current.state = HttpTransact::PARSE_ERROR;
01803
01804
01805
01806
01807 if (event == VC_EVENT_EOS) {
01808 handle_server_setup_error(VC_EVENT_EOS, data);
01809 } else {
01810 call_transact_and_set_next_state(HttpTransact::HandleResponse);
01811 }
01812 break;
01813 }
01814
01815 }
01816 case PARSE_DONE:
01817 DebugSM("http_seq", "Done parsing server response header");
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844 t_state.current.state = HttpTransact::CONNECTION_ALIVE;
01845 t_state.transact_return_point = HttpTransact::HandleResponse;
01846 t_state.api_next_action = HttpTransact::SM_ACTION_API_READ_RESPONSE_HDR;
01847
01848
01849 if (enable_redirection && (redirection_tries < HttpConfig::m_master.number_of_redirections)) {
01850 ++redirection_tries;
01851 } else {
01852 tunnel.deallocate_redirect_postdata_buffers();
01853 enable_redirection = false;
01854 }
01855
01856 do_api_callout();
01857 break;
01858 case PARSE_CONT:
01859 ink_assert(server_entry->eos == false);
01860 server_entry->read_vio->reenable();
01861 return VC_EVENT_CONT;
01862
01863 default:
01864 ink_assert(!"not reached");
01865 }
01866
01867 return 0;
01868 }
01869
01870 int
01871 HttpSM::state_send_server_request_header(int event, void *data)
01872 {
01873 STATE_ENTER(&HttpSM::state_send_server_request_header, event);
01874 ink_assert(server_entry != NULL);
01875 ink_assert(server_entry->write_vio == (VIO *) data || server_entry->read_vio == (VIO *) data);
01876
01877 int method;
01878
01879 switch (event) {
01880 case VC_EVENT_WRITE_READY:
01881 server_entry->write_vio->reenable();
01882 break;
01883
01884 case VC_EVENT_WRITE_COMPLETE:
01885
01886
01887 free_MIOBuffer(server_entry->write_buffer);
01888 server_entry->write_buffer = NULL;
01889 method = t_state.hdr_info.server_request.method_get_wksidx();
01890 if (!t_state.api_server_request_body_set &&
01891 method != HTTP_WKSIDX_TRACE &&
01892 (t_state.hdr_info.request_content_length > 0 || t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING)) {
01893
01894 if (post_transform_info.vc) {
01895 setup_transform_to_server_transfer();
01896 } else {
01897 if (t_state.http_config_param->send_100_continue_response) {
01898 int len = 0;
01899 const char *expect = t_state.hdr_info.client_request.value_get(MIME_FIELD_EXPECT, MIME_LEN_EXPECT, &len);
01900
01901
01902 if ((len == HTTP_LEN_100_CONTINUE) && (strncasecmp(expect, HTTP_VALUE_100_CONTINUE, HTTP_LEN_100_CONTINUE) == 0)) {
01903 int64_t alloc_index = buffer_size_to_index(len_100_continue_response);
01904 ua_entry->write_buffer = new_MIOBuffer(alloc_index);
01905 IOBufferReader *buf_start = ua_entry->write_buffer->alloc_reader();
01906
01907 DebugSM("http_seq", "send 100 Continue response to client");
01908 int64_t nbytes = ua_entry->write_buffer->write(str_100_continue_response, len_100_continue_response);
01909 ua_session->do_io_write(ua_session->get_netvc(), nbytes, buf_start);
01910 }
01911 }
01912 do_setup_post_tunnel(HTTP_SERVER_VC);
01913 }
01914 } else {
01915
01916 setup_server_read_response_header();
01917 }
01918
01919 break;
01920
01921 case VC_EVENT_READ_READY:
01922
01923
01924
01925
01926
01927
01928 ink_assert(server_entry->read_vio == (VIO *) data);
01929
01930
01931
01932
01933
01934
01935
01936 break;
01937
01938 case VC_EVENT_EOS:
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950 server_entry->eos = true;
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963 case VC_EVENT_ERROR:
01964 case VC_EVENT_ACTIVE_TIMEOUT:
01965 case VC_EVENT_INACTIVITY_TIMEOUT:
01966 handle_server_setup_error(event, data);
01967 break;
01968
01969 default:
01970 ink_release_assert(0);
01971 break;
01972 }
01973
01974 return 0;
01975 }
01976
01977 void
01978 HttpSM::process_srv_info(HostDBInfo * r)
01979 {
01980 DebugSM("dns_srv", "beginning process_srv_info");
01981
01982
01983 if (!r || !r->is_srv || !r->round_robin) {
01984 t_state.dns_info.srv_hostname[0] = '\0';
01985 t_state.dns_info.srv_lookup_success = false;
01986 t_state.srv_lookup = false;
01987 DebugSM("dns_srv", "No SRV records were available, continuing to lookup %s", t_state.dns_info.lookup_name);
01988 } else {
01989 HostDBRoundRobin *rr = r->rr();
01990 HostDBInfo *srv = NULL;
01991 if (rr) {
01992 srv = rr->select_best_srv(t_state.dns_info.srv_hostname, &mutex.m_ptr->thread_holding->generator,
01993 ink_cluster_time(), (int) t_state.txn_conf->down_server_timeout);
01994 }
01995 if (!srv) {
01996 t_state.dns_info.srv_lookup_success = false;
01997 t_state.dns_info.srv_hostname[0] = '\0';
01998 t_state.srv_lookup = false;
01999 DebugSM("dns_srv", "SRV records empty for %s", t_state.dns_info.lookup_name);
02000 } else {
02001 ink_assert(r->md5_high == srv->md5_high && r->md5_low == srv->md5_low &&
02002 r->md5_low_low == srv->md5_low_low);
02003 t_state.dns_info.srv_lookup_success = true;
02004 t_state.dns_info.srv_port = srv->data.srv.srv_port;
02005 t_state.dns_info.srv_app = srv->app;
02006
02007 ink_assert(srv->data.srv.key == makeHostHash(t_state.dns_info.srv_hostname));
02008 DebugSM("dns_srv", "select SRV records %s", t_state.dns_info.srv_hostname);
02009 }
02010 }
02011 return;
02012 }
02013
02014 void
02015 HttpSM::process_hostdb_info(HostDBInfo * r)
02016 {
02017 if (r && !r->failed()) {
02018 ink_time_t now = ink_cluster_time();
02019 HostDBInfo *ret = NULL;
02020 t_state.dns_info.lookup_success = true;
02021 t_state.dns_info.lookup_validated = true;
02022 if (r->round_robin) {
02023
02024
02025 if (t_state.http_config_param->use_client_target_addr == 1
02026 && t_state.client_info.is_transparent
02027 && t_state.dns_info.os_addr_style == HttpTransact::DNSLookupInfo::OS_ADDR_TRY_DEFAULT) {
02028
02029 HostDBRoundRobin *rr = r->rr();
02030 sockaddr const* addr = t_state.state_machine->ua_session->get_netvc()->get_local_addr();
02031 if (rr && rr->find_ip(addr) == NULL) {
02032
02033
02034 DebugSM("http", "use_client_target_addr == 1. Client specified address is not in the pool. Client address is not validated.");
02035 t_state.dns_info.lookup_validated = false;
02036 }
02037
02038
02039
02040
02041 ats_ip_copy(t_state.host_db_info.ip(), addr);
02042 t_state.dns_info.os_addr_style = HttpTransact::DNSLookupInfo::OS_ADDR_TRY_CLIENT;
02043 } else {
02044
02045
02046
02047 HostDBRoundRobin *rr = r->rr();
02048 ret = rr->select_best_http(&t_state.client_info.addr.sa, now, (int) t_state.txn_conf->down_server_timeout);
02049
02050
02051 if (t_state.dns_info.srv_lookup_success) {
02052 uint32_t last_failure = 0xFFFFFFFF;
02053 for (int i = 0; i < rr->rrcount && last_failure != 0; ++i) {
02054 if (last_failure > rr->info[i].app.http_data.last_failure)
02055 last_failure = rr->info[i].app.http_data.last_failure;
02056 }
02057
02058 if (last_failure != 0 && (uint32_t) (now - t_state.txn_conf->down_server_timeout) < last_failure) {
02059 HostDBApplicationInfo app;
02060 app.allotment.application1 = 0;
02061 app.allotment.application2 = 0;
02062 app.http_data.last_failure = last_failure;
02063 hostDBProcessor.setby_srv(t_state.dns_info.lookup_name, 0, t_state.dns_info.srv_hostname, &app);
02064 }
02065 }
02066 }
02067 } else {
02068 if (t_state.http_config_param->use_client_target_addr == 1
02069 && t_state.client_info.is_transparent
02070 && t_state.dns_info.os_addr_style == HttpTransact::DNSLookupInfo::OS_ADDR_TRY_DEFAULT) {
02071
02072 sockaddr const* addr = t_state.state_machine->ua_session->get_netvc()->get_local_addr();
02073 if (!ats_ip_addr_eq(addr, &r->data.ip.sa)) {
02074 DebugSM("http", "use_client_target_addr == 1. Comparing single addresses failed. Client address is not validated.");
02075 t_state.dns_info.lookup_validated = false;
02076 }
02077
02078
02079
02080
02081 ats_ip_copy(t_state.host_db_info.ip(), addr);
02082 t_state.dns_info.os_addr_style = HttpTransact::DNSLookupInfo::OS_ADDR_TRY_CLIENT;
02083
02084
02085 }
02086 else {
02087 ret = r;
02088 }
02089 }
02090 if (ret) {
02091 t_state.host_db_info = *ret;
02092 ink_release_assert(!t_state.host_db_info.reverse_dns);
02093 ink_release_assert(ats_is_ip(t_state.host_db_info.ip()));
02094 }
02095 } else {
02096 DebugSM("http", "[%" PRId64 "] DNS lookup failed for '%s'", sm_id, t_state.dns_info.lookup_name);
02097
02098 t_state.dns_info.lookup_success = false;
02099 t_state.host_db_info.app.allotment.application1 = 0;
02100 t_state.host_db_info.app.allotment.application2 = 0;
02101 ink_assert(!t_state.host_db_info.round_robin);
02102 }
02103
02104 milestones.dns_lookup_end = ink_get_hrtime();
02105
02106 if (is_debug_tag_set("http_timeout")) {
02107 if (t_state.api_txn_dns_timeout_value != -1) {
02108 int foo = (int) (milestone_difference_msec(milestones.dns_lookup_begin, milestones.dns_lookup_end));
02109 DebugSM("http_timeout", "DNS took: %d msec", foo);
02110 }
02111 }
02112 }
02113
02114
02115
02116
02117
02118
02119 int
02120 HttpSM::state_hostdb_lookup(int event, void *data)
02121 {
02122 STATE_ENTER(&HttpSM::state_hostdb_lookup, event);
02123
02124
02125
02126
02127 ink_assert(t_state.req_flavor == HttpTransact::REQ_FLAVOR_SCHEDULED_UPDATE ||
02128 t_state.req_flavor == HttpTransact::REQ_FLAVOR_REVPROXY || ua_entry->vc != NULL);
02129
02130 switch (event) {
02131 case EVENT_HOST_DB_LOOKUP:
02132 pending_action = NULL;
02133 process_hostdb_info((HostDBInfo *) data);
02134 call_transact_and_set_next_state(NULL);
02135 break;
02136 case EVENT_SRV_LOOKUP:
02137 {
02138 pending_action = NULL;
02139 process_srv_info((HostDBInfo *) data);
02140
02141 char *host_name = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_hostname : t_state.dns_info.lookup_name;
02142 HostDBProcessor::Options opt;
02143 opt.port = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_port : t_state.server_info.port;
02144 opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing)
02145 ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS
02146 : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD
02147 ;
02148 opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
02149 opt.host_res_style = ua_session->host_res_style;
02150
02151 Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this,
02152 (process_hostdb_info_pfn) & HttpSM::
02153 process_hostdb_info,
02154 host_name, 0,
02155 opt);
02156 if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
02157 ink_assert(!pending_action);
02158 pending_action = dns_lookup_action_handle;
02159 historical_action = pending_action;
02160 } else {
02161 call_transact_and_set_next_state(NULL);
02162 }
02163 }
02164 break;
02165 case EVENT_HOST_DB_IP_REMOVED:
02166 ink_assert(!"Unexpected event from HostDB");
02167 break;
02168 default:
02169 ink_assert(!"Unexpected event");
02170 }
02171
02172 return 0;
02173 }
02174
02175 int
02176 HttpSM::state_hostdb_reverse_lookup(int event, void *data)
02177 {
02178 STATE_ENTER(&HttpSM::state_hostdb_reverse_lookup, event);
02179
02180
02181
02182 ink_assert(t_state.req_flavor == HttpTransact::REQ_FLAVOR_SCHEDULED_UPDATE ||
02183 t_state.req_flavor == HttpTransact::REQ_FLAVOR_REVPROXY || ua_entry->vc != NULL);
02184
02185 switch (event) {
02186 case EVENT_HOST_DB_LOOKUP:
02187 pending_action = NULL;
02188 if (data) {
02189 t_state.request_data.hostname_str = ((HostDBInfo *) data)->hostname();
02190 } else {
02191 DebugSM("http", "[%" PRId64 "] reverse DNS lookup failed for '%s'", sm_id, t_state.dns_info.lookup_name);
02192 }
02193 call_transact_and_set_next_state(NULL);
02194 break;
02195 default:
02196 ink_assert(!"Unexpected event");
02197 }
02198
02199 return 0;
02200 }
02201
02202
02203
02204
02205
02206
02207 int
02208 HttpSM::state_mark_os_down(int event, void *data)
02209 {
02210 HostDBInfo *mark_down = NULL;
02211
02212 if (event == EVENT_HOST_DB_LOOKUP && data) {
02213 HostDBInfo *r = (HostDBInfo *) data;
02214
02215 if (r->round_robin) {
02216
02217 ink_assert(t_state.current.server != NULL);
02218 ink_assert(t_state.current.request_to == HttpTransact::ORIGIN_SERVER);
02219 if (t_state.current.server) {
02220 mark_down = r->rr()->find_ip(&t_state.current.server->addr.sa);
02221 }
02222 } else {
02223
02224 if (ats_ip_addr_eq(t_state.host_db_info.ip(), r->ip())) {
02225 mark_down = r;
02226 }
02227 }
02228
02229 if (mark_down) {
02230 mark_host_failure(mark_down, t_state.request_sent_time);
02231 }
02232 }
02233
02234
02235 return state_hostdb_lookup(event, data);
02236 }
02237
02238
02239
02240
02241
02242
02243 int
02244 HttpSM::state_handle_stat_page(int event, void *data)
02245 {
02246 STATE_ENTER(&HttpSM::state_handle_stat_page, event);
02247 switch (event) {
02248 case STAT_PAGE_SUCCESS:
02249 pending_action = NULL;
02250
02251 if (data) {
02252 StatPageData *spd = (StatPageData *) data;
02253
02254 t_state.internal_msg_buffer = spd->data;
02255 if (spd->type)
02256 t_state.internal_msg_buffer_type = spd->type;
02257 else
02258 t_state.internal_msg_buffer_type = NULL;
02259 t_state.internal_msg_buffer_size = spd->length;
02260 t_state.internal_msg_buffer_fast_allocator_size = -1;
02261 }
02262
02263 call_transact_and_set_next_state(HttpTransact::HandleStatPage);
02264 break;
02265
02266 case STAT_PAGE_FAILURE:
02267 pending_action = NULL;
02268 call_transact_and_set_next_state(HttpTransact::HandleStatPage);
02269 break;
02270
02271 default:
02272 ink_release_assert(0);
02273 break;
02274 }
02275
02276 return 0;
02277 }
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322 int
02323 HttpSM::state_icp_lookup(int event, void *data)
02324 {
02325 STATE_ENTER(&HttpSM::state_icp_lookup, event);
02326
02327
02328 ink_release_assert(ua_entry != NULL ||
02329 t_state.req_flavor == HttpTransact::REQ_FLAVOR_SCHEDULED_UPDATE ||
02330 t_state.req_flavor == HttpTransact::REQ_FLAVOR_REVPROXY);
02331 pending_action = NULL;
02332
02333 switch (event) {
02334 case ICP_LOOKUP_FOUND:
02335
02336 DebugSM("http", "ICP says ICP_LOOKUP_FOUND");
02337 t_state.icp_lookup_success = true;
02338 t_state.icp_ip_result = *(struct sockaddr_in *) data;
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352 break;
02353
02354 case ICP_LOOKUP_FAILED:
02355 DebugSM("http", "ICP says ICP_LOOKUP_FAILED");
02356 t_state.icp_lookup_success = false;
02357 break;
02358 default:
02359 ink_release_assert(0);
02360 break;
02361 }
02362
02363 call_transact_and_set_next_state(HttpTransact::HandleICPLookup);
02364
02365 return 0;
02366 }
02367
02368
02369
02370
02371
02372
02373
02374
02375 int
02376 HttpSM::state_cache_open_write(int event, void *data)
02377 {
02378 STATE_ENTER(&HttpSM:state_cache_open_write, event);
02379 milestones.cache_open_write_end = ink_get_hrtime();
02380 pending_action = NULL;
02381
02382 switch (event) {
02383 case CACHE_EVENT_OPEN_WRITE:
02384
02385
02386
02387 t_state.cache_info.write_lock_state = HttpTransact::CACHE_WL_SUCCESS;
02388 break;
02389
02390 case CACHE_EVENT_OPEN_WRITE_FAILED:
02391
02392
02393 t_state.cache_info.write_lock_state = HttpTransact::CACHE_WL_FAIL;
02394 break;
02395
02396 case CACHE_EVENT_OPEN_READ:
02397
02398
02399 cache_sm.cache_read_vc->get_http_info(&t_state.cache_info.object_read);
02400 t_state.cache_info.is_ram_cache_hit = (cache_sm.cache_read_vc)->is_ram_cache_hit();
02401
02402 ink_assert(t_state.cache_info.object_read != 0);
02403 t_state.source = HttpTransact::SOURCE_CACHE;
02404
02405
02406 t_state.cache_lookup_result = HttpTransact::CACHE_LOOKUP_NONE;
02407 t_state.cache_info.write_lock_state = HttpTransact::CACHE_WL_READ_RETRY;
02408 break;
02409
02410 case HTTP_TUNNEL_EVENT_DONE:
02411
02412
02413
02414
02415
02416
02417 if (t_state.next_action == HttpTransact::SM_ACTION_CACHE_ISSUE_WRITE_TRANSFORM) {
02418 state_common_wait_for_transform_read(&transform_info, &HttpSM::tunnel_handler, event, data);
02419
02420 return 0;
02421 }
02422
02423 default:
02424 ink_release_assert(0);
02425 }
02426
02427 if (t_state.api_lock_url != HttpTransact::LOCK_URL_FIRST) {
02428 if (event == CACHE_EVENT_OPEN_WRITE || event == CACHE_EVENT_OPEN_WRITE_FAILED) {
02429 if (t_state.api_lock_url == HttpTransact::LOCK_URL_SECOND) {
02430 t_state.api_lock_url = HttpTransact::LOCK_URL_ORIGINAL;
02431 do_cache_prepare_action(second_cache_sm, t_state.cache_info.second_object_read, true);
02432 return 0;
02433 } else {
02434 t_state.api_lock_url = HttpTransact::LOCK_URL_DONE;
02435 }
02436 } else if (event != CACHE_EVENT_OPEN_READ || t_state.api_lock_url != HttpTransact::LOCK_URL_SECOND)
02437 t_state.api_lock_url = HttpTransact::LOCK_URL_QUIT;
02438 }
02439
02440 call_transact_and_set_next_state(NULL);
02441
02442 return 0;
02443 }
02444
02445 inline void
02446 HttpSM::setup_cache_lookup_complete_api()
02447 {
02448 t_state.api_next_action = HttpTransact::SM_ACTION_API_CACHE_LOOKUP_COMPLETE;
02449 do_api_callout();
02450 }
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461 int
02462 HttpSM::state_cache_open_read(int event, void *data)
02463 {
02464 STATE_ENTER(&HttpSM::state_cache_open_read, event);
02465 milestones.cache_open_read_end = ink_get_hrtime();
02466
02467 ink_assert(server_entry == NULL);
02468 ink_assert(t_state.cache_info.object_read == 0);
02469
02470 switch (event) {
02471 case CACHE_EVENT_OPEN_READ:
02472 {
02473 pending_action = NULL;
02474
02475 DebugSM("http", "[%" PRId64 "] cache_open_read - CACHE_EVENT_OPEN_READ", sm_id);
02476
02477
02478
02479
02480 ink_assert(cache_sm.cache_read_vc != NULL);
02481 t_state.source = HttpTransact::SOURCE_CACHE;
02482
02483 cache_sm.cache_read_vc->get_http_info(&t_state.cache_info.object_read);
02484 t_state.cache_info.is_ram_cache_hit = (cache_sm.cache_read_vc)->is_ram_cache_hit();
02485
02486 ink_assert(t_state.cache_info.object_read != 0);
02487 call_transact_and_set_next_state(HttpTransact::HandleCacheOpenRead);
02488 break;
02489 }
02490 case CACHE_EVENT_OPEN_READ_FAILED:
02491 pending_action = NULL;
02492
02493 DebugSM("http", "[%" PRId64 "] cache_open_read - " "CACHE_EVENT_OPEN_READ_FAILED", sm_id);
02494 DebugSM("http", "[state_cache_open_read] open read failed.");
02495
02496
02497 if (data == (void *) -ECACHE_DOC_BUSY)
02498 t_state.cache_lookup_result = HttpTransact::CACHE_LOOKUP_DOC_BUSY;
02499 else
02500 t_state.cache_lookup_result = HttpTransact::CACHE_LOOKUP_MISS;
02501
02502 ink_assert(t_state.transact_return_point == NULL);
02503 t_state.transact_return_point = HttpTransact::HandleCacheOpenRead;
02504 setup_cache_lookup_complete_api();
02505 break;
02506
02507 default:
02508 ink_release_assert("!Unknown event");
02509 break;
02510 }
02511
02512 return 0;
02513 }
02514
02515 int
02516 HttpSM::main_handler(int event, void *data)
02517 {
02518 ink_release_assert(magic == HTTP_SM_MAGIC_ALIVE);
02519
02520 HttpSMHandler jump_point = NULL;
02521 ink_assert(reentrancy_count >= 0);
02522 reentrancy_count++;
02523
02524
02525
02526 DebugSM("http", "[%" PRId64 "] [HttpSM::main_handler, %s]", sm_id, HttpDebugNames::get_event_name(event));
02527
02528 HttpVCTableEntry *vc_entry = NULL;
02529
02530 if (data != NULL) {
02531
02532
02533
02534 if (event < VC_EVENT_EVENTS_START + 100) {
02535 vc_entry = vc_table.find_entry((VIO *) data);
02536 }
02537 }
02538
02539 if (vc_entry) {
02540 jump_point = vc_entry->vc_handler;
02541 ink_assert(jump_point != (HttpSMHandler)NULL);
02542 ink_assert(vc_entry->vc != (VConnection *)NULL);
02543 (this->*jump_point) (event, data);
02544 } else {
02545 ink_assert(default_handler != (HttpSMHandler)NULL);
02546 (this->*default_handler) (event, data);
02547 }
02548
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558 if (terminate_sm == true && reentrancy_count == 1) {
02559 kill_this();
02560 } else {
02561 reentrancy_count--;
02562 ink_assert(reentrancy_count >= 0);
02563 }
02564
02565 return (VC_EVENT_CONT);
02566
02567 }
02568
02569
02570
02571
02572
02573
02574 void
02575 HttpSM::tunnel_handler_post_or_put(HttpTunnelProducer * p)
02576 {
02577 ink_assert(p->vc_type == HT_HTTP_CLIENT);
02578 HttpTunnelConsumer *c;
02579
02580
02581
02582
02583
02584
02585
02586 if (post_transform_info.vc != NULL) {
02587 ink_assert(post_transform_info.entry->in_tunnel == true);
02588 ink_assert(post_transform_info.vc == post_transform_info.entry->vc);
02589 vc_table.cleanup_entry(post_transform_info.entry);
02590 post_transform_info.entry = NULL;
02591 }
02592
02593 switch (p->handler_state) {
02594 case HTTP_SM_POST_SERVER_FAIL:
02595 c = tunnel.get_consumer(server_entry->vc);
02596 ink_assert(c->write_success == false);
02597 break;
02598 case HTTP_SM_POST_UA_FAIL:
02599
02600 ink_assert(p->read_success == false);
02601 terminate_sm = true;
02602 break;
02603 case HTTP_SM_POST_SUCCESS:
02604
02605 ink_assert(p->read_success == true);
02606 ink_assert(p->consumer_list.head->write_success == true);
02607 tunnel.deallocate_buffers();
02608 tunnel.reset();
02609
02610
02611 ink_release_assert(ua_entry->in_tunnel == false);
02612 server_entry->in_tunnel = false;
02613
02614 break;
02615 default:
02616 ink_release_assert(0);
02617 }
02618 }
02619
02620
02621
02622
02623
02624
02625 int
02626 HttpSM::tunnel_handler_post(int event, void *data)
02627 {
02628 STATE_ENTER(&HttpSM::tunnel_handler_post, event);
02629
02630 ink_assert(event == HTTP_TUNNEL_EVENT_DONE);
02631 ink_assert(data == &tunnel);
02632
02633
02634 HttpTunnelProducer *p = tunnel.get_producer(ua_session);
02635 int p_handler_state = p->handler_state;
02636 tunnel_handler_post_or_put(p);
02637
02638 switch (p_handler_state) {
02639 case HTTP_SM_POST_SERVER_FAIL:
02640 handle_post_failure();
02641 break;
02642 case HTTP_SM_POST_UA_FAIL:
02643 break;
02644 case HTTP_SM_POST_SUCCESS:
02645
02646 setup_server_read_response_header();
02647 break;
02648 default:
02649 ink_release_assert(0);
02650 }
02651
02652 return 0;
02653 }
02654
02655 int
02656 HttpSM::tunnel_handler_cache_fill(int event, void *data)
02657 {
02658 STATE_ENTER(&HttpSM::tunnel_handler_cache_fill, event);
02659
02660 ink_assert(event == HTTP_TUNNEL_EVENT_DONE);
02661 ink_assert(data == &tunnel);
02662
02663 ink_release_assert(cache_sm.cache_write_vc);
02664
02665 tunnel.deallocate_buffers();
02666 tunnel.deallocate_redirect_postdata_buffers();
02667 tunnel.reset();
02668
02669 setup_server_transfer_to_cache_only();
02670 tunnel.tunnel_run();
02671
02672 return 0;
02673 }
02674
02675 int
02676 HttpSM::tunnel_handler_100_continue(int event, void *data)
02677 {
02678 STATE_ENTER(&HttpSM::tunnel_handler_100_continue, event);
02679
02680 ink_assert(event == HTTP_TUNNEL_EVENT_DONE);
02681 ink_assert(data == &tunnel);
02682
02683
02684
02685
02686 HttpTunnelConsumer *c = tunnel.get_consumer(ua_session);
02687
02688 if (c->write_success) {
02689
02690
02691 t_state.hdr_info.client_response.destroy();
02692 tunnel.deallocate_buffers();
02693 tunnel.deallocate_redirect_postdata_buffers();
02694 tunnel.reset();
02695
02696 if (server_entry->eos) {
02697
02698
02699
02700 DebugSM("http", "[%" PRId64 "] tunnel_handler_100_continue - server already " "closed, terminating connection", sm_id);
02701
02702
02703
02704 t_state.hdr_info.server_response.destroy();
02705 t_state.hdr_info.server_response.create(HTTP_TYPE_RESPONSE);
02706 handle_server_setup_error(VC_EVENT_EOS, server_entry->read_vio);
02707 } else {
02708 setup_server_read_response_header();
02709 }
02710 } else {
02711 terminate_sm = true;
02712 }
02713
02714 return 0;
02715 }
02716
02717 int
02718 HttpSM::tunnel_handler_push(int event, void *data)
02719 {
02720 STATE_ENTER(&HttpSM::tunnel_handler_push, event);
02721
02722 ink_assert(event == HTTP_TUNNEL_EVENT_DONE);
02723 ink_assert(data == &tunnel);
02724
02725
02726 HttpTunnelProducer *ua = tunnel.get_producer(ua_session);
02727
02728 if (!ua->read_success) {
02729
02730
02731 terminate_sm = true;
02732 return 0;
02733 }
02734
02735 HttpTunnelConsumer *cache = ua->consumer_list.head;
02736 ink_release_assert(cache->vc_type == HT_CACHE_WRITE);
02737 bool cache_write_success = cache->write_success;
02738
02739
02740
02741 tunnel.deallocate_buffers();
02742 tunnel.deallocate_redirect_postdata_buffers();
02743 tunnel.reset();
02744
02745 if (cache_write_success) {
02746 call_transact_and_set_next_state(HttpTransact::HandlePushTunnelSuccess);
02747 } else {
02748 call_transact_and_set_next_state(HttpTransact::HandlePushTunnelFailure);
02749 }
02750
02751 return 0;
02752 }
02753
02754 int
02755 HttpSM::tunnel_handler(int event, void *data)
02756 {
02757 STATE_ENTER(&HttpSM::tunnel_handler, event);
02758
02759 ink_assert(event == HTTP_TUNNEL_EVENT_DONE);
02760 ink_assert(data == &tunnel);
02761
02762 terminate_sm = true;
02763
02764 if (unlikely(t_state.is_websocket)) {
02765 HTTP_DECREMENT_DYN_STAT(http_websocket_current_active_client_connections_stat);
02766 }
02767
02768 return 0;
02769 }
02770
02771
02772
02773
02774
02775
02776
02777 bool
02778 HttpSM::is_http_server_eos_truncation(HttpTunnelProducer * p)
02779 {
02780
02781 if ((p->do_dechunking || p->do_chunked_passthru) && p->chunked_handler.truncation) {
02782 return true;
02783 }
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799 int64_t cl = t_state.hdr_info.server_response.get_content_length();
02800
02801 if (cl != UNDEFINED_COUNT && cl > server_response_body_bytes) {
02802 DebugSM("http", "[%" PRId64 "] server eos after %" PRId64". Expected %" PRId64, sm_id, cl, server_response_body_bytes);
02803 return true;
02804 } else {
02805 return false;
02806 }
02807 }
02808
02809 int
02810 HttpSM::tunnel_handler_server(int event, HttpTunnelProducer * p)
02811 {
02812 STATE_ENTER(&HttpSM::tunnel_handler_server, event);
02813
02814 milestones.server_close = ink_get_hrtime();
02815
02816 bool close_connection = false;
02817
02818 if (t_state.current.server->keep_alive == HTTP_KEEPALIVE &&
02819 server_entry->eos == false && plugin_tunnel_type == HTTP_NO_PLUGIN_TUNNEL) {
02820 close_connection = false;
02821 } else {
02822 close_connection = true;
02823 }
02824
02825 switch (event) {
02826 case VC_EVENT_INACTIVITY_TIMEOUT:
02827 case VC_EVENT_ACTIVE_TIMEOUT:
02828 case VC_EVENT_ERROR:
02829 t_state.squid_codes.log_code = SQUID_LOG_ERR_READ_TIMEOUT;
02830 t_state.squid_codes.hier_code = SQUID_HIER_TIMEOUT_DIRECT;
02831
02832
02833 case VC_EVENT_EOS:
02834
02835 switch (event) {
02836 case VC_EVENT_INACTIVITY_TIMEOUT:
02837 t_state.current.server->state = HttpTransact::INACTIVE_TIMEOUT;
02838 break;
02839 case VC_EVENT_ACTIVE_TIMEOUT:
02840 t_state.current.server->state = HttpTransact::ACTIVE_TIMEOUT;
02841 break;
02842 case VC_EVENT_ERROR:
02843 t_state.current.server->state = HttpTransact::CONNECTION_ERROR;
02844 break;
02845 case VC_EVENT_EOS:
02846 t_state.current.server->state = HttpTransact::TRANSACTION_COMPLETE;
02847 break;
02848 }
02849
02850 close_connection = true;
02851
02852 ink_assert(p->vc_type == HT_HTTP_SERVER);
02853
02854 if (is_http_server_eos_truncation(p)) {
02855 DebugSM("http", "[%" PRId64 "] [HttpSM::tunnel_handler_server] aborting HTTP tunnel due to server truncation", sm_id);
02856 tunnel.chain_abort_all(p);
02857 t_state.current.server->abort = HttpTransact::ABORTED;
02858 t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
02859 t_state.current.server->keep_alive = HTTP_NO_KEEPALIVE;
02860 t_state.squid_codes.log_code = SQUID_LOG_ERR_READ_ERROR;
02861 } else {
02862 DebugSM("http", "[%" PRId64 "] [HttpSM::tunnel_handler_server] finishing HTTP tunnel", sm_id);
02863 p->read_success = true;
02864 t_state.current.server->abort = HttpTransact::DIDNOT_ABORT;
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878 tunnel.local_finish_all(p);
02879 }
02880 break;
02881
02882 case HTTP_TUNNEL_EVENT_PRECOMPLETE:
02883 case VC_EVENT_READ_COMPLETE:
02884
02885
02886
02887
02888 p->read_success = true;
02889 t_state.current.server->state = HttpTransact::TRANSACTION_COMPLETE;
02890 t_state.current.server->abort = HttpTransact::DIDNOT_ABORT;
02891
02892 if (p->do_dechunking || p->do_chunked_passthru) {
02893 if (p->chunked_handler.truncation) {
02894 tunnel.abort_cache_write_finish_others(p);
02895
02896
02897 t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
02898 t_state.current.server->keep_alive = HTTP_NO_KEEPALIVE;
02899 } else {
02900 tunnel.local_finish_all(p);
02901 }
02902 }
02903 break;
02904
02905 case HTTP_TUNNEL_EVENT_CONSUMER_DETACH:
02906
02907
02908 p->read_success = true;
02909 t_state.current.server->state = HttpTransact::TRANSACTION_COMPLETE;
02910 t_state.current.server->abort = HttpTransact::DIDNOT_ABORT;
02911 close_connection = true;
02912 break;
02913
02914 case VC_EVENT_READ_READY:
02915 case VC_EVENT_WRITE_READY:
02916 case VC_EVENT_WRITE_COMPLETE:
02917 default:
02918
02919 ink_assert(0);
02920 break;
02921 }
02922
02923
02924 if (t_state.negative_caching)
02925 t_state.negative_caching = false;
02926
02927
02928 if (background_fill == BACKGROUND_FILL_STARTED) {
02929 background_fill = p->read_success ? BACKGROUND_FILL_COMPLETED : BACKGROUND_FILL_ABORTED;
02930 HTTP_DECREMENT_DYN_STAT(http_background_fill_current_count_stat);
02931 }
02932
02933
02934 ink_assert(server_entry->vc == p->vc);
02935 ink_assert(p->vc_type == HT_HTTP_SERVER);
02936 ink_assert(p->vc == server_session);
02937
02938 if (close_connection) {
02939 p->vc->do_io_close();
02940 p->read_vio = NULL;
02941
02942
02943
02944
02945
02946 if (ua_session && ua_session->f_outbound_transparent && t_state.http_config_param->use_client_source_port) {
02947 t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
02948 }
02949 } else {
02950 server_session->attach_hostname(t_state.current.server->name);
02951 server_session->server_trans_stat--;
02952 HTTP_DECREMENT_DYN_STAT(http_current_server_transactions_stat);
02953
02954
02955
02956
02957
02958
02959 if (t_state.http_config_param->attach_server_session_to_client == 1 &&
02960 ua_session && t_state.client_info.keep_alive == HTTP_KEEPALIVE) {
02961 Debug("http", "attaching server session to the client");
02962 ua_session->attach_server_session(server_session);
02963 } else {
02964
02965 server_session->release();
02966 }
02967 }
02968
02969 return 0;
02970 }
02971
02972
02973
02974
02975
02976
02977
02978 int
02979 HttpSM::tunnel_handler_100_continue_ua(int event, HttpTunnelConsumer * c)
02980 {
02981 STATE_ENTER(&HttpSM::tunnel_handler_100_continue_ua, event);
02982
02983 ink_assert(c->vc == ua_session);
02984
02985 switch (event) {
02986 case VC_EVENT_EOS:
02987 ua_entry->eos = true;
02988
02989 case VC_EVENT_INACTIVITY_TIMEOUT:
02990 case VC_EVENT_ACTIVE_TIMEOUT:
02991 case VC_EVENT_ERROR:
02992 set_ua_abort(HttpTransact::ABORTED, event);
02993 c->vc->do_io_close();
02994 break;
02995 case VC_EVENT_WRITE_COMPLETE:
02996
02997
02998
02999 ua_entry->in_tunnel = false;
03000 c->write_success = true;
03001 }
03002
03003 return 0;
03004 }
03005
03006 bool
03007 HttpSM::is_bg_fill_necessary(HttpTunnelConsumer * c)
03008 {
03009 ink_assert(c->vc_type == HT_HTTP_CLIENT);
03010
03011 if (c->producer->alive &&
03012 server_entry && server_entry->vc &&
03013 c->producer->num_consumers > 1
03014 ) {
03015
03016
03017
03018
03019 if (t_state.txn_conf->background_fill_threshold <= 0.001) {
03020 return true;
03021 }
03022
03023 int64_t ua_cl = t_state.hdr_info.client_response.get_content_length();
03024
03025 if (ua_cl > 0) {
03026 int64_t ua_body_done = c->bytes_written - client_response_hdr_bytes;
03027 float pDone = (float) ua_body_done / ua_cl;
03028
03029
03030
03031
03032 if (pDone <= 1.0 && pDone > t_state.txn_conf->background_fill_threshold) {
03033 return true;
03034 } else {
03035 DebugSM("http", "[%" PRId64 "] no background. Only %%%f of %%%f done [%" PRId64 " / %" PRId64" ]", sm_id, pDone, t_state.txn_conf->background_fill_threshold, ua_body_done, ua_cl);
03036 }
03037
03038 }
03039 }
03040
03041 return false;
03042 }
03043
03044 int
03045 HttpSM::tunnel_handler_ua(int event, HttpTunnelConsumer * c)
03046 {
03047 bool close_connection = true;
03048 HttpTunnelProducer *p = NULL;
03049 HttpTunnelConsumer *selfc = NULL;
03050
03051 STATE_ENTER(&HttpSM::tunnel_handler_ua, event);
03052 ink_assert(c->vc == ua_session);
03053 milestones.ua_close = ink_get_hrtime();
03054
03055 switch (event) {
03056 case VC_EVENT_EOS:
03057 ua_entry->eos = true;
03058
03059 case VC_EVENT_INACTIVITY_TIMEOUT:
03060 case VC_EVENT_ACTIVE_TIMEOUT:
03061 case VC_EVENT_ERROR:
03062
03063
03064
03065 set_ua_abort(HttpTransact::ABORTED, event);
03066
03067 if (is_bg_fill_necessary(c)) {
03068 DebugSM("http", "[%" PRId64 "] Initiating background fill", sm_id);
03069 background_fill = BACKGROUND_FILL_STARTED;
03070 HTTP_INCREMENT_DYN_STAT(http_background_fill_current_count_stat);
03071
03072
03073
03074 ink_assert(server_entry->vc == server_session);
03075 ink_assert(c->is_downstream_from(server_session));
03076 server_session->get_netvc()->
03077 set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->background_fill_active_timeout));
03078 } else {
03079
03080 p = c->producer;
03081 tunnel.chain_abort_all(c->producer);
03082 selfc = p->self_consumer;
03083 if (selfc) {
03084
03085 p = selfc->producer;
03086
03087
03088
03089 if (p->alive &&
03090 ((p->vc_type == HT_CACHE_READ) || (p->vc_type == HT_HTTP_SERVER))) {
03091 tunnel.chain_abort_all(p);
03092 }
03093 }
03094 }
03095 break;
03096
03097 case VC_EVENT_WRITE_COMPLETE:
03098 c->write_success = true;
03099 t_state.client_info.abort = HttpTransact::DIDNOT_ABORT;
03100 if (t_state.client_info.keep_alive == HTTP_KEEPALIVE) {
03101 if (t_state.www_auth_content != HttpTransact::CACHE_AUTH_SERVE || ua_session->get_bound_ss()) {
03102
03103 close_connection = false;
03104 }
03105
03106
03107
03108
03109
03110 }
03111 break;
03112 case VC_EVENT_WRITE_READY:
03113 case VC_EVENT_READ_READY:
03114 case VC_EVENT_READ_COMPLETE:
03115 default:
03116
03117 ink_assert(0);
03118 break;
03119 }
03120
03121 client_response_body_bytes = c->bytes_written - client_response_hdr_bytes;
03122
03123 if (client_response_body_bytes < 0)
03124 client_response_body_bytes = 0;
03125
03126
03127
03128
03129
03130
03131
03132 HttpTransact::Source_t original_source = t_state.source;
03133 if (HttpTransact::SOURCE_TRANSFORM == original_source &&
03134 t_state.range_setup != HttpTransact::RANGE_NONE) {
03135 original_source = t_state.pre_transform_source;
03136 }
03137
03138 switch (original_source) {
03139 case HttpTransact::SOURCE_HTTP_ORIGIN_SERVER:
03140 server_response_body_bytes = client_response_body_bytes;
03141 break;
03142 case HttpTransact::SOURCE_CACHE:
03143 cache_response_body_bytes = client_response_body_bytes;
03144 break;
03145 default:
03146 break;
03147 }
03148
03149 ink_assert(ua_entry->vc == c->vc);
03150 if (close_connection) {
03151
03152
03153 if ((t_state.method == HTTP_WKSIDX_POST || t_state.client_info.pipeline_possible == true)
03154 && event == VC_EVENT_WRITE_COMPLETE) {
03155 ua_session->set_half_close_flag();
03156 }
03157
03158 ua_session->do_io_close();
03159 ua_session = NULL;
03160 } else {
03161 ink_assert(ua_buffer_reader != NULL);
03162 ua_session->release(ua_buffer_reader);
03163 ua_buffer_reader = NULL;
03164 ua_session = NULL;
03165 }
03166
03167 return 0;
03168 }
03169
03170 int
03171 HttpSM::tunnel_handler_ua_push(int event, HttpTunnelProducer * p)
03172 {
03173 STATE_ENTER(&HttpSM::tunnel_handler_ua_push, event);
03174
03175 pushed_response_body_bytes += p->bytes_read;
03176 client_request_body_bytes += p->bytes_read;
03177
03178 switch (event) {
03179 case VC_EVENT_INACTIVITY_TIMEOUT:
03180 case VC_EVENT_ACTIVE_TIMEOUT:
03181 case VC_EVENT_ERROR:
03182 case VC_EVENT_EOS:
03183
03184 t_state.client_info.abort = HttpTransact::ABORTED;
03185 p->vc->do_io_close(EHTTP_ERROR);
03186 p->read_vio = NULL;
03187 tunnel.chain_abort_all(p);
03188 break;
03189
03190 case HTTP_TUNNEL_EVENT_PRECOMPLETE:
03191 case VC_EVENT_READ_COMPLETE:
03192
03193
03194 p->read_success = true;
03195 ua_entry->in_tunnel = false;
03196 break;
03197
03198 case VC_EVENT_READ_READY:
03199 case VC_EVENT_WRITE_READY:
03200 case VC_EVENT_WRITE_COMPLETE:
03201 default:
03202
03203 ink_assert(0);
03204 break;
03205 }
03206
03207 return 0;
03208 }
03209
03210 int
03211 HttpSM::tunnel_handler_cache_read(int event, HttpTunnelProducer * p)
03212 {
03213 STATE_ENTER(&HttpSM::tunnel_handler_cache_read, event);
03214
03215 switch (event) {
03216 case VC_EVENT_ERROR:
03217 case VC_EVENT_EOS:
03218 ink_assert(t_state.cache_info.object_read->valid());
03219 if (t_state.cache_info.object_read->object_size_get() != INT64_MAX || event == VC_EVENT_ERROR) {
03220
03221 t_state.squid_codes.log_code = SQUID_LOG_TCP_SWAPFAIL;
03222 p->vc->do_io_close(EHTTP_ERROR);
03223 p->read_vio = NULL;
03224 tunnel.chain_abort_all(p);
03225 HTTP_INCREMENT_TRANS_STAT(http_cache_read_errors);
03226 break;
03227 } else {
03228 tunnel.local_finish_all(p);
03229
03230
03231 }
03232 case VC_EVENT_READ_COMPLETE:
03233 case HTTP_TUNNEL_EVENT_PRECOMPLETE:
03234 case HTTP_TUNNEL_EVENT_CONSUMER_DETACH:
03235 p->read_success = true;
03236 p->vc->do_io_close();
03237 p->read_vio = NULL;
03238 break;
03239 default:
03240 ink_release_assert(0);
03241 break;
03242 }
03243
03244 HTTP_DECREMENT_DYN_STAT(http_current_cache_connections_stat);
03245 return 0;
03246 }
03247
03248
03249 int
03250 HttpSM::tunnel_handler_cache_write(int event, HttpTunnelConsumer * c)
03251 {
03252 STATE_ENTER(&HttpSM::tunnel_handler_cache_write, event);
03253
03254 HttpTransact::CacheWriteStatus_t * status_ptr =
03255 (c->producer->vc_type == HT_TRANSFORM) ?
03256 &t_state.cache_info.transform_write_status : &t_state.cache_info.write_status;
03257
03258 switch (event) {
03259 case VC_EVENT_ERROR:
03260 case VC_EVENT_EOS:
03261
03262 *status_ptr = HttpTransact::CACHE_WRITE_ERROR;
03263 c->write_vio = NULL;
03264 c->vc->do_io_close(EHTTP_ERROR);
03265
03266 HTTP_INCREMENT_TRANS_STAT(http_cache_write_errors);
03267 DebugSM("http", "[%" PRId64 "] aborting cache write due %s event from cache", sm_id, HttpDebugNames::get_event_name(event));
03268
03269 if (c->producer->alive && c->producer->num_consumers == 1)
03270 tunnel.chain_abort_all(c->producer);
03271 break;
03272 case VC_EVENT_WRITE_COMPLETE:
03273
03274
03275
03276
03277
03278 if (c->write_vio == NULL) {
03279 *status_ptr = HttpTransact::CACHE_WRITE_ERROR;
03280 c->write_success = false;
03281 c->vc->do_io_close(EHTTP_ERROR);
03282 } else {
03283 *status_ptr = HttpTransact::CACHE_WRITE_COMPLETE;
03284 c->write_success = true;
03285 c->write_vio = c->vc->do_io(VIO::CLOSE);
03286 }
03287 break;
03288 default:
03289
03290 ink_assert(0);
03291 break;
03292 }
03293
03294 HTTP_DECREMENT_DYN_STAT(http_current_cache_connections_stat);
03295 return 0;
03296 }
03297
03298 int
03299 HttpSM::tunnel_handler_post_ua(int event, HttpTunnelProducer * p)
03300 {
03301 STATE_ENTER(&HttpSM::tunnel_handler_post_ua, event);
03302 client_request_body_bytes = p->init_bytes_done + p->bytes_read;
03303
03304 switch (event) {
03305 case VC_EVENT_EOS:
03306
03307
03308 case VC_EVENT_ERROR:
03309 case VC_EVENT_INACTIVITY_TIMEOUT:
03310 case VC_EVENT_ACTIVE_TIMEOUT:
03311
03312
03313 p->handler_state = HTTP_SM_POST_UA_FAIL;
03314 tunnel.chain_abort_all(p);
03315 p->read_vio = NULL;
03316 p->vc->do_io_close(EHTTP_ERROR);
03317 set_ua_abort(HttpTransact::ABORTED, event);
03318
03319
03320
03321
03322
03323 hsm_release_assert(ua_entry->in_tunnel == true);
03324 if (p->consumer_list.head->vc_type == HT_TRANSFORM) {
03325 hsm_release_assert(post_transform_info.entry->in_tunnel == true);
03326 } else {
03327 hsm_release_assert(server_entry->in_tunnel == true);
03328 }
03329 break;
03330
03331 case VC_EVENT_READ_COMPLETE:
03332 case HTTP_TUNNEL_EVENT_PRECOMPLETE:
03333
03334
03335
03336 if (t_state.http_config_param->send_100_continue_response &&
03337 ua_entry->write_buffer) {
03338 free_MIOBuffer(ua_entry->write_buffer);
03339 ua_entry->write_buffer = NULL;
03340 }
03341
03342
03343 if (t_state.txn_conf->keep_alive_post_out == 0) {
03344
03345 DebugSM("http_ss", "Setting server session to private because of keep-alive post out");
03346 set_server_session_private(true);
03347 }
03348
03349 p->handler_state = HTTP_SM_POST_SUCCESS;
03350 p->read_success = true;
03351 ua_entry->in_tunnel = false;
03352
03353 if (p->do_dechunking || p->do_chunked_passthru) {
03354 if (p->chunked_handler.truncation) {
03355 tunnel.abort_cache_write_finish_others(p);
03356 } else {
03357 tunnel.local_finish_all(p);
03358 }
03359 }
03360
03361
03362 ua_entry->vc_handler = &HttpSM::state_watch_for_client_abort;
03363 ua_entry->read_vio = p->vc->do_io_read(this, INT64_MAX, ua_buffer_reader->mbuf);
03364 break;
03365 default:
03366 ink_release_assert(0);
03367 }
03368
03369 return 0;
03370 }
03371
03372
03373
03374
03375
03376
03377 int
03378 HttpSM::tunnel_handler_for_partial_post(int event, void * )
03379 {
03380 STATE_ENTER(&HttpSM::tunnel_handler_for_partial_post, event);
03381 tunnel.deallocate_buffers();
03382 tunnel.reset();
03383
03384 tunnel.allocate_redirect_postdata_producer_buffer();
03385
03386 t_state.redirect_info.redirect_in_process = false;
03387
03388 if (post_failed) {
03389 post_failed = false;
03390 handle_post_failure();
03391 } else
03392 do_setup_post_tunnel(HTTP_SERVER_VC);
03393
03394 return 0;
03395 }
03396
03397 int
03398 HttpSM::tunnel_handler_post_server(int event, HttpTunnelConsumer * c)
03399 {
03400 STATE_ENTER(&HttpSM::tunnel_handler_post_server, event);
03401
03402 server_request_body_bytes = c->bytes_written;
03403
03404 switch (event) {
03405 case VC_EVENT_EOS:
03406 case VC_EVENT_ERROR:
03407 case VC_EVENT_INACTIVITY_TIMEOUT:
03408 case VC_EVENT_ACTIVE_TIMEOUT:
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424 server_entry->eos = true;
03425 c->vc->do_io_shutdown(IO_SHUTDOWN_WRITE);
03426
03427
03428
03429 HttpTunnelProducer *ua_producer;
03430 if (c->producer->vc_type == HT_TRANSFORM) {
03431 if (c->producer->handler_state == HTTP_SM_TRANSFORM_OPEN) {
03432 ink_assert(c->producer->vc == post_transform_info.vc);
03433 c->producer->vc->do_io_close();
03434 c->producer->alive = false;
03435 c->producer->self_consumer->alive = false;
03436 }
03437 ua_producer = c->producer->self_consumer->producer;
03438 } else {
03439 ua_producer = c->producer;
03440 }
03441 ink_assert(ua_producer->vc_type == HT_HTTP_CLIENT);
03442 ink_assert(ua_producer->vc == ua_session);
03443 ink_assert(ua_producer->vc == ua_entry->vc);
03444
03445
03446
03447
03448 ua_entry->vc_handler = &HttpSM::state_watch_for_client_abort;
03449
03450
03451
03452
03453 if (enable_redirection) {
03454 if (ua_producer->vc_type == HT_STATIC && event != VC_EVENT_ERROR && event != VC_EVENT_EOS) {
03455 ua_entry->read_vio = ua_producer->vc->do_io_read(this, INT64_MAX, c->producer->read_buffer);
03456
03457 t_state.client_info.pipeline_possible = false;
03458 } else {
03459 if (ua_producer->vc_type == HT_STATIC && t_state.redirect_info.redirect_in_process) {
03460 post_failed = true;
03461 }
03462 }
03463 } else {
03464 ua_entry->read_vio = ua_producer->vc->do_io_read(this, INT64_MAX, c->producer->read_buffer);
03465
03466
03467 t_state.client_info.pipeline_possible = false;
03468 }
03469
03470
03471
03472
03473 ua_producer->alive = false;
03474 ua_producer->handler_state = HTTP_SM_POST_SERVER_FAIL;
03475 ink_assert(tunnel.is_tunnel_alive() == false);
03476 break;
03477
03478 case VC_EVENT_WRITE_COMPLETE:
03479
03480 c->write_success = true;
03481 break;
03482 default:
03483 ink_release_assert(0);
03484 }
03485
03486 return 0;
03487 }
03488
03489 int
03490 HttpSM::tunnel_handler_ssl_producer(int event, HttpTunnelProducer * p)
03491 {
03492
03493 STATE_ENTER(&HttpSM::tunnel_handler_ssl_producer, event);
03494
03495 switch (event) {
03496 case VC_EVENT_EOS:
03497
03498
03499 if (p->self_consumer->alive) {
03500 p->vc->do_io_shutdown(IO_SHUTDOWN_READ);
03501 tunnel.local_finish_all(p);
03502 break;
03503 }
03504
03505 case VC_EVENT_ERROR:
03506 case VC_EVENT_INACTIVITY_TIMEOUT:
03507 case VC_EVENT_ACTIVE_TIMEOUT:
03508
03509
03510
03511
03512 tunnel.close_vc(p);
03513 tunnel.local_finish_all(p);
03514
03515
03516
03517
03518 if (p->self_consumer->producer->alive) {
03519 p->self_consumer->producer->alive = false;
03520 if (p->self_consumer->producer->self_consumer->alive) {
03521 p->self_consumer->producer->vc->do_io_shutdown(IO_SHUTDOWN_READ);
03522 } else {
03523 tunnel.close_vc(p->self_consumer->producer);
03524 }
03525 }
03526 break;
03527 case VC_EVENT_READ_COMPLETE:
03528 case HTTP_TUNNEL_EVENT_PRECOMPLETE:
03529
03530
03531 default:
03532 ink_release_assert(0);
03533 }
03534
03535
03536 switch (p->vc_type) {
03537 case HT_HTTP_SERVER:
03538 server_response_body_bytes += p->bytes_read;
03539 break;
03540 case HT_HTTP_CLIENT:
03541 client_request_body_bytes += p->bytes_read;
03542 break;
03543 default:
03544
03545
03546
03547 break;
03548 }
03549
03550 return 0;
03551 }
03552
03553 int
03554 HttpSM::tunnel_handler_ssl_consumer(int event, HttpTunnelConsumer * c)
03555 {
03556 STATE_ENTER(&HttpSM::tunnel_handler_ssl_consumer, event);
03557
03558 switch (event) {
03559 case VC_EVENT_ERROR:
03560 case VC_EVENT_EOS:
03561 case VC_EVENT_INACTIVITY_TIMEOUT:
03562 case VC_EVENT_ACTIVE_TIMEOUT:
03563
03564
03565 if (c->producer->alive) {
03566 c->producer->alive = false;
03567 if (c->producer->self_consumer->alive) {
03568 c->producer->vc->do_io_shutdown(IO_SHUTDOWN_READ);
03569 } else {
03570 tunnel.close_vc(c->producer);
03571 }
03572 }
03573
03574
03575 tunnel.close_vc(c);
03576 tunnel.local_finish_all(c->self_producer);
03577 break;
03578
03579 case VC_EVENT_WRITE_COMPLETE:
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589 ink_assert(c->producer->alive == false);
03590 c->write_success = true;
03591 if (c->self_producer->alive == true) {
03592 c->vc->do_io_shutdown(IO_SHUTDOWN_WRITE);
03593 if (!c->producer->alive) {
03594 tunnel.close_vc(c);
03595 tunnel.local_finish_all(c->self_producer);
03596 break;
03597 }
03598 } else {
03599 c->vc->do_io_close();
03600 }
03601 break;
03602
03603 default:
03604 ink_release_assert(0);
03605 }
03606
03607
03608 switch (c->vc_type) {
03609 case HT_HTTP_SERVER:
03610 server_request_body_bytes += c->bytes_written;
03611 break;
03612 case HT_HTTP_CLIENT:
03613 client_response_body_bytes += c->bytes_written;
03614 break;
03615 default:
03616
03617
03618
03619 break;
03620 }
03621
03622 return 0;
03623 }
03624
03625 int
03626 HttpSM::tunnel_handler_transform_write(int event, HttpTunnelConsumer * c)
03627 {
03628 STATE_ENTER(&HttpSM::tunnel_handler_transform_write, event);
03629
03630 HttpTransformInfo *i;
03631
03632
03633
03634
03635 if (post_transform_info.entry) {
03636 i = &post_transform_info;
03637 ink_assert(c->vc == i->entry->vc);
03638 } else {
03639 i = &transform_info;
03640 ink_assert(c->vc == i->vc);
03641 ink_assert(c->vc == i->entry->vc);
03642 }
03643
03644 switch (event) {
03645 case VC_EVENT_ERROR:
03646
03647 tunnel.chain_abort_all(c->producer);
03648 c->handler_state = HTTP_SM_TRANSFORM_FAIL;
03649 c->vc->do_io_close(EHTTP_ERROR);
03650 break;
03651 case VC_EVENT_EOS:
03652
03653
03654
03655
03656
03657 if (c->producer->alive && c->producer->num_consumers == 1) {
03658
03659
03660
03661
03662 tunnel.producer_handler(HTTP_TUNNEL_EVENT_CONSUMER_DETACH, c->producer);
03663 }
03664
03665 case VC_EVENT_WRITE_COMPLETE:
03666
03667 c->write_success = true;
03668 c->vc->do_io_shutdown(IO_SHUTDOWN_WRITE);
03669
03670
03671
03672 if (c->self_producer == NULL) {
03673 i->entry->in_tunnel = false;
03674 } else if (c->self_producer->alive == false) {
03675
03676
03677
03678
03679 c->vc->do_io(VIO::CLOSE);
03680 }
03681 break;
03682 default:
03683 ink_release_assert(0);
03684 }
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695 if (t_state.range_setup == HttpTransact::RANGE_NONE) {
03696 switch (t_state.pre_transform_source) {
03697 case HttpTransact::SOURCE_HTTP_ORIGIN_SERVER:
03698 server_response_body_bytes = client_response_body_bytes;
03699 break;
03700 case HttpTransact::SOURCE_CACHE:
03701 cache_response_body_bytes = client_response_body_bytes;
03702 break;
03703 default:
03704 break;
03705 }
03706 }
03707
03708 return 0;
03709 }
03710
03711 int
03712 HttpSM::tunnel_handler_transform_read(int event, HttpTunnelProducer * p)
03713 {
03714 STATE_ENTER(&HttpSM::tunnel_handler_transform_read, event);
03715
03716 ink_assert(p->vc == transform_info.vc || p->vc == post_transform_info.vc);
03717
03718 switch (event) {
03719 case VC_EVENT_ERROR:
03720
03721 tunnel.chain_abort_all(p->self_consumer->producer);
03722 break;
03723 case VC_EVENT_EOS:
03724
03725
03726
03727 if (t_state.hdr_info.transform_response_cl != HTTP_UNDEFINED_CL &&
03728 p->read_vio->nbytes < t_state.hdr_info.transform_response_cl) {
03729 tunnel.abort_cache_write_finish_others(p);
03730 break;
03731 }
03732
03733 case VC_EVENT_READ_COMPLETE:
03734 case HTTP_TUNNEL_EVENT_PRECOMPLETE:
03735
03736 p->read_success = true;
03737 tunnel.local_finish_all(p);
03738 break;
03739 default:
03740 ink_release_assert(0);
03741 }
03742
03743
03744
03745
03746 if (p->self_consumer->alive == false) {
03747 p->vc->do_io_close();
03748 }
03749 p->handler_state = HTTP_SM_TRANSFORM_CLOSED;
03750
03751 return 0;
03752 }
03753
03754 int
03755 HttpSM::tunnel_handler_plugin_agent(int event, HttpTunnelConsumer * c)
03756 {
03757 STATE_ENTER(&HttpSM::tunnel_handler_plugin_client, event);
03758
03759 switch (event) {
03760 case VC_EVENT_ERROR:
03761 c->vc->do_io_close(EHTTP_ERROR);
03762
03763 if (c->producer->alive && c->producer->num_consumers == 1) {
03764 tunnel.producer_handler(HTTP_TUNNEL_EVENT_CONSUMER_DETACH, c->producer);
03765 }
03766 break;
03767 case VC_EVENT_EOS:
03768 if (c->producer->alive && c->producer->num_consumers == 1) {
03769 tunnel.producer_handler(HTTP_TUNNEL_EVENT_CONSUMER_DETACH, c->producer);
03770 }
03771
03772 case VC_EVENT_WRITE_COMPLETE:
03773 c->write_success = true;
03774 c->vc->do_io(VIO::CLOSE);
03775 break;
03776 default:
03777 ink_release_assert(0);
03778 }
03779
03780 return 0;
03781 }
03782
03783 int
03784 HttpSM::state_srv_lookup(int event, void *data)
03785 {
03786 STATE_ENTER(&HttpSM::state_srv_lookup, event);
03787
03788 ink_assert(t_state.req_flavor == HttpTransact::REQ_FLAVOR_SCHEDULED_UPDATE ||
03789 t_state.req_flavor == HttpTransact::REQ_FLAVOR_REVPROXY || ua_entry->vc != NULL);
03790
03791 switch (event) {
03792 case EVENT_SRV_LOOKUP:
03793 pending_action = NULL;
03794 process_srv_info((HostDBInfo *) data);
03795 break;
03796 case EVENT_SRV_IP_REMOVED:
03797 ink_assert(!"Unexpected SRV event from HostDB. What up, Eric?");
03798 break;
03799 default:
03800 ink_assert(!"Unexpected event");
03801 }
03802
03803 return 0;
03804 }
03805
03806 int
03807 HttpSM::state_remap_request(int event, void * )
03808 {
03809 STATE_ENTER(&HttpSM::state_remap_request, event);
03810
03811 switch (event) {
03812 case EVENT_REMAP_ERROR:
03813 {
03814 ink_assert(!"this doesn't happen");
03815 pending_action = NULL;
03816 Error("error remapping request [see previous errors]");
03817 call_transact_and_set_next_state(HttpTransact::HandleRequest);
03818 break;
03819 }
03820
03821 case EVENT_REMAP_COMPLETE:
03822 {
03823 pending_action = NULL;
03824 DebugSM("url_rewrite", "completed processor-based remapping request for [%" PRId64 "]", sm_id);
03825 t_state.url_remap_success = remapProcessor.finish_remap(&t_state);
03826 call_transact_and_set_next_state(NULL);
03827 break;
03828 }
03829
03830 default:
03831 ink_assert("Unexpected event inside state_remap_request");
03832 break;
03833 }
03834
03835 return 0;
03836 }
03837
03838 void
03839 HttpSM::do_remap_request(bool run_inline)
03840 {
03841 DebugSM("http_seq", "[HttpSM::do_remap_request] Remapping request");
03842 DebugSM("url_rewrite", "Starting a possible remapping for request [%" PRId64 "]", sm_id);
03843
03844 bool ret = false;
03845 if (t_state.cop_test_page == false) {
03846 ret = remapProcessor.setup_for_remap(&t_state);
03847 }
03848
03849
03850
03851
03852 t_state.pristine_url.create(t_state.hdr_info.client_request.url_get()->m_heap);
03853 t_state.pristine_url.copy(t_state.hdr_info.client_request.url_get());
03854
03855 if (!ret) {
03856 DebugSM("url_rewrite", "Could not find a valid remapping entry for this request [%" PRId64 "]", sm_id);
03857 if (!run_inline) {
03858 handleEvent(EVENT_REMAP_COMPLETE, NULL);
03859 }
03860 return;
03861 }
03862
03863 DebugSM("url_rewrite", "Found a remap map entry for [%" PRId64 "], attempting to remap request and call any plugins", sm_id);
03864 Action *remap_action_handle = remapProcessor.perform_remap(this, &t_state);
03865
03866 if (remap_action_handle != ACTION_RESULT_DONE) {
03867 DebugSM("url_rewrite", "Still more remapping needed for [%" PRId64 "]", sm_id);
03868 ink_assert(!pending_action);
03869 historical_action = pending_action = remap_action_handle;
03870 }
03871
03872 return;
03873 }
03874
03875 void
03876 HttpSM::do_hostdb_lookup()
03877 {
03878
03879
03880 // if a connection to the origin server //
03881 // is currently opened --- close it. //
03882
03883 if (m_origin_server_vc != 0) {
03884 origin_server_close(CLOSE_CONNECTION);
03885 if (m_response_body_tunnel_buffer_.buf() != 0)
03886 m_response_body_tunnel_buffer_.reset();
03887 }
03888 */
03889
03890 ink_assert(t_state.dns_info.lookup_name != NULL);
03891 ink_assert(pending_action == NULL);
03892
03893 milestones.dns_lookup_begin = ink_get_hrtime();
03894 bool use_srv_records = t_state.srv_lookup;
03895
03896 if (use_srv_records) {
03897 char d[MAXDNAME];
03898
03899 memcpy(d, "_http._tcp.", 11);
03900 ink_strlcpy(d + 11, t_state.server_info.name, sizeof(d) - 11 );
03901
03902 DebugSM("dns_srv", "Beginning lookup of SRV records for origin %s", d);
03903
03904 HostDBProcessor::Options opt;
03905 if (t_state.api_txn_dns_timeout_value != -1)
03906 opt.timeout = t_state.api_txn_dns_timeout_value;
03907 Action *srv_lookup_action_handle =
03908 hostDBProcessor.getSRVbyname_imm(this, (process_srv_info_pfn) & HttpSM::process_srv_info, d, 0, opt);
03909
03910 if (srv_lookup_action_handle != ACTION_RESULT_DONE) {
03911 ink_assert(!pending_action);
03912 pending_action = srv_lookup_action_handle;
03913 historical_action = pending_action;
03914 } else {
03915 char *host_name = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_hostname : t_state.dns_info.lookup_name;
03916 opt.port = t_state.dns_info.srv_lookup_success ? t_state.dns_info.srv_port : t_state.server_info.port;
03917 opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing)
03918 ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS
03919 : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD
03920 ;
03921 opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
03922 opt.host_res_style = ua_session->host_res_style;
03923
03924 Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this,
03925 (process_hostdb_info_pfn) & HttpSM::
03926 process_hostdb_info,
03927 host_name, 0,
03928 opt);
03929 if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
03930 ink_assert(!pending_action);
03931 pending_action = dns_lookup_action_handle;
03932 historical_action = pending_action;
03933 } else {
03934 call_transact_and_set_next_state(NULL);
03935 }
03936 }
03937 return;
03938 } else {
03939 DebugSM("http_seq", "[HttpSM::do_hostdb_lookup] Doing DNS Lookup");
03940
03941
03942
03943 int server_port = t_state.current.server ? t_state.current.server->port : t_state.server_info.port;
03944
03945 if (t_state.api_txn_dns_timeout_value != -1) {
03946 DebugSM("http_timeout", "beginning DNS lookup. allowing %d mseconds for DNS lookup",
03947 t_state.api_txn_dns_timeout_value);
03948 }
03949
03950 HostDBProcessor::Options opt;
03951 opt.port = server_port;
03952 opt.flags = (t_state.cache_info.directives.does_client_permit_dns_storing)
03953 ? HostDBProcessor::HOSTDB_DO_NOT_FORCE_DNS
03954 : HostDBProcessor::HOSTDB_FORCE_DNS_RELOAD
03955 ;
03956 opt.timeout = (t_state.api_txn_dns_timeout_value != -1) ? t_state.api_txn_dns_timeout_value : 0;
03957 opt.host_res_style = ua_session->host_res_style;
03958
03959 Action *dns_lookup_action_handle = hostDBProcessor.getbyname_imm(this, (process_hostdb_info_pfn) & HttpSM::process_hostdb_info, t_state.dns_info.lookup_name, 0, opt);
03960
03961 if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
03962 ink_assert(!pending_action);
03963 pending_action = dns_lookup_action_handle;
03964 historical_action = pending_action;
03965 } else {
03966 call_transact_and_set_next_state(NULL);
03967 }
03968 return;
03969 }
03970 ink_assert(!"not reached");
03971 return;
03972 }
03973
03974 void
03975 HttpSM::do_hostdb_reverse_lookup()
03976 {
03977 ink_assert(t_state.dns_info.lookup_name != NULL);
03978 ink_assert(pending_action == NULL);
03979
03980 DebugSM("http_seq", "[HttpSM::do_hostdb_reverse_lookup] Doing reverse DNS Lookup");
03981
03982 IpEndpoint addr;
03983 ats_ip_pton(t_state.dns_info.lookup_name, &addr.sa);
03984 Action *dns_lookup_action_handle = hostDBProcessor.getbyaddr_re(this, &addr.sa);
03985
03986 if (dns_lookup_action_handle != ACTION_RESULT_DONE) {
03987 ink_assert(!pending_action);
03988 pending_action = dns_lookup_action_handle;
03989 historical_action = pending_action;
03990 }
03991 return;
03992 }
03993
03994 void
03995 HttpSM::do_hostdb_update_if_necessary()
03996 {
03997 int issue_update = 0;
03998
03999 if (t_state.current.server == NULL || plugin_tunnel_type != HTTP_NO_PLUGIN_TUNNEL) {
04000
04001 return;
04002 }
04003
04004
04005 if (!ats_ip_addr_eq(&t_state.current.server->addr.sa, t_state.host_db_info.ip())) {
04006 DebugSM("http", "[%" PRId64 "] skipping hostdb update due to server failover", sm_id);
04007 return;
04008 }
04009
04010 if (t_state.updated_server_version != HostDBApplicationInfo::HTTP_VERSION_UNDEFINED) {
04011
04012
04013
04014
04015
04016
04017
04018 if (t_state.host_db_info.app.http_data.http_version != t_state.updated_server_version) {
04019 t_state.host_db_info.app.http_data.http_version = t_state.updated_server_version;
04020 issue_update |= 1;
04021 }
04022
04023 t_state.updated_server_version = HostDBApplicationInfo::HTTP_VERSION_UNDEFINED;
04024 }
04025
04026 if (t_state.current.server->had_connect_fail()) {
04027 issue_update |= 1;
04028 mark_host_failure(&t_state.host_db_info, t_state.client_request_time);
04029 } else {
04030 if (t_state.host_db_info.app.http_data.last_failure != 0) {
04031 t_state.host_db_info.app.http_data.last_failure = 0;
04032 ats_ip_port_cast(&t_state.current.server->addr) = htons(t_state.current.server->port);
04033 issue_update |= 1;
04034 char addrbuf[INET6_ADDRPORTSTRLEN];
04035 DebugSM("http", "[%" PRId64 "] hostdb update marking IP: %s as up",
04036 sm_id,
04037 ats_ip_nptop(&t_state.current.server->addr.sa, addrbuf, sizeof(addrbuf)));
04038 }
04039
04040 if (t_state.dns_info.srv_lookup_success && t_state.dns_info.srv_app.http_data.last_failure != 0) {
04041 t_state.dns_info.srv_app.http_data.last_failure = 0;
04042 hostDBProcessor.setby_srv(t_state.dns_info.lookup_name, 0, t_state.dns_info.srv_hostname, &t_state.dns_info.srv_app);
04043 DebugSM("http", "[%" PRId64 "] hostdb update marking SRV: %s as up",
04044 sm_id,
04045 t_state.dns_info.srv_hostname);
04046 }
04047 }
04048
04049 if (issue_update) {
04050 hostDBProcessor.setby(t_state.current.server->name,
04051 strlen(t_state.current.server->name),
04052 &t_state.current.server->addr.sa,
04053 &t_state.host_db_info.app
04054 );
04055 }
04056
04057 char addrbuf[INET6_ADDRPORTSTRLEN];
04058 DebugSM("http", "server info = %s", ats_ip_nptop(&t_state.current.server->addr.sa, addrbuf, sizeof(addrbuf)));
04059 return;
04060 }
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073 void
04074 HttpSM::parse_range_and_compare(MIMEField *field, int64_t content_length)
04075 {
04076 int prev_good_range = -1;
04077 const char *value;
04078 int value_len;
04079 int n_values;
04080 int nr = 0;
04081 int not_satisfy = 0;
04082 HdrCsvIter csv;
04083 const char *s, *e, *tmp;
04084 RangeRecord *ranges = NULL;
04085 int64_t start, end;
04086
04087 ink_assert(field != NULL && t_state.range_setup == HttpTransact::RANGE_NONE && t_state.ranges == NULL);
04088
04089 if (content_length <= 0)
04090 return;
04091
04092
04093 if (content_length == INT64_MAX) {
04094 t_state.range_setup = HttpTransact::RANGE_NOT_HANDLED;
04095 return;
04096 }
04097
04098 n_values = 0;
04099 value = csv.get_first(field, &value_len);
04100 while (value) {
04101 ++n_values;
04102 value = csv.get_next(&value_len);
04103 }
04104
04105 value = csv.get_first(field, &value_len);
04106 if (n_values <= 0 || ptr_len_ncmp(value, value_len, "bytes=", 6))
04107 return;
04108
04109 ranges = new RangeRecord[n_values];
04110 value += 6;
04111 value_len -= 6;
04112
04113 for (; value; value = csv.get_next(&value_len)) {
04114 if (!(tmp = (const char *) memchr(value, '-', value_len))) {
04115 t_state.range_setup = HttpTransact::RANGE_NONE;
04116 goto Lfaild;
04117 }
04118
04119
04120 s = value;
04121 e = tmp;
04122
04123 for (; s < e && ParseRules::is_ws(*s); ++s) ;
04124
04125 if (s >= e)
04126 start = -1;
04127 else {
04128 for (start = 0; s < e && *s >= '0' && *s <= '9'; ++s)
04129 start = start * 10 + (*s - '0');
04130
04131 for (; s < e && ParseRules::is_ws(*s); ++s) ;
04132
04133 if (s < e || start < 0) {
04134 t_state.range_setup = HttpTransact::RANGE_NONE;
04135 goto Lfaild;
04136 }
04137 }
04138
04139
04140 s = tmp + 1;
04141 e = value + value_len;
04142
04143 for (; s < e && ParseRules::is_ws(*s); ++s) ;
04144
04145 if (s >= e) {
04146 if (start < 0) {
04147 t_state.range_setup = HttpTransact::RANGE_NONE;
04148 goto Lfaild;
04149 } else if (start >= content_length) {
04150 not_satisfy++;
04151 continue;
04152 }
04153 end = content_length - 1;
04154 } else {
04155 for (end = 0; s < e && *s >= '0' && *s <= '9'; ++s)
04156 end = end * 10 + (*s - '0');
04157
04158 for (; s < e && ParseRules::is_ws(*s); ++s) ;
04159
04160 if (s < e || end < 0) {
04161 t_state.range_setup = HttpTransact::RANGE_NONE;
04162 goto Lfaild;
04163 }
04164
04165 if (start < 0) {
04166 if (end >= content_length)
04167 end = content_length;
04168 start = content_length - end;
04169 end = content_length - 1;
04170 } else if (start >= content_length && start <= end) {
04171 not_satisfy++;
04172 continue;
04173 }
04174
04175 if (end >= content_length)
04176 end = content_length - 1;
04177 }
04178
04179 if (start > end) {
04180 t_state.range_setup = HttpTransact::RANGE_NONE;
04181 goto Lfaild;
04182 }
04183
04184 if (prev_good_range >= 0 && start <= ranges[prev_good_range]._end) {
04185 t_state.range_setup = HttpTransact::RANGE_NOT_HANDLED;
04186 goto Lfaild;
04187 }
04188
04189 ink_assert(start >= 0 && end >= 0 && start < content_length && end < content_length);
04190
04191 prev_good_range = nr;
04192 ranges[nr]._start = start;
04193 ranges[nr]._end = end;
04194 ++nr;
04195 }
04196
04197 if (nr > 0) {
04198 t_state.range_setup = HttpTransact::RANGE_REQUESTED;
04199 t_state.ranges = ranges;
04200 t_state.num_range_fields = nr;
04201 return;
04202 }
04203
04204 if (not_satisfy)
04205 t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
04206
04207 Lfaild:
04208 t_state.num_range_fields = -1;
04209 delete []ranges;
04210 return;
04211 }
04212
04213 void
04214 HttpSM::calculate_output_cl(int64_t content_length, int64_t num_chars)
04215 {
04216 int i;
04217
04218 if (t_state.range_setup != HttpTransact::RANGE_REQUESTED &&
04219 t_state.range_setup != HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED)
04220 return;
04221
04222 ink_assert(t_state.ranges);
04223
04224 if (t_state.num_range_fields == 1) {
04225 t_state.range_output_cl = t_state.ranges[0]._end - t_state.ranges[0]._start + 1;
04226 }
04227 else {
04228 for (i = 0; i < t_state.num_range_fields; i++) {
04229 if (t_state.ranges[i]._start >= 0) {
04230 t_state.range_output_cl += boundary_size;
04231 t_state.range_output_cl += sub_header_size + content_length;
04232 t_state.range_output_cl += num_chars_for_int(t_state.ranges[i]._start)
04233 + num_chars_for_int(t_state.ranges[i]._end) + num_chars + 2;
04234 t_state.range_output_cl += t_state.ranges[i]._end - t_state.ranges[i]._start + 1;
04235 t_state.range_output_cl += 2;
04236 }
04237 }
04238
04239 t_state.range_output_cl += boundary_size + 2;
04240 }
04241
04242 Debug("http_range", "Pre-calculated Content-Length for Range response is %" PRId64, t_state.range_output_cl);
04243 }
04244
04245 void
04246 HttpSM::do_range_parse(MIMEField *range_field)
04247 {
04248
04249
04250
04251 int64_t content_length = t_state.cache_info.object_read->object_size_get();
04252 int64_t num_chars_for_cl = num_chars_for_int(content_length);
04253
04254 parse_range_and_compare(range_field, content_length);
04255 calculate_output_cl(content_length, num_chars_for_cl);
04256 }
04257
04258
04259
04260
04261 void
04262 HttpSM::do_range_setup_if_necessary()
04263 {
04264 MIMEField *field;
04265 INKVConnInternal *range_trans;
04266 int field_content_type_len = -1;
04267 const char * content_type;
04268
04269 ink_assert(t_state.cache_info.object_read != NULL);
04270
04271 field = t_state.hdr_info.client_request.field_find(MIME_FIELD_RANGE, MIME_LEN_RANGE);
04272 ink_assert(field != NULL);
04273
04274 t_state.range_setup = HttpTransact::RANGE_NONE;
04275
04276 if (t_state.method == HTTP_WKSIDX_GET && t_state.hdr_info.client_request.version_get() == HTTPVersion(1, 1)) {
04277 do_range_parse(field);
04278
04279
04280 if (t_state.range_setup == HttpTransact::RANGE_REQUESTED &&
04281 t_state.num_range_fields == 1 &&
04282 cache_sm.cache_read_vc->is_pread_capable())
04283 t_state.range_setup = HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED;
04284
04285 if (t_state.range_setup == HttpTransact::RANGE_REQUESTED &&
04286 api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK) == NULL) {
04287 Debug("http_trans", "Unable to accelerate range request, fallback to transform");
04288 content_type = t_state.cache_info.object_read->response_get()->value_get(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE, &field_content_type_len);
04289
04290 range_trans = transformProcessor.range_transform(mutex,
04291 t_state.ranges,
04292 t_state.num_range_fields,
04293 &t_state.hdr_info.transform_response,
04294 content_type,
04295 field_content_type_len,
04296 t_state.cache_info.object_read->object_size_get()
04297 );
04298 api_hooks.append(TS_HTTP_RESPONSE_TRANSFORM_HOOK, range_trans);
04299 }
04300 }
04301 }
04302
04303
04304 void
04305 HttpSM::do_cache_lookup_and_read()
04306 {
04307
04308
04309 ink_assert(pending_action == 0);
04310
04311 HTTP_INCREMENT_TRANS_STAT(http_cache_lookups_stat);
04312
04313 milestones.cache_open_read_begin = ink_get_hrtime();
04314 t_state.cache_lookup_result = HttpTransact::CACHE_LOOKUP_NONE;
04315 t_state.cache_info.lookup_count++;
04316
04317
04318
04319 URL *c_url;
04320 if (t_state.redirect_info.redirect_in_process)
04321 c_url = t_state.hdr_info.client_request.url_get();
04322 else
04323 c_url = t_state.cache_info.lookup_url;
04324
04325 DebugSM("http_seq", "[HttpSM::do_cache_lookup_and_read] [%" PRId64 "] Issuing cache lookup for URL %s", sm_id, c_url->string_get(&t_state.arena));
04326 Action *cache_action_handle = cache_sm.open_read(c_url,
04327 &t_state.hdr_info.client_request,
04328 &(t_state.cache_info.config),
04329 (time_t) ((t_state.cache_control.pin_in_cache_for < 0) ?
04330 0 : t_state.cache_control.pin_in_cache_for));
04331
04332
04333
04334
04335
04336
04337 if (cache_action_handle != ACTION_RESULT_DONE) {
04338 ink_assert(!pending_action);
04339 pending_action = cache_action_handle;
04340 historical_action = pending_action;
04341 }
04342 REMEMBER((long) pending_action, reentrancy_count);
04343
04344 return;
04345 }
04346
04347 void
04348 HttpSM::do_cache_delete_all_alts(Continuation * cont)
04349 {
04350
04351 ink_assert(t_state.cache_info.object_read);
04352
04353 DebugSM("http_seq", "[HttpSM::do_cache_delete_all_alts] Issuing cache delete for %s",
04354 t_state.cache_info.lookup_url->string_get_ref());
04355
04356 Action *cache_action_handle = NULL;
04357
04358 cache_action_handle = cacheProcessor.remove(cont, t_state.cache_info.lookup_url, t_state.cache_control.cluster_cache_local);
04359 if (cont != NULL) {
04360 if (cache_action_handle != ACTION_RESULT_DONE) {
04361 ink_assert(!pending_action);
04362 pending_action = cache_action_handle;
04363 historical_action = pending_action;
04364 }
04365 }
04366
04367 return;
04368 }
04369
04370 inline void
04371 HttpSM::do_cache_prepare_write()
04372 {
04373
04374
04375 milestones.cache_open_write_begin = ink_get_hrtime();
04376 bool retry = (t_state.api_lock_url == HttpTransact::LOCK_URL_FIRST);
04377 do_cache_prepare_action(&cache_sm, t_state.cache_info.object_read, retry);
04378 }
04379
04380 inline void
04381 HttpSM::do_cache_prepare_write_transform()
04382 {
04383 if (cache_sm.cache_write_vc != NULL || tunnel.has_cache_writer())
04384 do_cache_prepare_action(&transform_cache_sm, NULL, false, true);
04385 else
04386 do_cache_prepare_action(&transform_cache_sm, NULL, false);
04387 }
04388
04389 void
04390 HttpSM::do_cache_prepare_update()
04391 {
04392 if (t_state.cache_info.object_read != NULL &&
04393 t_state.cache_info.object_read->valid() &&
04394 t_state.cache_info.object_store.valid() &&
04395 t_state.cache_info.object_store.response_get() != NULL &&
04396 t_state.cache_info.object_store.response_get()->valid() && t_state.hdr_info.client_request.method_get_wksidx()
04397 == HTTP_WKSIDX_GET) {
04398 t_state.cache_info.object_store.request_set(t_state.cache_info.object_read->request_get());
04399
04400
04401
04402 t_state.transact_return_point = HttpTransact::HandleUpdateCachedObject;
04403 ink_assert(cache_sm.cache_write_vc == NULL);
04404 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_cache_open_write);
04405
04406 do_cache_prepare_action(&cache_sm, t_state.cache_info.object_read, false);
04407 } else {
04408 t_state.api_modifiable_cached_resp = false;
04409 call_transact_and_set_next_state(HttpTransact::HandleApiErrorJump);
04410 }
04411 }
04412
04413 void
04414 HttpSM::do_cache_prepare_action(HttpCacheSM * c_sm, CacheHTTPInfo * object_read_info, bool retry, bool allow_multiple)
04415 {
04416 URL *o_url, *c_url, *s_url;
04417 bool restore_client_request = false;
04418
04419 ink_assert(!pending_action);
04420 ink_assert(c_sm->cache_write_vc == NULL);
04421
04422 if (t_state.api_lock_url == HttpTransact::LOCK_URL_FIRST) {
04423 if (t_state.redirect_info.redirect_in_process) {
04424 o_url = &(t_state.redirect_info.original_url);
04425 ink_assert(o_url->valid());
04426 restore_client_request = true;
04427 s_url = o_url;
04428 } else {
04429 o_url = &(t_state.cache_info.original_url);
04430 if (o_url->valid())
04431 s_url = o_url;
04432 else
04433 s_url = t_state.cache_info.lookup_url;
04434 }
04435 } else if (t_state.api_lock_url == HttpTransact::LOCK_URL_SECOND) {
04436 s_url = &t_state.cache_info.lookup_url_storage;
04437 } else {
04438 ink_assert(t_state.api_lock_url == HttpTransact::LOCK_URL_ORIGINAL);
04439 s_url = &(t_state.cache_info.original_url);
04440 restore_client_request = true;
04441 }
04442
04443
04444
04445 if (restore_client_request) {
04446 c_url = t_state.hdr_info.client_request.url_get();
04447 s_url->copy(c_url);
04448 }
04449
04450 ink_assert(s_url != NULL && s_url->valid());
04451 DebugSM("http_cache_write", "[%" PRId64 "] writing to cache with URL %s", sm_id, s_url->string_get(&t_state.arena));
04452 Action *cache_action_handle = c_sm->open_write(s_url, &t_state.hdr_info.client_request,
04453 object_read_info,
04454 (time_t) ((t_state.cache_control.pin_in_cache_for < 0) ?
04455 0 : t_state.cache_control.pin_in_cache_for),
04456 retry, allow_multiple);
04457
04458 if (cache_action_handle != ACTION_RESULT_DONE) {
04459 ink_assert(!pending_action);
04460 pending_action = cache_action_handle;
04461 historical_action = pending_action;
04462 }
04463 }
04464
04465
04466
04467
04468
04469
04470 void
04471 HttpSM::do_http_server_open(bool raw)
04472 {
04473 int ip_family = t_state.current.server->addr.sa.sa_family;
04474 DebugSM("http_track", "entered inside do_http_server_open ][%s]", ats_ip_family_name(ip_family));
04475
04476 ink_assert(server_entry == NULL);
04477
04478
04479
04480
04481 ink_assert(ua_entry != NULL ||
04482 t_state.req_flavor == HttpTransact::REQ_FLAVOR_SCHEDULED_UPDATE ||
04483 t_state.req_flavor == HttpTransact::REQ_FLAVOR_REVPROXY);
04484
04485 ink_assert(pending_action == NULL);
04486
04487 if (false == t_state.api_server_addr_set) {
04488 ink_assert(t_state.current.server->port > 0);
04489 t_state.current.server->addr.port() = htons(t_state.current.server->port);
04490 } else {
04491 ink_assert(ats_ip_port_cast(&t_state.current.server->addr) != 0);
04492 }
04493
04494 char addrbuf[INET6_ADDRPORTSTRLEN];
04495 DebugSM("http", "[%" PRId64 "] open connection to %s: %s",
04496 sm_id, t_state.current.server->name,
04497 ats_ip_nptop(&t_state.current.server->addr.sa, addrbuf, sizeof(addrbuf)));
04498
04499 if (plugin_tunnel) {
04500 PluginVCCore *t = plugin_tunnel;
04501 plugin_tunnel = NULL;
04502 Action *pvc_action_handle = t->connect_re(this);
04503
04504
04505 ink_release_assert(pvc_action_handle == ACTION_RESULT_DONE);
04506 return;
04507 }
04508
04509 DebugSM("http_seq", "[HttpSM::do_http_server_open] Sending request to server");
04510
04511 milestones.server_connect = ink_get_hrtime();
04512 if (milestones.server_first_connect == 0) {
04513 milestones.server_first_connect = milestones.server_connect;
04514 }
04515
04516 if (t_state.pCongestionEntry != NULL) {
04517 if (t_state.pCongestionEntry->F_congested() && (!t_state.pCongestionEntry->proxy_retry(milestones.server_connect))) {
04518 t_state.congestion_congested_or_failed = 1;
04519 t_state.pCongestionEntry->stat_inc_F();
04520 CONGEST_INCREMENT_DYN_STAT(congested_on_F_stat);
04521 handleEvent(CONGESTION_EVENT_CONGESTED_ON_F, NULL);
04522 return;
04523 } else if (t_state.pCongestionEntry->M_congested(ink_hrtime_to_sec(milestones.server_connect))) {
04524 t_state.pCongestionEntry->stat_inc_M();
04525 t_state.congestion_congested_or_failed = 1;
04526 CONGEST_INCREMENT_DYN_STAT(congested_on_M_stat);
04527 handleEvent(CONGESTION_EVENT_CONGESTED_ON_M, NULL);
04528 return;
04529 }
04530 }
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542 if (raw == false && TS_SERVER_SESSION_SHARING_MATCH_NONE != t_state.txn_conf->server_session_sharing_match &&
04543 (t_state.txn_conf->keep_alive_post_out == 1 || t_state.hdr_info.request_content_length == 0) &&
04544 !is_private() && ua_session != NULL) {
04545 HSMresult_t shared_result;
04546 shared_result = httpSessionManager.acquire_session(this,
04547 &t_state.current.server->addr.sa,
04548 t_state.current.server->name,
04549 ua_session,
04550 this
04551 );
04552
04553 switch (shared_result) {
04554 case HSM_DONE:
04555 hsm_release_assert(server_session != NULL);
04556 handle_http_server_open();
04557 return;
04558 case HSM_NOT_FOUND:
04559 hsm_release_assert(server_session == NULL);
04560 break;
04561 case HSM_RETRY:
04562
04563
04564 break;
04565 default:
04566 hsm_release_assert(0);
04567 }
04568 }
04569
04570
04571
04572 else if ((TS_SERVER_SESSION_SHARING_MATCH_NONE == t_state.txn_conf->server_session_sharing_match || is_private()) &&
04573 (ua_session != NULL)) {
04574 HttpServerSession *existing_ss = ua_session->get_server_session();
04575
04576 if (existing_ss) {
04577
04578
04579
04580
04581 if (ats_ip_addr_port_eq(&existing_ss->server_ip.sa, &t_state.current.server->addr.sa)) {
04582 ua_session->attach_server_session(NULL);
04583 existing_ss->state = HSS_ACTIVE;
04584 this->attach_server_session(existing_ss);
04585 hsm_release_assert(server_session != NULL);
04586 handle_http_server_open();
04587 return;
04588 } else {
04589
04590
04591 existing_ss->release();
04592 ua_session->attach_server_session(NULL);
04593 }
04594 }
04595 }
04596
04597
04598
04599 else if (ua_session != NULL) {
04600 HttpServerSession *existing_ss = ua_session->get_server_session();
04601 if (existing_ss) {
04602 existing_ss->release();
04603 ua_session->attach_server_session(NULL);
04604 }
04605 }
04606
04607
04608
04609 if (t_state.http_config_param->server_max_connections > 0) {
04610 int64_t sum;
04611
04612 HTTP_READ_GLOBAL_DYN_SUM(http_current_server_connections_stat, sum);
04613
04614
04615
04616
04617
04618 if (sum >= t_state.http_config_param->server_max_connections) {
04619 ink_assert(pending_action == NULL);
04620 pending_action = eventProcessor.schedule_in(this, HRTIME_MSECONDS(100));
04621 httpSessionManager.purge_keepalives();
04622 return;
04623 }
04624 }
04625
04626
04627 if (t_state.txn_conf->origin_max_connections > 0) {
04628 ConnectionCount *connections = ConnectionCount::getInstance();
04629
04630 char addrbuf[INET6_ADDRSTRLEN];
04631 if (connections->getCount((t_state.current.server->addr)) >= t_state.txn_conf->origin_max_connections) {
04632 DebugSM("http", "[%" PRId64 "] over the number of connection for this host: %s", sm_id,
04633 ats_ip_ntop(&t_state.current.server->addr.sa, addrbuf, sizeof(addrbuf)));
04634 ink_assert(pending_action == NULL);
04635 pending_action = eventProcessor.schedule_in(this, HRTIME_MSECONDS(100));
04636 return;
04637 }
04638 }
04639
04640
04641
04642 Action *connect_action_handle;
04643
04644 NetVCOptions opt;
04645 opt.f_blocking_connect = false;
04646 opt.set_sock_param(t_state.txn_conf->sock_recv_buffer_size_out,
04647 t_state.txn_conf->sock_send_buffer_size_out,
04648 t_state.txn_conf->sock_option_flag_out,
04649 t_state.txn_conf->sock_packet_mark_out,
04650 t_state.txn_conf->sock_packet_tos_out);
04651
04652 opt.ip_family = ip_family;
04653
04654 if (ua_session) {
04655 opt.local_port = ua_session->outbound_port;
04656
04657 IpAddr& outbound_ip = AF_INET6 == ip_family ? ua_session->outbound_ip6 : ua_session->outbound_ip4;
04658 if (outbound_ip.isValid()) {
04659 opt.addr_binding = NetVCOptions::INTF_ADDR;
04660 opt.local_ip = outbound_ip;
04661 } else if (ua_session->f_outbound_transparent) {
04662 opt.addr_binding = NetVCOptions::FOREIGN_ADDR;
04663 opt.local_ip = t_state.client_info.addr;
04664
04665
04666
04667
04668
04669
04670 NetVConnection *client_vc = ua_session->get_netvc();
04671 if (t_state.http_config_param->use_client_source_port && NULL != client_vc) {
04672 opt.local_port = client_vc->get_remote_port();
04673 }
04674 }
04675 }
04676
04677 int scheme_to_use = t_state.scheme;
04678
04679 if (!t_state.is_websocket) {
04680 int new_scheme_to_use = t_state.hdr_info.server_request.url_get()->scheme_get_wksidx();
04681
04682 if (new_scheme_to_use < 0) {
04683 new_scheme_to_use = t_state.hdr_info.client_request.url_get()->scheme_get_wksidx();
04684 }
04685 if (new_scheme_to_use >= 0) {
04686 scheme_to_use = new_scheme_to_use;
04687 }
04688 }
04689
04690 if (scheme_to_use == URL_WKSIDX_HTTPS) {
04691 DebugSM("http", "calling sslNetProcessor.connect_re");
04692 int len = 0;
04693 const char * host = t_state.hdr_info.server_request.host_get(&len);
04694 opt.set_sni_servername(host, len);
04695 connect_action_handle = sslNetProcessor.connect_re(this,
04696 &t_state.current.server->addr.sa,
04697 &opt);
04698 } else {
04699 if (t_state.method != HTTP_WKSIDX_CONNECT) {
04700 DebugSM("http", "calling netProcessor.connect_re");
04701 connect_action_handle = netProcessor.connect_re(this,
04702 &t_state.current.server->addr.sa,
04703 &opt);
04704 } else {
04705
04706
04707
04708
04709 MgmtInt connect_timeout;
04710 if (t_state.method == HTTP_WKSIDX_POST || t_state.method == HTTP_WKSIDX_PUT) {
04711 connect_timeout = t_state.txn_conf->post_connect_attempts_timeout;
04712 } else if (t_state.current.server == &t_state.parent_info) {
04713 connect_timeout = t_state.http_config_param->parent_connect_timeout;
04714 } else {
04715 if (t_state.pCongestionEntry != NULL)
04716 connect_timeout = t_state.pCongestionEntry->connect_timeout();
04717 else
04718 connect_timeout = t_state.txn_conf->connect_attempts_timeout;
04719 }
04720 DebugSM("http", "calling netProcessor.connect_s");
04721 connect_action_handle = netProcessor.connect_s(this,
04722 &t_state.current.server->addr.sa,
04723 connect_timeout, &opt);
04724 }
04725 }
04726
04727 if (connect_action_handle != ACTION_RESULT_DONE) {
04728 ink_assert(!pending_action);
04729 pending_action = connect_action_handle;
04730 historical_action = pending_action;
04731 }
04732
04733 return;
04734 }
04735
04736
04737 void
04738 HttpSM::do_icp_lookup()
04739 {
04740 ink_assert(pending_action == NULL);
04741
04742 URL *o_url = &t_state.cache_info.original_url;
04743
04744 Action *icp_lookup_action_handle = icpProcessor.ICPQuery(this,
04745 o_url->valid()? o_url : t_state.cache_info.lookup_url);
04746
04747 if (icp_lookup_action_handle != ACTION_RESULT_DONE) {
04748 ink_assert(!pending_action);
04749 pending_action = icp_lookup_action_handle;
04750 historical_action = pending_action;
04751 }
04752
04753 return;
04754 }
04755
04756 void
04757 HttpSM::do_api_callout_internal()
04758 {
04759 if (t_state.backdoor_request) {
04760 handle_api_return();
04761 return;
04762 }
04763
04764 switch (t_state.api_next_action) {
04765 case HttpTransact::SM_ACTION_API_SM_START:
04766 cur_hook_id = TS_HTTP_TXN_START_HOOK;
04767 break;
04768 case HttpTransact::SM_ACTION_API_PRE_REMAP:
04769 cur_hook_id = TS_HTTP_PRE_REMAP_HOOK;
04770 break;
04771 case HttpTransact::SM_ACTION_API_POST_REMAP:
04772 cur_hook_id = TS_HTTP_POST_REMAP_HOOK;
04773 break;
04774 case HttpTransact::SM_ACTION_API_READ_REQUEST_HDR:
04775 cur_hook_id = TS_HTTP_READ_REQUEST_HDR_HOOK;
04776 break;
04777 case HttpTransact::SM_ACTION_API_OS_DNS:
04778 cur_hook_id = TS_HTTP_OS_DNS_HOOK;
04779 break;
04780 case HttpTransact::SM_ACTION_API_SEND_REQUEST_HDR:
04781 cur_hook_id = TS_HTTP_SEND_REQUEST_HDR_HOOK;
04782 break;
04783 case HttpTransact::SM_ACTION_API_READ_CACHE_HDR:
04784 cur_hook_id = TS_HTTP_READ_CACHE_HDR_HOOK;
04785 break;
04786 case HttpTransact::SM_ACTION_API_CACHE_LOOKUP_COMPLETE:
04787 cur_hook_id = TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK;
04788 break;
04789 case HttpTransact::SM_ACTION_API_READ_RESPONSE_HDR:
04790 cur_hook_id = TS_HTTP_READ_RESPONSE_HDR_HOOK;
04791 break;
04792 case HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR:
04793 cur_hook_id = TS_HTTP_SEND_RESPONSE_HDR_HOOK;
04794 milestones.ua_begin_write = ink_get_hrtime();
04795 break;
04796 case HttpTransact::SM_ACTION_API_SM_SHUTDOWN:
04797 if (callout_state == HTTP_API_IN_CALLOUT || callout_state == HTTP_API_DEFERED_SERVER_ERROR) {
04798 callout_state = HTTP_API_DEFERED_CLOSE;
04799 return;
04800 } else {
04801 cur_hook_id = TS_HTTP_TXN_CLOSE_HOOK;
04802 }
04803
04804 break;
04805 default:
04806 cur_hook_id = (TSHttpHookID) - 1;
04807 ink_assert(!"not reached");
04808 }
04809
04810 cur_hook = NULL;
04811 cur_hooks = 0;
04812 state_api_callout(0, NULL);
04813 }
04814
04815 VConnection *
04816 HttpSM::do_post_transform_open()
04817 {
04818 ink_assert(post_transform_info.vc == NULL);
04819
04820 if (is_action_tag_set("http_post_nullt")) {
04821 txn_hook_prepend(TS_HTTP_REQUEST_TRANSFORM_HOOK, transformProcessor.null_transform(mutex));
04822 }
04823
04824 post_transform_info.vc = transformProcessor.open(this, api_hooks.get(TS_HTTP_REQUEST_TRANSFORM_HOOK));
04825 if (post_transform_info.vc) {
04826
04827 post_transform_info.entry = vc_table.new_entry();
04828 post_transform_info.entry->vc = post_transform_info.vc;
04829 post_transform_info.entry->vc_type = HTTP_TRANSFORM_VC;
04830 }
04831
04832 return post_transform_info.vc;
04833 }
04834
04835 VConnection *
04836 HttpSM::do_transform_open()
04837 {
04838 ink_assert(transform_info.vc == NULL);
04839 APIHook *hooks;
04840
04841 if (is_action_tag_set("http_nullt")) {
04842 txn_hook_prepend(TS_HTTP_RESPONSE_TRANSFORM_HOOK, transformProcessor.null_transform(mutex));
04843 }
04844
04845 hooks = api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK);
04846 if (hooks) {
04847 transform_info.vc = transformProcessor.open(this, hooks);
04848
04849
04850 transform_info.entry = vc_table.new_entry();
04851 transform_info.entry->vc = transform_info.vc;
04852 transform_info.entry->vc_type = HTTP_TRANSFORM_VC;
04853 } else {
04854 transform_info.vc = NULL;
04855 }
04856
04857 return transform_info.vc;
04858 }
04859
04860 void
04861 HttpSM::mark_host_failure(HostDBInfo * info, time_t time_down)
04862 {
04863 char addrbuf[INET6_ADDRPORTSTRLEN];
04864
04865 if (info->app.http_data.last_failure == 0) {
04866 char *url_str = t_state.hdr_info.client_request.url_string_get(&t_state.arena, 0);
04867 Log::error("CONNECT: could not connect to %s "
04868 "for '%s' (setting last failure time)",
04869 ats_ip_ntop(&t_state.current.server->addr.sa, addrbuf, sizeof(addrbuf)),
04870 url_str ? url_str : "<none>"
04871 );
04872 if (url_str)
04873 t_state.arena.str_free(url_str);
04874 }
04875
04876 info->app.http_data.last_failure = time_down;
04877
04878
04879 #ifdef DEBUG
04880 ink_assert(ink_cluster_time() + t_state.txn_conf->down_server_timeout > time_down);
04881 #endif
04882
04883 DebugSM("http", "[%" PRId64 "] hostdb update marking IP: %s as down",
04884 sm_id,
04885 ats_ip_nptop(&t_state.current.server->addr.sa, addrbuf, sizeof(addrbuf)));
04886 }
04887
04888 void
04889 HttpSM::set_ua_abort(HttpTransact::AbortState_t ua_abort, int event)
04890 {
04891 t_state.client_info.abort = ua_abort;
04892
04893 switch (ua_abort) {
04894 case HttpTransact::ABORTED:
04895 case HttpTransact::MAYBE_ABORTED:
04896 t_state.squid_codes.log_code = SQUID_LOG_ERR_CLIENT_ABORT;
04897 break;
04898 default:
04899
04900
04901 break;
04902 }
04903
04904
04905
04906 switch (event) {
04907 case VC_EVENT_ACTIVE_TIMEOUT:
04908 t_state.client_info.state = HttpTransact::ACTIVE_TIMEOUT;
04909 break;
04910 case VC_EVENT_INACTIVITY_TIMEOUT:
04911 t_state.client_info.state = HttpTransact::INACTIVE_TIMEOUT;
04912 break;
04913 case VC_EVENT_ERROR:
04914 t_state.client_info.state = HttpTransact::CONNECTION_ERROR;
04915 break;
04916 }
04917 }
04918
04919 void
04920 HttpSM::mark_server_down_on_client_abort()
04921 {
04922
04923
04924
04925
04926
04927
04928
04929
04930
04931
04932
04933
04934
04935 if (t_state.current.request_to == HttpTransact::ORIGIN_SERVER && t_state.hdr_info.request_content_length == 0) {
04936 if (milestones.server_first_connect != 0 && milestones.server_first_read == 0) {
04937
04938
04939 ink_hrtime wait = ink_get_hrtime() - milestones.server_first_connect;
04940 if (wait < 0) {
04941 wait = 0;
04942 }
04943 if (ink_hrtime_to_sec(wait) > t_state.txn_conf->client_abort_threshold) {
04944 t_state.current.server->set_connect_fail(ETIMEDOUT);
04945 do_hostdb_update_if_necessary();
04946 }
04947 }
04948 }
04949 }
04950
04951
04952
04953
04954
04955
04956
04957 void
04958 HttpSM::release_server_session(bool serve_from_cache)
04959 {
04960 if (server_session == NULL) {
04961 return;
04962 }
04963
04964 if (TS_SERVER_SESSION_SHARING_MATCH_NONE != t_state.txn_conf->server_session_sharing_match &&
04965 t_state.current.server->keep_alive == HTTP_KEEPALIVE &&
04966 t_state.hdr_info.server_response.valid() &&
04967 (t_state.hdr_info.server_response.status_get() == HTTP_STATUS_NOT_MODIFIED ||
04968 (t_state.hdr_info.server_request.method_get_wksidx() == HTTP_WKSIDX_HEAD
04969 && t_state.www_auth_content != HttpTransact::CACHE_AUTH_NONE)) &&
04970 plugin_tunnel_type == HTTP_NO_PLUGIN_TUNNEL) {
04971 HTTP_DECREMENT_DYN_STAT(http_current_server_transactions_stat);
04972 server_session->server_trans_stat--;
04973 server_session->attach_hostname(t_state.current.server->name);
04974 if (t_state.www_auth_content == HttpTransact::CACHE_AUTH_NONE || serve_from_cache == false) {
04975 server_session->release();
04976 } else {
04977
04978
04979 t_state.www_auth_content = HttpTransact::CACHE_AUTH_SERVE;
04980 ua_session->attach_server_session(server_session, false);
04981 }
04982 } else {
04983 server_session->do_io_close();
04984 }
04985
04986 ink_assert(server_entry->vc == server_session);
04987 server_entry->in_tunnel = true;
04988 vc_table.cleanup_entry(server_entry);
04989 server_entry = NULL;
04990 server_session = NULL;
04991 }
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001
05002 void
05003 HttpSM::handle_post_failure()
05004 {
05005 STATE_ENTER(&HttpSM::handle_post_failure, VC_EVENT_NONE);
05006
05007 ink_assert(ua_entry->vc == ua_session);
05008 ink_assert(server_entry->eos == true);
05009
05010
05011
05012
05013
05014
05015 if (false == t_state.redirect_info.redirect_in_process) {
05016 ua_entry->read_vio = ua_session->do_io_read(this, 0, NULL);
05017 }
05018 ua_entry->in_tunnel = false;
05019 server_entry->in_tunnel = false;
05020
05021
05022
05023 enable_redirection = false;
05024 tunnel.deallocate_redirect_postdata_buffers();
05025
05026
05027 t_state.client_info.keep_alive = HTTP_NO_KEEPALIVE;
05028 t_state.current.server->keep_alive = HTTP_NO_KEEPALIVE;
05029
05030 if (server_buffer_reader->read_avail() > 0) {
05031 tunnel.reset();
05032
05033 setup_server_read_response_header();
05034 } else {
05035 tunnel.deallocate_buffers();
05036 tunnel.reset();
05037
05038 vc_table.cleanup_entry(server_entry);
05039 server_entry = NULL;
05040 server_session = NULL;
05041 t_state.current.state = HttpTransact::CONNECTION_CLOSED;
05042 call_transact_and_set_next_state(HttpTransact::HandleResponse);
05043 }
05044 }
05045
05046
05047
05048
05049
05050
05051
05052 void
05053 HttpSM::handle_http_server_open()
05054 {
05055
05056
05057
05058
05059 if (NULL != server_session) {
05060 NetVConnection *vc = server_session->get_netvc();
05061 if (vc != NULL &&
05062 (vc->options.sockopt_flags != t_state.txn_conf->sock_option_flag_out ||
05063 vc->options.packet_mark != t_state.txn_conf->sock_packet_mark_out ||
05064 vc->options.packet_tos != t_state.txn_conf->sock_packet_tos_out )) {
05065 vc->options.sockopt_flags = t_state.txn_conf->sock_option_flag_out;
05066 vc->options.packet_mark = t_state.txn_conf->sock_packet_mark_out;
05067 vc->options.packet_tos = t_state.txn_conf->sock_packet_tos_out;
05068 vc->apply_options();
05069 }
05070 }
05071
05072 if (t_state.pCongestionEntry != NULL) {
05073 if (t_state.congestion_connection_opened == 0) {
05074 t_state.congestion_connection_opened = 1;
05075 t_state.pCongestionEntry->connection_opened();
05076 }
05077 }
05078
05079 int method = t_state.hdr_info.server_request.method_get_wksidx();
05080 if (method != HTTP_WKSIDX_TRACE &&
05081 (t_state.hdr_info.request_content_length > 0 || t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING) &&
05082 do_post_transform_open()) {
05083 do_setup_post_tunnel(HTTP_TRANSFORM_VC);
05084 } else {
05085 setup_server_send_request_api();
05086 }
05087 }
05088
05089
05090
05091
05092
05093
05094
05095
05096
05097 void
05098 HttpSM::handle_server_setup_error(int event, void *data)
05099 {
05100 VIO *vio = (VIO *) data;
05101 ink_assert(vio != NULL);
05102
05103 STATE_ENTER(&HttpSM::handle_server_setup_error, event);
05104
05105
05106
05107
05108 if (tunnel.is_tunnel_active()) {
05109 ink_assert(server_entry->read_vio == data);
05110 DebugSM("http", "[%" PRId64 "] [handle_server_setup_error] "
05111 "forwarding event %s to post tunnel", sm_id, HttpDebugNames::get_event_name(event));
05112 HttpTunnelConsumer *c = tunnel.get_consumer(server_entry->vc);
05113
05114
05115
05116
05117 if (c == NULL && post_transform_info.vc) {
05118 c = tunnel.get_consumer(post_transform_info.vc);
05119
05120
05121 HttpTunnelProducer *ua_producer = c->producer;
05122 ink_assert(ua_entry->vc == ua_producer->vc);
05123
05124 ua_entry->vc_handler = &HttpSM::state_watch_for_client_abort;
05125 ua_entry->read_vio = ua_producer->vc->do_io_read(this, INT64_MAX, c->producer->read_buffer);
05126 ua_producer->vc->do_io_shutdown(IO_SHUTDOWN_READ);
05127
05128 ua_producer->alive = false;
05129 ua_producer->handler_state = HTTP_SM_POST_SERVER_FAIL;
05130 tunnel.handleEvent(VC_EVENT_ERROR, c->write_vio);
05131 } else {
05132 tunnel.handleEvent(event, c->write_vio);
05133 }
05134 return;
05135 } else {
05136 if (post_transform_info.vc) {
05137 HttpTunnelConsumer *c = tunnel.get_consumer(post_transform_info.vc);
05138 if (c && c->handler_state == HTTP_SM_TRANSFORM_OPEN) {
05139 vc_table.cleanup_entry(post_transform_info.entry);
05140 post_transform_info.entry = NULL;
05141 tunnel.deallocate_buffers();
05142 tunnel.reset();
05143 }
05144 }
05145 }
05146
05147 if (event == VC_EVENT_ERROR) {
05148 t_state.cause_of_death_errno = server_session->get_netvc()->lerrno;
05149 }
05150
05151 switch (event) {
05152 case VC_EVENT_EOS:
05153 t_state.current.state = HttpTransact::CONNECTION_CLOSED;
05154 break;
05155 case VC_EVENT_ERROR:
05156 t_state.current.state = HttpTransact::CONNECTION_ERROR;
05157 break;
05158 case VC_EVENT_ACTIVE_TIMEOUT:
05159 t_state.current.state = HttpTransact::ACTIVE_TIMEOUT;
05160 break;
05161
05162 case VC_EVENT_INACTIVITY_TIMEOUT:
05163
05164
05165
05166
05167
05168
05169 if (server_entry->write_vio->nbytes > 0 && server_entry->write_vio->ndone == 0) {
05170 t_state.current.state = HttpTransact::CONNECTION_ERROR;
05171 } else {
05172 t_state.current.state = HttpTransact::INACTIVE_TIMEOUT;
05173 }
05174 break;
05175 default:
05176 ink_release_assert(0);
05177 }
05178
05179
05180 ink_assert(server_entry->in_tunnel == false);
05181 vc_table.cleanup_entry(server_entry);
05182 server_entry = NULL;
05183 server_session = NULL;
05184
05185
05186
05187
05188 switch (callout_state) {
05189 case HTTP_API_NO_CALLOUT:
05190
05191 break;
05192 case HTTP_API_IN_CALLOUT:
05193 case HTTP_API_DEFERED_SERVER_ERROR:
05194
05195
05196 callout_state = HTTP_API_DEFERED_SERVER_ERROR;
05197 return;
05198 case HTTP_API_DEFERED_CLOSE:
05199
05200
05201
05202
05203
05204 return;
05205 default:
05206 ink_release_assert(0);
05207 }
05208
05209 call_transact_and_set_next_state(HttpTransact::HandleResponse);
05210 }
05211
05212 void
05213 HttpSM::setup_transform_to_server_transfer()
05214 {
05215 ink_assert(post_transform_info.vc != NULL);
05216 ink_assert(post_transform_info.entry->vc == post_transform_info.vc);
05217
05218 int64_t nbytes = t_state.hdr_info.transform_request_cl;
05219 int64_t alloc_index = buffer_size_to_index(nbytes);
05220 MIOBuffer *post_buffer = new_MIOBuffer(alloc_index);
05221 IOBufferReader *buf_start = post_buffer->alloc_reader();
05222
05223 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler_post);
05224
05225 HttpTunnelConsumer *c = tunnel.get_consumer(post_transform_info.vc);
05226
05227 HttpTunnelProducer *p = tunnel.add_producer(post_transform_info.vc,
05228 nbytes,
05229 buf_start,
05230 &HttpSM::tunnel_handler_transform_read,
05231 HT_TRANSFORM,
05232 "post transform");
05233 tunnel.chain(c,p);
05234 post_transform_info.entry->in_tunnel = true;
05235
05236 tunnel.add_consumer(server_entry->vc,
05237 post_transform_info.vc, &HttpSM::tunnel_handler_post_server, HT_HTTP_SERVER, "http server post");
05238 server_entry->in_tunnel = true;
05239
05240 tunnel.tunnel_run(p);
05241 }
05242
05243 #ifdef PROXY_DRAIN
05244 void
05245 HttpSM::do_drain_request_body()
05246 {
05247 int64_t post_bytes = t_state.hdr_info.request_content_length;
05248 int64_t avail = ua_buffer_reader->read_avail();
05249
05250 int64_t act_on = (avail < post_bytes) ? avail : post_bytes;
05251
05252 client_request_body_bytes = act_on;
05253 ua_buffer_reader->consume(act_on);
05254
05255 ink_assert(client_request_body_bytes <= post_bytes);
05256
05257 if (client_request_body_bytes < post_bytes) {
05258 ua_buffer_reader->mbuf->size_index = buffer_size_to_index(t_state.hdr_info.request_content_length);
05259 ua_entry->vc_handler = &HttpSM::state_drain_client_request_body;
05260 ua_entry->read_vio = ua_entry->vc->do_io_read(this, post_bytes - client_request_body_bytes, ua_buffer_reader->mbuf);
05261 } else {
05262 call_transact_and_set_next_state(NULL);
05263 }
05264 }
05265 #endif
05266
05267 void
05268 HttpSM::do_setup_post_tunnel(HttpVC_t to_vc_type)
05269 {
05270 bool chunked = (t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING);
05271 bool post_redirect = false;
05272
05273 HttpTunnelProducer *p = NULL;
05274
05275
05276
05277 if (t_state.redirect_info.redirect_in_process && enable_redirection &&
05278 (tunnel.postbuf && tunnel.postbuf->postdata_copy_buffer_start != NULL &&
05279 tunnel.postbuf->postdata_producer_buffer != NULL)) {
05280 post_redirect = true;
05281
05282 tunnel.postbuf->postdata_producer_buffer->write(tunnel.postbuf->postdata_copy_buffer_start);
05283 int64_t post_bytes = tunnel.postbuf->postdata_producer_reader->read_avail();
05284 transfered_bytes = post_bytes;
05285 p = tunnel.add_producer(HTTP_TUNNEL_STATIC_PRODUCER,
05286 post_bytes,
05287 tunnel.postbuf->postdata_producer_reader,
05288 (HttpProducerHandler) NULL, HT_STATIC, "redirect static agent post");
05289
05290 tunnel.postbuf->postdata_producer_buffer = NULL;
05291 tunnel.postbuf->postdata_producer_reader = NULL;
05292 } else {
05293 int64_t alloc_index;
05294
05295 if (t_state.hdr_info.request_content_length == HTTP_UNDEFINED_CL) {
05296 alloc_index = (int) t_state.txn_conf->default_buffer_size_index;
05297 if (alloc_index<MIN_CONFIG_BUFFER_SIZE_INDEX || alloc_index> MAX_BUFFER_SIZE_INDEX) {
05298 alloc_index = DEFAULT_REQUEST_BUFFER_SIZE_INDEX;
05299 }
05300 } else {
05301 alloc_index = buffer_size_to_index(t_state.hdr_info.request_content_length);
05302 }
05303 MIOBuffer *post_buffer = new_MIOBuffer(alloc_index);
05304 IOBufferReader *buf_start = post_buffer->alloc_reader();
05305 int64_t post_bytes = chunked ? INT64_MAX : t_state.hdr_info.request_content_length;
05306
05307 t_state.hdr_info.request_body_start = true;
05308
05309
05310
05311
05312
05313
05314
05315
05316 client_request_body_bytes = post_buffer->write(ua_buffer_reader, chunked ? ua_buffer_reader->read_avail() : post_bytes);
05317 ua_buffer_reader->consume(client_request_body_bytes);
05318 p = tunnel.add_producer(ua_entry->vc, post_bytes - transfered_bytes, buf_start,
05319 &HttpSM::tunnel_handler_post_ua, HT_HTTP_CLIENT, "user agent post");
05320 }
05321 ua_entry->in_tunnel = true;
05322
05323 switch (to_vc_type) {
05324 case HTTP_TRANSFORM_VC:
05325 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_request_wait_for_transform_read);
05326 ink_assert(post_transform_info.entry != NULL);
05327 ink_assert(post_transform_info.entry->vc == post_transform_info.vc);
05328 tunnel.add_consumer(post_transform_info.entry->vc,
05329 ua_entry->vc, &HttpSM::tunnel_handler_transform_write, HT_TRANSFORM, "post transform");
05330 post_transform_info.entry->in_tunnel = true;
05331 break;
05332 case HTTP_SERVER_VC:
05333
05334
05335
05336 if (post_redirect) {
05337 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler_for_partial_post);
05338 tunnel.add_consumer(server_entry->vc,
05339 HTTP_TUNNEL_STATIC_PRODUCER,
05340 &HttpSM::tunnel_handler_post_server, HT_HTTP_SERVER, "redirect http server post");
05341 } else {
05342 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler_post);
05343 tunnel.add_consumer(server_entry->vc,
05344 ua_entry->vc, &HttpSM::tunnel_handler_post_server, HT_HTTP_SERVER, "http server post");
05345 }
05346 server_entry->in_tunnel = true;
05347 break;
05348 default:
05349 ink_release_assert(0);
05350 break;
05351 }
05352
05353 if (chunked)
05354 tunnel.set_producer_chunking_action(p, 0, TCA_PASSTHRU_CHUNKED_CONTENT);
05355
05356 tunnel.tunnel_run(p);
05357 }
05358
05359
05360
05361
05362
05363 void
05364 HttpSM::perform_transform_cache_write_action()
05365 {
05366 DebugSM("http", "[%" PRId64 "] perform_transform_cache_write_action %s", sm_id,
05367 HttpDebugNames::get_cache_action_name(t_state.cache_info.action));
05368
05369 if (t_state.range_setup)
05370 return;
05371
05372 switch (t_state.cache_info.transform_action) {
05373 case HttpTransact::CACHE_DO_NO_ACTION:
05374 {
05375
05376 transform_cache_sm.end_both();
05377 break;
05378 }
05379
05380 case HttpTransact::CACHE_DO_WRITE:
05381 {
05382 transform_cache_sm.close_read();
05383 t_state.cache_info.transform_write_status = HttpTransact::CACHE_WRITE_IN_PROGRESS;
05384 setup_cache_write_transfer(&transform_cache_sm,
05385 transform_info.entry->vc,
05386 &t_state.cache_info.transform_store, client_response_hdr_bytes, "cache write t");
05387 break;
05388 }
05389
05390 default:
05391 ink_release_assert(0);
05392 break;
05393 }
05394
05395 }
05396
05397
05398
05399
05400
05401
05402
05403 void
05404 HttpSM::perform_cache_write_action()
05405 {
05406 DebugSM("http", "[%" PRId64 "] perform_cache_write_action %s",
05407 sm_id, HttpDebugNames::get_cache_action_name(t_state.cache_info.action));
05408
05409 switch (t_state.cache_info.action) {
05410 case HttpTransact::CACHE_DO_NO_ACTION:
05411
05412 {
05413
05414 cache_sm.end_both();
05415 break;
05416 }
05417
05418 case HttpTransact::CACHE_DO_SERVE:
05419 {
05420 cache_sm.abort_write();
05421 break;
05422 }
05423
05424 case HttpTransact::CACHE_DO_DELETE:
05425 {
05426
05427 cache_sm.close_write();
05428 cache_sm.close_read();
05429 break;
05430 }
05431
05432 case HttpTransact::CACHE_DO_SERVE_AND_DELETE:
05433 {
05434
05435
05436 break;
05437 }
05438
05439 case HttpTransact::CACHE_DO_SERVE_AND_UPDATE:
05440 {
05441 issue_cache_update();
05442 break;
05443 }
05444
05445 case HttpTransact::CACHE_DO_UPDATE:
05446 {
05447 cache_sm.close_read();
05448 issue_cache_update();
05449 break;
05450 }
05451
05452 case HttpTransact::CACHE_DO_WRITE:
05453 case HttpTransact::CACHE_DO_REPLACE:
05454
05455
05456 if (transform_info.entry == NULL || t_state.api_info.cache_untransformed == true) {
05457 cache_sm.close_read();
05458 t_state.cache_info.write_status = HttpTransact::CACHE_WRITE_IN_PROGRESS;
05459 setup_cache_write_transfer(&cache_sm,
05460 server_entry->vc,
05461 &t_state.cache_info.object_store, client_response_hdr_bytes, "cache write");
05462 } else {
05463
05464
05465 ink_assert(transform_cache_sm.cache_write_vc == NULL);
05466 transform_cache_sm.cache_write_vc = cache_sm.cache_write_vc;
05467 cache_sm.cache_write_vc = NULL;
05468 }
05469 break;
05470
05471 default:
05472 ink_release_assert(0);
05473 break;
05474 }
05475 }
05476
05477
05478 void
05479 HttpSM::issue_cache_update()
05480 {
05481 ink_assert(cache_sm.cache_write_vc != NULL);
05482 if (cache_sm.cache_write_vc) {
05483 t_state.cache_info.object_store.request_sent_time_set(t_state.request_sent_time);
05484 t_state.cache_info.object_store.response_received_time_set(t_state.response_received_time);
05485 ink_assert(t_state.cache_info.object_store.request_sent_time_get() > 0);
05486 ink_assert(t_state.cache_info.object_store.response_received_time_get() > 0);
05487 cache_sm.cache_write_vc->set_http_info(&t_state.cache_info.object_store);
05488 t_state.cache_info.object_store.clear();
05489 }
05490
05491 cache_sm.close_write();
05492 }
05493
05494 int
05495 HttpSM::write_header_into_buffer(HTTPHdr * h, MIOBuffer * b)
05496 {
05497 int bufindex;
05498 int dumpoffset;
05499 int done, tmp;
05500 IOBufferBlock *block;
05501
05502 dumpoffset = 0;
05503 do {
05504 bufindex = 0;
05505 tmp = dumpoffset;
05506 block = b->get_current_block();
05507 ink_assert(block->write_avail() > 0);
05508 done = h->print(block->start(), block->write_avail(), &bufindex, &tmp);
05509 dumpoffset += bufindex;
05510 ink_assert(bufindex > 0);
05511 b->fill(bufindex);
05512 if (!done) {
05513 b->add_block();
05514 }
05515 } while (!done);
05516
05517 return dumpoffset;
05518 }
05519
05520 void
05521 HttpSM::attach_server_session(HttpServerSession * s)
05522 {
05523 hsm_release_assert(server_session == NULL);
05524 hsm_release_assert(server_entry == NULL);
05525 hsm_release_assert(s->state == HSS_ACTIVE);
05526 server_session = s;
05527 server_session->transact_count++;
05528
05529
05530
05531 server_session->mutex = this->mutex;
05532
05533 HTTP_INCREMENT_DYN_STAT(http_current_server_transactions_stat);
05534 ++s->server_trans_stat;
05535
05536
05537 server_entry = vc_table.new_entry();
05538 server_entry->vc = server_session;
05539 server_entry->vc_type = HTTP_SERVER_VC;
05540 server_entry->vc_handler = &HttpSM::state_send_server_request_header;
05541
05542
05543
05544
05545
05546
05547 server_buffer_reader = server_session->get_reader();
05548 server_entry->read_vio = server_session->do_io_read(this, INT64_MAX, server_session->read_buffer);
05549
05550
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562 server_session->do_io_write(this, 0, NULL);
05563
05564
05565
05566
05567
05568 MgmtInt connect_timeout;
05569
05570 if (t_state.method == HTTP_WKSIDX_POST || t_state.method == HTTP_WKSIDX_PUT) {
05571 connect_timeout = t_state.txn_conf->post_connect_attempts_timeout;
05572 } else if (t_state.current.server == &t_state.parent_info) {
05573 connect_timeout = t_state.http_config_param->parent_connect_timeout;
05574 } else {
05575 connect_timeout = t_state.txn_conf->connect_attempts_timeout;
05576 }
05577 if (t_state.pCongestionEntry != NULL)
05578 connect_timeout = t_state.pCongestionEntry->connect_timeout();
05579
05580 if (t_state.api_txn_connect_timeout_value != -1) {
05581 server_session->get_netvc()->set_inactivity_timeout(HRTIME_MSECONDS(t_state.api_txn_connect_timeout_value));
05582 } else {
05583 server_session->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(connect_timeout));
05584 }
05585
05586 if (t_state.api_txn_active_timeout_value != -1) {
05587 server_session->get_netvc()->set_active_timeout(HRTIME_MSECONDS(t_state.api_txn_active_timeout_value));
05588 } else {
05589 server_session->get_netvc()->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_active_timeout_out));
05590 }
05591
05592 if (plugin_tunnel_type != HTTP_NO_PLUGIN_TUNNEL) {
05593 DebugSM("http_ss", "Setting server session to private");
05594 server_session->private_session = true;
05595 }
05596 }
05597
05598 void
05599 HttpSM::setup_server_send_request_api()
05600 {
05601 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_REQUEST_HDR;
05602 do_api_callout();
05603 }
05604
05605 void
05606 HttpSM::setup_server_send_request()
05607 {
05608 int hdr_length;
05609 int64_t msg_len = 0;
05610
05611 hsm_release_assert(server_entry != NULL);
05612 hsm_release_assert(server_session != NULL);
05613 hsm_release_assert(server_entry->vc == server_session);
05614
05615
05616 server_entry->vc_handler = &HttpSM::state_send_server_request_header;
05617 server_entry->write_buffer = new_MIOBuffer(HTTP_HEADER_BUFFER_SIZE_INDEX);
05618
05619 if (t_state.api_server_request_body_set) {
05620 msg_len = t_state.internal_msg_buffer_size;
05621 t_state.hdr_info.server_request.value_set_int64(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH, msg_len);
05622 }
05623 DUMP_HEADER("http_hdrs", &(t_state.hdr_info.server_request), t_state.state_machine_id, "Proxy's Request after hooks");
05624
05625
05626 IOBufferReader *buf_start = server_entry->write_buffer->alloc_reader();
05627 server_request_hdr_bytes = hdr_length =
05628 write_header_into_buffer(&t_state.hdr_info.server_request, server_entry->write_buffer);
05629
05630
05631 if (t_state.api_server_request_body_set) {
05632 DebugSM("http", "[%" PRId64 "] appending msg of %" PRId64" bytes to request %s", sm_id, msg_len, t_state.internal_msg_buffer);
05633 hdr_length += server_entry->write_buffer->write(t_state.internal_msg_buffer, msg_len);
05634 server_request_body_bytes = msg_len;
05635 }
05636
05637
05638 if (t_state.txn_conf->auth_server_session_private == 1 &&
05639 t_state.hdr_info.server_request.presence(MIME_PRESENCE_AUTHORIZATION | MIME_PRESENCE_PROXY_AUTHORIZATION | MIME_PRESENCE_WWW_AUTHENTICATE)) {
05640 server_session->private_session = true;
05641 DebugSM("http_ss", "Setting server session to private for authorization header");
05642 }
05643 milestones.server_begin_write = ink_get_hrtime();
05644 server_entry->write_vio = server_entry->vc->do_io_write(this, hdr_length, buf_start);
05645 }
05646
05647 void
05648 HttpSM::setup_server_read_response_header()
05649 {
05650 ink_assert(server_session != NULL);
05651 ink_assert(server_entry != NULL);
05652
05653 ink_assert(ua_session != NULL ||
05654 t_state.req_flavor == HttpTransact::REQ_FLAVOR_SCHEDULED_UPDATE ||
05655 t_state.req_flavor == HttpTransact::REQ_FLAVOR_REVPROXY);
05656
05657
05658
05659 ink_assert(server_buffer_reader != NULL);
05660
05661
05662
05663 server_entry->vc_handler = &HttpSM::state_read_server_response_header;
05664
05665 t_state.current.state = HttpTransact::STATE_UNDEFINED;
05666 t_state.current.server->state = HttpTransact::STATE_UNDEFINED;
05667
05668
05669
05670 t_state.hdr_info.server_response.destroy();
05671 t_state.hdr_info.server_response.create(HTTP_TYPE_RESPONSE);
05672 http_parser_clear(&http_parser);
05673 server_response_hdr_bytes = 0;
05674 milestones.server_read_header_done = 0;
05675
05676
05677
05678 ink_assert(server_entry->read_vio);
05679
05680
05681
05682
05683
05684
05685
05686 if (server_buffer_reader->read_avail() > 0) {
05687 if (server_entry->eos) {
05688
05689
05690 state_read_server_response_header(VC_EVENT_EOS, server_entry->read_vio);
05691 } else {
05692
05693
05694 state_read_server_response_header(VC_EVENT_READ_READY, server_entry->read_vio);
05695 }
05696 }
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707 if (server_entry != NULL) {
05708 if (t_state.current.server->state == HttpTransact::STATE_UNDEFINED &&
05709 server_entry->read_vio->nbytes == server_entry->read_vio->ndone &&
05710 milestones.server_read_header_done == 0) {
05711 ink_assert(server_entry->eos == false);
05712 server_entry->read_vio = server_session->do_io_read(this, INT64_MAX, server_buffer_reader->mbuf);
05713 }
05714 }
05715 }
05716
05717 void
05718 HttpSM::setup_cache_read_transfer()
05719 {
05720 int64_t alloc_index, hdr_size;
05721 int64_t doc_size;
05722
05723 ink_assert(cache_sm.cache_read_vc != NULL);
05724
05725 doc_size = t_state.cache_info.object_read->object_size_get();
05726 alloc_index = buffer_size_to_index(doc_size + index_to_buffer_size(HTTP_HEADER_BUFFER_SIZE_INDEX));
05727
05728 #ifndef USE_NEW_EMPTY_MIOBUFFER
05729 MIOBuffer *buf = new_MIOBuffer(alloc_index);
05730 #else
05731 MIOBuffer *buf = new_empty_MIOBuffer(alloc_index);
05732 buf->append_block(HTTP_HEADER_BUFFER_SIZE_INDEX);
05733 #endif
05734
05735 buf->water_mark = (int) t_state.txn_conf->default_buffer_water_mark;
05736
05737 IOBufferReader *buf_start = buf->alloc_reader();
05738
05739
05740 ink_assert(t_state.hdr_info.client_response.status_get() != HTTP_STATUS_NOT_MODIFIED);
05741 client_response_hdr_bytes = hdr_size = write_response_header_into_buffer(&t_state.hdr_info.client_response, buf);
05742 cache_response_hdr_bytes = client_response_hdr_bytes;
05743
05744
05745 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
05746
05747 if (doc_size != INT64_MAX)
05748 doc_size += hdr_size;
05749
05750 HttpTunnelProducer *p = tunnel.add_producer(cache_sm.cache_read_vc,
05751 doc_size, buf_start, &HttpSM::tunnel_handler_cache_read, HT_CACHE_READ,
05752 "cache read");
05753 tunnel.add_consumer(ua_entry->vc, cache_sm.cache_read_vc, &HttpSM::tunnel_handler_ua, HT_HTTP_CLIENT, "user agent");
05754
05755
05756
05757 if ( t_state.client_info.receive_chunked_response ) {
05758 tunnel.set_producer_chunking_action(p, client_response_hdr_bytes, TCA_CHUNK_CONTENT);
05759 tunnel.set_producer_chunking_size(p, t_state.txn_conf->http_chunking_size);
05760 }
05761 ua_entry->in_tunnel = true;
05762 cache_sm.cache_read_vc = NULL;
05763 }
05764
05765 HttpTunnelProducer *
05766 HttpSM::setup_cache_transfer_to_transform()
05767 {
05768 int64_t alloc_index;
05769 int64_t doc_size;
05770
05771 ink_assert(cache_sm.cache_read_vc != NULL);
05772 ink_assert(transform_info.vc != NULL);
05773 ink_assert(transform_info.entry->vc == transform_info.vc);
05774
05775
05776 cache_response_hdr_bytes = t_state.hdr_info.cache_response.length_get();
05777
05778 doc_size = t_state.cache_info.object_read->object_size_get();
05779 alloc_index = buffer_size_to_index(doc_size);
05780 MIOBuffer *buf = new_MIOBuffer(alloc_index);
05781 IOBufferReader *buf_start = buf->alloc_reader();
05782
05783
05784 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_response_wait_for_transform_read);
05785
05786 HttpTunnelProducer *p = tunnel.add_producer(cache_sm.cache_read_vc,
05787 doc_size,
05788 buf_start,
05789 &HttpSM::tunnel_handler_cache_read,
05790 HT_CACHE_READ,
05791 "cache read");
05792
05793 tunnel.add_consumer(transform_info.vc,
05794 cache_sm.cache_read_vc, &HttpSM::tunnel_handler_transform_write, HT_TRANSFORM, "transform write");
05795 transform_info.entry->in_tunnel = true;
05796 cache_sm.cache_read_vc = NULL;
05797
05798 return p;
05799 }
05800
05801 void
05802 HttpSM::setup_cache_write_transfer(HttpCacheSM * c_sm,
05803 VConnection * source_vc, HTTPInfo * store_info, int64_t skip_bytes, const char *name)
05804 {
05805 ink_assert(c_sm->cache_write_vc != NULL);
05806 ink_assert(t_state.request_sent_time > 0);
05807 ink_assert(t_state.response_received_time > 0);
05808
05809 store_info->request_sent_time_set(t_state.request_sent_time);
05810 store_info->response_received_time_set(t_state.response_received_time);
05811
05812 c_sm->cache_write_vc->set_http_info(store_info);
05813 store_info->clear();
05814
05815 tunnel.add_consumer(c_sm->cache_write_vc,
05816 source_vc, &HttpSM::tunnel_handler_cache_write, HT_CACHE_WRITE, name, skip_bytes);
05817
05818 c_sm->cache_write_vc = NULL;
05819 }
05820
05821 void
05822 HttpSM::setup_100_continue_transfer()
05823 {
05824 MIOBuffer *buf = new_MIOBuffer(HTTP_HEADER_BUFFER_SIZE_INDEX);
05825 IOBufferReader *buf_start = buf->alloc_reader();
05826
05827
05828 ink_assert(t_state.client_info.http_version != HTTPVersion(0, 9));
05829 client_response_hdr_bytes = write_header_into_buffer(&t_state.hdr_info.client_response, buf);
05830 ink_assert(client_response_hdr_bytes > 0);
05831
05832 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler_100_continue);
05833
05834
05835 tunnel.add_producer(HTTP_TUNNEL_STATIC_PRODUCER,
05836 client_response_hdr_bytes,
05837 buf_start, (HttpProducerHandler) NULL, HT_STATIC, "internal msg - 100 continue");
05838 tunnel.add_consumer(ua_entry->vc,
05839 HTTP_TUNNEL_STATIC_PRODUCER,
05840 &HttpSM::tunnel_handler_100_continue_ua, HT_HTTP_CLIENT, "user agent");
05841
05842 ua_entry->in_tunnel = true;
05843 tunnel.tunnel_run();
05844 }
05845
05846
05847
05848
05849
05850
05851
05852
05853
05854
05855
05856
05857
05858
05859
05860
05861
05862
05863 void
05864 HttpSM::setup_error_transfer()
05865 {
05866 if (t_state.internal_msg_buffer) {
05867
05868
05869 ink_assert(t_state.internal_msg_buffer_size > 0);
05870 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
05871 do_api_callout();
05872 } else {
05873 DebugSM("http", "[setup_error_transfer] Now closing connection ...");
05874 vc_table.cleanup_entry(ua_entry);
05875 ua_entry = NULL;
05876 ua_session = NULL;
05877 terminate_sm = true;
05878 t_state.source = HttpTransact::SOURCE_INTERNAL;
05879 }
05880 }
05881
05882 void
05883 HttpSM::setup_internal_transfer(HttpSMHandler handler_arg)
05884 {
05885 bool is_msg_buf_present;
05886
05887 if (t_state.internal_msg_buffer) {
05888 is_msg_buf_present = true;
05889 ink_assert(t_state.internal_msg_buffer_size > 0);
05890
05891
05892
05893 t_state.hdr_info.client_response.set_content_length(t_state.internal_msg_buffer_size);
05894
05895
05896 if (t_state.internal_msg_buffer_type) {
05897 int len = strlen(t_state.internal_msg_buffer_type);
05898
05899 if (len > 0) {
05900 t_state.hdr_info.client_response.value_set(MIME_FIELD_CONTENT_TYPE,
05901 MIME_LEN_CONTENT_TYPE,
05902 t_state.internal_msg_buffer_type, len);
05903 }
05904 ats_free(t_state.internal_msg_buffer_type);
05905 t_state.internal_msg_buffer_type = NULL;
05906 } else {
05907 t_state.hdr_info.client_response.value_set(MIME_FIELD_CONTENT_TYPE,
05908 MIME_LEN_CONTENT_TYPE,
05909 "text/html", 9);
05910 }
05911 } else {
05912 is_msg_buf_present = false;
05913
05914
05915
05916
05917 if (!is_response_body_precluded(t_state.hdr_info.client_response.status_get(), t_state.method)) {
05918 t_state.hdr_info.client_response.set_content_length(0);
05919 }
05920 }
05921
05922 t_state.source = HttpTransact::SOURCE_INTERNAL;
05923
05924 int64_t buf_size = index_to_buffer_size(HTTP_HEADER_BUFFER_SIZE_INDEX) + (is_msg_buf_present ? t_state.internal_msg_buffer_size : 0);
05925
05926 MIOBuffer *buf = new_MIOBuffer(buffer_size_to_index(buf_size));
05927 IOBufferReader *buf_start = buf->alloc_reader();
05928
05929
05930 client_response_hdr_bytes = write_response_header_into_buffer(&t_state.hdr_info.client_response, buf);
05931 int64_t nbytes = client_response_hdr_bytes;
05932
05933
05934
05935
05936
05937
05938
05939
05940
05941
05942
05943 if (is_msg_buf_present && t_state.method != HTTP_WKSIDX_HEAD) {
05944 nbytes += t_state.internal_msg_buffer_size;
05945
05946 if (t_state.internal_msg_buffer_fast_allocator_size < 0)
05947 buf->append_xmalloced(t_state.internal_msg_buffer, t_state.internal_msg_buffer_size);
05948 else
05949 buf->append_fast_allocated(t_state.internal_msg_buffer,
05950 t_state.internal_msg_buffer_size, t_state.internal_msg_buffer_fast_allocator_size);
05951
05952
05953
05954
05955 t_state.internal_msg_buffer = NULL;
05956 t_state.internal_msg_buffer_size = 0;
05957 }
05958
05959
05960 HTTP_SM_SET_DEFAULT_HANDLER(handler_arg);
05961
05962
05963 tunnel.add_producer(HTTP_TUNNEL_STATIC_PRODUCER,
05964 nbytes, buf_start, (HttpProducerHandler) NULL, HT_STATIC, "internal msg");
05965 tunnel.add_consumer(ua_entry->vc,
05966 HTTP_TUNNEL_STATIC_PRODUCER, &HttpSM::tunnel_handler_ua, HT_HTTP_CLIENT, "user agent");
05967
05968 ua_entry->in_tunnel = true;
05969 tunnel.tunnel_run();
05970 }
05971
05972
05973
05974
05975
05976
05977 int
05978 HttpSM::find_http_resp_buffer_size(int64_t content_length)
05979 {
05980 int64_t buf_size;
05981 int64_t alloc_index;
05982
05983 if (content_length == HTTP_UNDEFINED_CL) {
05984
05985
05986 alloc_index = (int) t_state.txn_conf->default_buffer_size_index;
05987 if (alloc_index<MIN_CONFIG_BUFFER_SIZE_INDEX || alloc_index> DEFAULT_MAX_BUFFER_SIZE) {
05988 alloc_index = DEFAULT_RESPONSE_BUFFER_SIZE_INDEX;
05989 }
05990 } else {
05991 #ifdef WRITE_AND_TRANSFER
05992 buf_size = HTTP_HEADER_BUFFER_SIZE + content_length - index_to_buffer_size(HTTP_SERVER_RESP_HDR_BUFFER_INDEX);
05993 #else
05994 buf_size = index_to_buffer_size(HTTP_HEADER_BUFFER_SIZE_INDEX) + content_length;
05995 #endif
05996 alloc_index = buffer_size_to_index(buf_size);
05997 }
05998
05999 return alloc_index;
06000 }
06001
06002
06003
06004
06005
06006
06007
06008 int64_t
06009 HttpSM::server_transfer_init(MIOBuffer * buf, int hdr_size)
06010 {
06011 int64_t nbytes;
06012 int64_t to_copy = INT64_MAX;
06013
06014 ink_assert(t_state.current.server != NULL);
06015
06016 if (server_entry->eos == true) {
06017
06018
06019 nbytes = server_buffer_reader->read_avail() + hdr_size;
06020 } else if (t_state.hdr_info.response_content_length == HTTP_UNDEFINED_CL) {
06021 nbytes = -1;
06022 } else {
06023
06024
06025
06026
06027 to_copy = t_state.hdr_info.response_content_length;
06028 nbytes = t_state.hdr_info.response_content_length + hdr_size;
06029 }
06030
06031
06032
06033
06034 int64_t server_response_pre_read_bytes =
06035 #ifdef WRITE_AND_TRANSFER
06036
06037
06038
06039 buf->write_and_transfer_left_over_space(server_buffer_reader, to_copy);
06040 #else
06041 buf->write(server_buffer_reader, to_copy);
06042 #endif
06043 server_buffer_reader->consume(server_response_pre_read_bytes);
06044
06045
06046
06047
06048
06049 if (server_response_pre_read_bytes == to_copy && server_buffer_reader->read_avail() > 0) {
06050 t_state.current.server->keep_alive = HTTP_NO_KEEPALIVE;
06051 }
06052 #ifdef LAZY_BUF_ALLOC
06053
06054 server_session->reset_read_buffer();
06055 #endif
06056 return nbytes;
06057 }
06058
06059 HttpTunnelProducer *
06060 HttpSM::setup_server_transfer_to_transform()
06061 {
06062 int64_t alloc_index;
06063 int64_t nbytes;
06064
06065 alloc_index = find_server_buffer_size();
06066 MIOBuffer *buf = new_MIOBuffer(alloc_index);
06067 IOBufferReader *buf_start = buf->alloc_reader();
06068 nbytes = server_transfer_init(buf, 0);
06069
06070 if (t_state.negative_caching && t_state.hdr_info.server_response.status_get() == HTTP_STATUS_NO_CONTENT) {
06071 int s = sizeof("No Content") - 1;
06072 buf->write("No Content", s);
06073 nbytes += s;
06074 }
06075
06076 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_response_wait_for_transform_read);
06077
06078 HttpTunnelProducer *p = tunnel.add_producer(server_entry->vc,
06079 nbytes,
06080 buf_start,
06081 &HttpSM::tunnel_handler_server,
06082 HT_HTTP_SERVER,
06083 "http server");
06084
06085 tunnel.add_consumer(transform_info.vc,
06086 server_entry->vc, &HttpSM::tunnel_handler_transform_write, HT_TRANSFORM, "transform write");
06087
06088 server_entry->in_tunnel = true;
06089 transform_info.entry->in_tunnel = true;
06090
06091 if (t_state.current.server->transfer_encoding == HttpTransact::CHUNKED_ENCODING) {
06092 client_response_hdr_bytes = 0;
06093 tunnel.set_producer_chunking_action(p, client_response_hdr_bytes, TCA_DECHUNK_CONTENT);
06094 }
06095
06096 return p;
06097 }
06098
06099 HttpTunnelProducer *
06100 HttpSM::setup_transfer_from_transform()
06101 {
06102 int64_t alloc_index = find_server_buffer_size();
06103
06104
06105 MIOBuffer *buf = new_MIOBuffer(alloc_index);
06106 buf->water_mark = (int) t_state.txn_conf->default_buffer_water_mark;
06107 IOBufferReader *buf_start = buf->alloc_reader();
06108
06109 HttpTunnelConsumer *c = tunnel.get_consumer(transform_info.vc);
06110 ink_assert(c != NULL);
06111 ink_assert(c->vc == transform_info.vc);
06112 ink_assert(c->vc_type == HT_TRANSFORM);
06113
06114
06115 ink_assert(t_state.hdr_info.client_response.status_get() != HTTP_STATUS_NOT_MODIFIED);
06116 client_response_hdr_bytes = write_response_header_into_buffer(&t_state.hdr_info.client_response, buf);
06117
06118 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
06119
06120 HttpTunnelProducer *p = tunnel.add_producer(transform_info.vc,
06121 INT64_MAX,
06122 buf_start,
06123 &HttpSM::tunnel_handler_transform_read,
06124 HT_TRANSFORM,
06125 "transform read");
06126 tunnel.chain(c, p);
06127
06128 tunnel.add_consumer(ua_entry->vc, transform_info.vc, &HttpSM::tunnel_handler_ua, HT_HTTP_CLIENT, "user agent");
06129
06130 transform_info.entry->in_tunnel = true;
06131 ua_entry->in_tunnel = true;
06132
06133 this->setup_plugin_agents(p);
06134
06135 if ( t_state.client_info.receive_chunked_response ) {
06136 tunnel.set_producer_chunking_action(p, client_response_hdr_bytes, TCA_CHUNK_CONTENT);
06137 tunnel.set_producer_chunking_size(p, t_state.txn_conf->http_chunking_size);
06138 }
06139
06140 return p;
06141 }
06142
06143
06144 HttpTunnelProducer *
06145 HttpSM::setup_transfer_from_transform_to_cache_only()
06146 {
06147 int64_t alloc_index = find_server_buffer_size();
06148 MIOBuffer *buf = new_MIOBuffer(alloc_index);
06149 IOBufferReader *buf_start = buf->alloc_reader();
06150
06151 HttpTunnelConsumer *c = tunnel.get_consumer(transform_info.vc);
06152 ink_assert(c != NULL);
06153 ink_assert(c->vc == transform_info.vc);
06154 ink_assert(c->vc_type == HT_TRANSFORM);
06155
06156 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
06157
06158 HttpTunnelProducer *p = tunnel.add_producer(transform_info.vc,
06159 INT64_MAX,
06160 buf_start,
06161 &HttpSM::tunnel_handler_transform_read,
06162 HT_TRANSFORM,
06163 "transform read");
06164 tunnel.chain(c, p);
06165
06166 transform_info.entry->in_tunnel = true;
06167
06168 ink_assert(t_state.cache_info.transform_action == HttpTransact::CACHE_DO_WRITE);
06169
06170 perform_transform_cache_write_action();
06171
06172 return p;
06173 }
06174
06175 void
06176 HttpSM::setup_server_transfer_to_cache_only()
06177 {
06178 TunnelChunkingAction_t action;
06179 int64_t alloc_index;
06180 int64_t nbytes;
06181
06182 alloc_index = find_server_buffer_size();
06183 MIOBuffer *buf = new_MIOBuffer(alloc_index);
06184 IOBufferReader *buf_start = buf->alloc_reader();
06185
06186 action = (t_state.current.server && t_state.current.server->transfer_encoding == HttpTransact::CHUNKED_ENCODING) ?
06187 TCA_DECHUNK_CONTENT : TCA_PASSTHRU_DECHUNKED_CONTENT;
06188
06189 nbytes = server_transfer_init(buf, 0);
06190
06191 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
06192
06193 HttpTunnelProducer *p = tunnel.add_producer(server_entry->vc,
06194 nbytes,
06195 buf_start,
06196 &HttpSM::tunnel_handler_server,
06197 HT_HTTP_SERVER,
06198 "http server");
06199
06200 tunnel.set_producer_chunking_action(p, 0, action);
06201 tunnel.set_producer_chunking_size(p, t_state.txn_conf->http_chunking_size);
06202
06203 setup_cache_write_transfer(&cache_sm, server_entry->vc, &t_state.cache_info.object_store, 0, "cache write");
06204
06205 server_entry->in_tunnel = true;
06206 }
06207
06208 void
06209 HttpSM::setup_server_transfer()
06210 {
06211 DebugSM("http", "Setup Server Transfer");
06212 int64_t alloc_index, hdr_size;
06213 int64_t nbytes;
06214
06215 alloc_index = find_server_buffer_size();
06216 #ifndef USE_NEW_EMPTY_MIOBUFFER
06217 MIOBuffer *buf = new_MIOBuffer(alloc_index);
06218 #else
06219 MIOBuffer *buf = new_empty_MIOBuffer(alloc_index);
06220 buf->append_block(HTTP_HEADER_BUFFER_SIZE_INDEX);
06221 #endif
06222 buf->water_mark = (int) t_state.txn_conf->default_buffer_water_mark;
06223 IOBufferReader *buf_start = buf->alloc_reader();
06224
06225
06226
06227 TunnelChunkingAction_t action;
06228 if (t_state.client_info.receive_chunked_response == false) {
06229 if (t_state.current.server->transfer_encoding == HttpTransact::CHUNKED_ENCODING)
06230 action = TCA_DECHUNK_CONTENT;
06231 else
06232 action = TCA_PASSTHRU_DECHUNKED_CONTENT;
06233 } else {
06234 if (t_state.current.server->transfer_encoding != HttpTransact::CHUNKED_ENCODING)
06235 if (t_state.client_info.http_version == HTTPVersion(0, 9))
06236 action = TCA_PASSTHRU_DECHUNKED_CONTENT;
06237 else
06238 action = TCA_CHUNK_CONTENT;
06239 else
06240 action = TCA_PASSTHRU_CHUNKED_CONTENT;
06241 }
06242 if (action == TCA_CHUNK_CONTENT || action == TCA_PASSTHRU_CHUNKED_CONTENT) {
06243 t_state.hdr_info.client_response.field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
06244 }
06245
06246 ink_assert(t_state.hdr_info.client_response.status_get() != HTTP_STATUS_NOT_MODIFIED);
06247 client_response_hdr_bytes = hdr_size = write_response_header_into_buffer(&t_state.hdr_info.client_response, buf);
06248
06249 nbytes = server_transfer_init(buf, hdr_size);
06250
06251 if (t_state.negative_caching && t_state.hdr_info.server_response.status_get() == HTTP_STATUS_NO_CONTENT) {
06252 int s = sizeof("No Content") - 1;
06253 buf->write("No Content", s);
06254 nbytes += s;
06255 }
06256
06257 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
06258
06259 HttpTunnelProducer *p = tunnel.add_producer(server_entry->vc,
06260 nbytes,
06261 buf_start,
06262 &HttpSM::tunnel_handler_server,
06263 HT_HTTP_SERVER,
06264 "http server");
06265
06266 tunnel.add_consumer(ua_entry->vc, server_entry->vc, &HttpSM::tunnel_handler_ua, HT_HTTP_CLIENT, "user agent");
06267
06268 ua_entry->in_tunnel = true;
06269 server_entry->in_tunnel = true;
06270
06271 this->setup_plugin_agents(p);
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287
06288
06289
06290
06291
06292
06293
06294
06295 tunnel.set_producer_chunking_action(p, client_response_hdr_bytes, action);
06296 tunnel.set_producer_chunking_size(p, t_state.txn_conf->http_chunking_size);
06297 }
06298
06299 void
06300 HttpSM::setup_push_transfer_to_cache()
06301 {
06302 int64_t nbytes, alloc_index;
06303
06304 alloc_index = find_http_resp_buffer_size(t_state.hdr_info.request_content_length);
06305 MIOBuffer *buf = new_MIOBuffer(alloc_index);
06306 IOBufferReader *buf_start = buf->alloc_reader();
06307
06308 ink_release_assert(t_state.hdr_info.request_content_length != HTTP_UNDEFINED_CL);
06309 nbytes = t_state.hdr_info.request_content_length - pushed_response_hdr_bytes;
06310 ink_release_assert(nbytes >= 0);
06311
06312 if (ua_entry->eos == true) {
06313
06314
06315
06316 int64_t avail = ua_buffer_reader->read_avail();
06317
06318 if (avail < nbytes) {
06319
06320
06321 terminate_sm = true;
06322 return;
06323 }
06324 }
06325
06326
06327 pushed_response_body_bytes = buf->write(ua_buffer_reader, nbytes);
06328 ua_buffer_reader->consume(pushed_response_body_bytes);
06329 client_request_body_bytes += pushed_response_body_bytes;
06330
06331 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler_push);
06332
06333
06334 tunnel.add_producer(ua_entry->vc, nbytes, buf_start, &HttpSM::tunnel_handler_ua_push,
06335 HT_HTTP_CLIENT, "user_agent");
06336 setup_cache_write_transfer(&cache_sm, ua_entry->vc, &t_state.cache_info.object_store, 0, "cache write");
06337
06338 ua_entry->in_tunnel = true;
06339 }
06340
06341 void
06342 HttpSM::setup_blind_tunnel(bool send_response_hdr)
06343 {
06344 HttpTunnelConsumer *c_ua;
06345 HttpTunnelConsumer *c_os;
06346 HttpTunnelProducer *p_ua;
06347 HttpTunnelProducer *p_os;
06348 MIOBuffer *from_ua_buf = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
06349 MIOBuffer *to_ua_buf = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
06350 IOBufferReader *r_from = from_ua_buf->alloc_reader();
06351 IOBufferReader *r_to = to_ua_buf->alloc_reader();
06352
06353 milestones.server_begin_write = ink_get_hrtime();
06354 if (send_response_hdr) {
06355 client_response_hdr_bytes = write_response_header_into_buffer(&t_state.hdr_info.client_response, to_ua_buf);
06356 } else {
06357 client_response_hdr_bytes = 0;
06358 }
06359
06360 client_request_body_bytes = 0;
06361 if (ua_raw_buffer_reader != NULL) {
06362 client_request_body_bytes += from_ua_buf->write(ua_raw_buffer_reader, client_request_hdr_bytes);
06363 ua_raw_buffer_reader->dealloc();
06364 ua_raw_buffer_reader = NULL;
06365 }
06366
06367
06368
06369 client_request_body_bytes += from_ua_buf->write(ua_buffer_reader);
06370
06371 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::tunnel_handler);
06372
06373 p_os = tunnel.add_producer(server_entry->vc,
06374 -1, r_to, &HttpSM::tunnel_handler_ssl_producer, HT_HTTP_SERVER, "http server - tunnel");
06375
06376 c_ua = tunnel.add_consumer(ua_entry->vc,
06377 server_entry->vc,
06378 &HttpSM::tunnel_handler_ssl_consumer, HT_HTTP_CLIENT, "user agent - tunnel");
06379
06380
06381 p_ua = tunnel.add_producer(ua_entry->vc,
06382 -1, r_from, &HttpSM::tunnel_handler_ssl_producer, HT_HTTP_CLIENT, "user agent - tunnel");
06383
06384 c_os = tunnel.add_consumer(server_entry->vc,
06385 ua_entry->vc,
06386 &HttpSM::tunnel_handler_ssl_consumer, HT_HTTP_SERVER, "http server - tunnel");
06387
06388
06389 tunnel.chain(c_os, p_os);
06390 tunnel.chain(c_ua, p_ua);
06391
06392 ua_entry->in_tunnel = true;
06393 server_entry->in_tunnel = true;
06394
06395 tunnel.tunnel_run();
06396 }
06397
06398 void
06399 HttpSM::setup_plugin_agents(HttpTunnelProducer* p)
06400 {
06401 APIHook* agent = txn_hook_get(TS_HTTP_RESPONSE_CLIENT_HOOK);
06402 has_active_plugin_agents = agent != 0;
06403 while (agent) {
06404 INKVConnInternal* contp = static_cast<INKVConnInternal*>(agent->m_cont);
06405 tunnel.add_consumer(contp, p->vc, &HttpSM::tunnel_handler_plugin_agent, HT_HTTP_CLIENT, "plugin agent");
06406
06407
06408 agent = agent->next();
06409 }
06410 }
06411
06412 inline void
06413 HttpSM::transform_cleanup(TSHttpHookID hook, HttpTransformInfo * info)
06414 {
06415 APIHook *t_hook = api_hooks.get(hook);
06416 if (t_hook && info->vc == NULL) {
06417 do {
06418 VConnection *t_vcon = t_hook->m_cont;
06419 t_vcon->do_io_close();
06420 t_hook = t_hook->m_link.next;
06421 } while (t_hook != NULL);
06422 }
06423 }
06424
06425 void
06426 HttpSM::plugin_agents_cleanup()
06427 {
06428
06429
06430
06431 if (!has_active_plugin_agents) {
06432 APIHook* agent = txn_hook_get(TS_HTTP_RESPONSE_CLIENT_HOOK);
06433 while (agent) {
06434 INKVConnInternal* contp = static_cast<INKVConnInternal*>(agent->m_cont);
06435 contp->do_io_close();
06436 agent = agent->next();
06437 }
06438 }
06439 }
06440
06441
06442
06443
06444
06445
06446
06447
06448
06449
06450
06451 void
06452 HttpSM::kill_this()
06453 {
06454 ink_release_assert(reentrancy_count == 1);
06455 tunnel.deallocate_redirect_postdata_buffers();
06456 enable_redirection = false;
06457
06458 if (kill_this_async_done == false) {
06459
06460
06461
06462
06463
06464
06465
06466
06467 if (callout_state == HTTP_API_NO_CALLOUT && pending_action) {
06468 pending_action->cancel();
06469 pending_action = NULL;
06470 }
06471
06472 cache_sm.end_both();
06473 if (second_cache_sm)
06474 second_cache_sm->end_both();
06475 transform_cache_sm.end_both();
06476 vc_table.cleanup_all();
06477 tunnel.deallocate_buffers();
06478
06479
06480
06481
06482
06483 if (hooks_set) {
06484 transform_cleanup(TS_HTTP_RESPONSE_TRANSFORM_HOOK, &transform_info);
06485 transform_cleanup(TS_HTTP_REQUEST_TRANSFORM_HOOK, &post_transform_info);
06486 plugin_agents_cleanup();
06487 }
06488
06489
06490 if (plugin_tunnel) {
06491 plugin_tunnel->kill_no_connect();
06492 plugin_tunnel = NULL;
06493 }
06494
06495 ua_session = NULL;
06496 server_session = NULL;
06497
06498
06499
06500
06501 terminate_sm = false;
06502 t_state.api_next_action = HttpTransact::SM_ACTION_API_SM_SHUTDOWN;
06503 do_api_callout();
06504 }
06505
06506
06507
06508
06509
06510
06511
06512
06513
06514
06515
06516
06517 reentrancy_count--;
06518 ink_release_assert(reentrancy_count == 0);
06519
06520
06521
06522
06523 if (kill_this_async_done == true) {
06524
06525
06526
06527 if (plugin_tunnel) {
06528 plugin_tunnel->kill_no_connect();
06529 plugin_tunnel = NULL;
06530 }
06531
06532 if (t_state.pCongestionEntry != NULL) {
06533 if (t_state.congestion_congested_or_failed != 1) {
06534 t_state.pCongestionEntry->go_alive();
06535 }
06536 }
06537
06538 ink_assert(pending_action == NULL);
06539 ink_release_assert(vc_table.is_table_clear() == true);
06540 ink_release_assert(tunnel.is_tunnel_active() == false);
06541
06542 if (t_state.http_config_param->enable_http_stats)
06543 update_stats();
06544
06545 HTTP_SM_SET_DEFAULT_HANDLER(NULL);
06546
06547 if (redirect_url != NULL) {
06548 ats_free((void*)redirect_url);
06549 redirect_url = NULL;
06550 redirect_url_len = 0;
06551 }
06552
06553 #ifdef USE_HTTP_DEBUG_LISTS
06554 ink_mutex_acquire(&debug_sm_list_mutex);
06555 debug_sm_list.remove(this, this->debug_link);
06556 ink_mutex_release(&debug_sm_list_mutex);
06557 #endif
06558
06559 DebugSM("http", "[%" PRId64 "] deallocating sm", sm_id);
06560
06561 destroy();
06562 }
06563 }
06564
06565 void
06566 HttpSM::update_stats()
06567 {
06568 milestones.sm_finish = ink_get_hrtime();
06569
06570 if (t_state.cop_test_page && !t_state.http_config_param->record_cop_page) {
06571 DebugSM("http_seq", "Skipping cop heartbeat logging & stats due to config");
06572 return;
06573 }
06574
06575
06576
06577
06578 DebugSM("http_seq", "[HttpSM::update_stats] Logging transaction");
06579 if (Log::transaction_logging_enabled() && t_state.api_info.logging_enabled) {
06580 LogAccessHttp accessor(this);
06581
06582 int ret = Log::access(&accessor);
06583
06584 if (ret & Log::FULL) {
06585 DebugSM("http", "[update_stats] Logging system indicates FULL.");
06586 }
06587 if (ret & Log::FAIL) {
06588 Log::error("failed to log transaction for at least one log object");
06589 }
06590 }
06591
06592 if (is_action_tag_set("bad_length_state_dump")) {
06593 if (t_state.hdr_info.client_response.valid() && t_state.hdr_info.client_response.status_get() == HTTP_STATUS_OK) {
06594 int64_t p_resp_cl = t_state.hdr_info.client_response.get_content_length();
06595 int64_t resp_size = client_response_body_bytes;
06596 if (!((p_resp_cl == -1 || p_resp_cl == resp_size || resp_size == 0))) {
06597 Error("[%" PRId64 "] Truncated content detected", sm_id);
06598 dump_state_on_assert();
06599 }
06600 } else if (client_request_hdr_bytes == 0) {
06601 Error("[%" PRId64 "] Zero length request header received", sm_id);
06602 dump_state_on_assert();
06603 }
06604 }
06605
06606 if (is_action_tag_set("assert_jtest_length")) {
06607 if (t_state.hdr_info.client_response.valid() && t_state.hdr_info.client_response.status_get() == HTTP_STATUS_OK) {
06608 int64_t p_resp_cl = t_state.hdr_info.client_response.get_content_length();
06609 int64_t resp_size = client_response_body_bytes;
06610 ink_release_assert(p_resp_cl == -1 || p_resp_cl == resp_size || resp_size == 0);
06611 }
06612 }
06613
06614 ink_hrtime total_time = milestones.sm_finish - milestones.sm_start;
06615
06616
06617
06618 if (milestones.ua_close == 0 && milestones.ua_read_header_done > 0)
06619 milestones.ua_close = ink_get_hrtime();
06620
06621
06622 ink_hrtime request_process_time = milestones.ua_close - milestones.ua_read_header_done;
06623
06624 HttpTransact::client_result_stat(&t_state, total_time, request_process_time);
06625
06626 ink_hrtime ua_write_time;
06627 if (milestones.ua_begin_write != 0 && milestones.ua_close != 0) {
06628 ua_write_time = milestones.ua_close - milestones.ua_begin_write;
06629 } else {
06630 ua_write_time = -1;
06631 }
06632
06633 ink_hrtime os_read_time;
06634 if (milestones.server_read_header_done != 0 && milestones.server_close != 0) {
06635 os_read_time = milestones.server_close - milestones.server_read_header_done;
06636 } else {
06637 os_read_time = -1;
06638 }
06639
06640
06641
06642 #if 0
06643 ink_hrtime cache_lookup_time;
06644 if (milestones.cache_open_read_end != 0 && milestones.cache_open_read_begin != 0) {
06645 cache_lookup_time = milestones.cache_open_read_end - milestones.cache_open_read_begin;
06646 } else {
06647 cache_lookup_time = -1;
06648 }
06649 #endif
06650
06651 HttpTransact::update_size_and_time_stats(&t_state, total_time, ua_write_time, os_read_time, client_request_hdr_bytes,
06652 client_request_body_bytes, client_response_hdr_bytes, client_response_body_bytes,
06653 server_request_hdr_bytes, server_request_body_bytes, server_response_hdr_bytes,
06654 server_response_body_bytes, pushed_response_hdr_bytes, pushed_response_body_bytes);
06655
06656
06657
06658
06659
06660
06661
06662
06663 if (t_state.http_config_param->slow_log_threshold != 0 &&
06664 ink_hrtime_from_msec(t_state.http_config_param->slow_log_threshold) < total_time) {
06665 URL* url = t_state.hdr_info.client_request.url_get();
06666 char url_string[256] = "";
06667 int offset = 0;
06668 int skip = 0;
06669
06670 t_state.hdr_info.client_request.url_print(url_string, sizeof url_string, &offset, &skip);
06671
06672
06673 char unique_id_string[128] = "";
06674
06675 if (0 != url && url->valid()) {
06676 int length = 0;
06677 const char *field = t_state.hdr_info.client_request.value_get(MIME_FIELD_X_ID, MIME_LEN_X_ID, &length);
06678 if (field != NULL) {
06679 ink_strlcpy(unique_id_string, field, sizeof(unique_id_string));
06680 }
06681 }
06682
06683
06684 int fd = 0;
06685 NetVConnection *vc = NULL;
06686 if (ua_session != NULL) {
06687 vc = ua_session->get_netvc();
06688 if (vc != NULL) {
06689 fd = vc->get_socket();
06690 } else {
06691 fd = -1;
06692 }
06693 }
06694
06695 int status = 0;
06696 if (t_state.hdr_info.client_response.valid()) {
06697 status = t_state.hdr_info.client_response.status_get();
06698 }
06699 char client_ip[INET6_ADDRSTRLEN];
06700 ats_ip_ntop(&t_state.client_info.addr, client_ip, sizeof(client_ip));
06701 Error("[%" PRId64 "] Slow Request: "
06702 "client_ip: %s:%u "
06703 "url: %s "
06704 "status: %d "
06705 "unique id: %s "
06706 "bytes: %" PRId64 " "
06707 "fd: %d "
06708 "client state: %d "
06709 "server state: %d "
06710 "ua_begin: %.3f "
06711 "ua_read_header_done: %.3f "
06712 "cache_open_read_begin: %.3f "
06713 "cache_open_read_end: %.3f "
06714 "dns_lookup_begin: %.3f "
06715 "dns_lookup_end: %.3f "
06716 "server_connect: %.3f "
06717 "server_first_read: %.3f "
06718 "server_read_header_done: %.3f "
06719 "server_close: %.3f "
06720 "ua_close: %.3f "
06721 "sm_finish: %.3f",
06722 sm_id,
06723 client_ip,
06724 ats_ip_port_host_order(&t_state.client_info.addr),
06725 url_string,
06726 status,
06727 unique_id_string,
06728 client_response_body_bytes,
06729 fd,
06730 t_state.client_info.state,
06731 t_state.server_info.state,
06732 milestone_difference(milestones.sm_start, milestones.ua_begin),
06733 milestone_difference(milestones.sm_start, milestones.ua_read_header_done),
06734 milestone_difference(milestones.sm_start, milestones.cache_open_read_begin),
06735 milestone_difference(milestones.sm_start, milestones.cache_open_read_end),
06736 milestone_difference(milestones.sm_start, milestones.dns_lookup_begin),
06737 milestone_difference(milestones.sm_start, milestones.dns_lookup_end),
06738 milestone_difference(milestones.sm_start, milestones.server_connect),
06739 milestone_difference(milestones.sm_start, milestones.server_first_read),
06740 milestone_difference(milestones.sm_start, milestones.server_read_header_done),
06741 milestone_difference(milestones.sm_start, milestones.server_close),
06742 milestone_difference(milestones.sm_start, milestones.ua_close),
06743 milestone_difference(milestones.sm_start, milestones.sm_finish)
06744 );
06745
06746 }
06747 }
06748
06749
06750
06751
06752
06753
06754
06755
06756
06757 void
06758 HttpSM::dump_state_on_assert()
06759 {
06760 Error("[%" PRId64 "] ------- begin http state dump -------", sm_id);
06761
06762 int hist_size = this->history_pos;
06763 if (this->history_pos > HISTORY_SIZE) {
06764 hist_size = HISTORY_SIZE;
06765 Error(" History Wrap around. history_pos: %d", this->history_pos);
06766 }
06767
06768 for (int i = 0; i < hist_size; i++) {
06769 int r = history[i].reentrancy;
06770 int e = history[i].event;
06771 Error("%d %d %s", e, r, history[i].fileline);
06772 }
06773
06774
06775 Error("Via String: [%s]\n", t_state.via_string);
06776
06777
06778 dump_state_hdr(&t_state.hdr_info.client_request, "Client Request");
06779 dump_state_hdr(&t_state.hdr_info.server_request, "Server Request");
06780 dump_state_hdr(&t_state.hdr_info.server_response, "Server Response");
06781 dump_state_hdr(&t_state.hdr_info.transform_response, "Transform Response");
06782 dump_state_hdr(&t_state.hdr_info.client_response, "Client Response");
06783
06784 Error("[%" PRId64 "] ------- end http state dump ---------", sm_id);
06785 }
06786
06787 void
06788 HttpSM::dump_state_hdr(HTTPHdr *h, const char *s)
06789 {
06790
06791 if (h->valid()) {
06792 int l = h->length_get();
06793 char *hdr_buf = (char *)ats_malloc(l + 1);
06794 int index = 0;
06795 int offset = 0;
06796
06797 h->print(hdr_buf, l, &index, &offset);
06798
06799 hdr_buf[l] = '\0';
06800 Error(" ---- %s [%" PRId64 "] ----\n%s\n", s, sm_id, hdr_buf);
06801 ats_free(hdr_buf);
06802 }
06803 }
06804
06805
06806
06807
06808
06809
06810
06811
06812
06813
06814
06815
06816
06817
06818
06819
06820
06821
06822
06823
06824
06825
06826
06827
06828
06829
06830 void
06831 HttpSM::call_transact_and_set_next_state(TransactEntryFunc_t f)
06832 {
06833 last_action = t_state.next_action;
06834
06835
06836
06837
06838 if (f == NULL) {
06839 ink_release_assert(t_state.transact_return_point != NULL);
06840 t_state.transact_return_point(&t_state);
06841 } else {
06842 f(&t_state);
06843 }
06844
06845 DebugSM("http", "[%" PRId64 "] State Transition: %s -> %s",
06846 sm_id, HttpDebugNames::get_action_name(last_action), HttpDebugNames::get_action_name(t_state.next_action));
06847
06848 set_next_state();
06849
06850 return;
06851 }
06852
06853
06854
06855
06856
06857
06858
06859
06860
06861
06862
06863
06864 void
06865 HttpSM::set_next_state()
06866 {
06867
06868
06869
06870 switch (t_state.next_action) {
06871 case HttpTransact::SM_ACTION_API_READ_REQUEST_HDR:
06872 case HttpTransact::SM_ACTION_API_PRE_REMAP:
06873 case HttpTransact::SM_ACTION_API_POST_REMAP:
06874 case HttpTransact::SM_ACTION_API_OS_DNS:
06875 case HttpTransact::SM_ACTION_API_SEND_REQUEST_HDR:
06876 case HttpTransact::SM_ACTION_API_READ_CACHE_HDR:
06877 case HttpTransact::SM_ACTION_API_READ_RESPONSE_HDR:
06878 case HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR:
06879 case HttpTransact::SM_ACTION_API_CACHE_LOOKUP_COMPLETE:
06880 {
06881 t_state.api_next_action = t_state.next_action;
06882 do_api_callout();
06883 break;
06884 }
06885
06886 case HttpTransact::SM_ACTION_POST_REMAP_SKIP:
06887 {
06888 call_transact_and_set_next_state(NULL);
06889 break;
06890 }
06891
06892 case HttpTransact::SM_ACTION_REMAP_REQUEST:
06893 {
06894 if (!remapProcessor.using_separate_thread()) {
06895 do_remap_request(true);
06896 DebugSM("url_rewrite", "completed inline remapping request for [%" PRId64 "]", sm_id);
06897 t_state.url_remap_success = remapProcessor.finish_remap(&t_state);
06898 call_transact_and_set_next_state(NULL);
06899 } else {
06900 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_remap_request);
06901 do_remap_request(false);
06902 }
06903 break;
06904 }
06905
06906 case HttpTransact::SM_ACTION_DNS_LOOKUP:
06907 {
06908 sockaddr const* addr;
06909
06910 if (t_state.api_server_addr_set) {
06911
06912
06913
06914 ip_text_buffer ipb;
06915 DebugSM("dns", "[HttpTransact::HandleRequest] Skipping DNS lookup for API supplied target %s.\n", ats_ip_ntop(&t_state.server_info.addr, ipb, sizeof(ipb)));
06916
06917 ats_ip_copy(t_state.host_db_info.ip(), &t_state.server_info.addr);
06918 t_state.dns_info.lookup_success = true;
06919 call_transact_and_set_next_state(NULL);
06920 break;
06921 } else if (url_remap_mode == HttpTransact::URL_REMAP_FOR_OS && t_state.first_dns_lookup) {
06922 DebugSM("cdn", "Skipping DNS Lookup");
06923
06924 t_state.first_dns_lookup = false;
06925 call_transact_and_set_next_state(HttpTransact::HandleFiltering);
06926 break;
06927 } else if (t_state.http_config_param->use_client_target_addr == 2
06928 && !t_state.url_remap_success
06929 && t_state.parent_result.r != PARENT_SPECIFIED
06930 && t_state.client_info.is_transparent
06931 && t_state.dns_info.os_addr_style == HttpTransact::DNSLookupInfo::OS_ADDR_TRY_DEFAULT
06932 && ats_is_ip(addr = t_state.state_machine->ua_session->get_netvc()->get_local_addr())
06933 ) {
06934
06935
06936
06937
06938
06939
06940 if (is_debug_tag_set("dns")) {
06941 ip_text_buffer ipb;
06942 DebugSM("dns", "[HttpTransact::HandleRequest] Skipping DNS lookup for client supplied target %s.\n", ats_ip_ntop(addr, ipb, sizeof(ipb)));
06943 }
06944 ats_ip_copy(t_state.host_db_info.ip(), addr);
06945 if (t_state.hdr_info.client_request.version_get() == HTTPVersion(0, 9))
06946 t_state.host_db_info.app.http_data.http_version = HostDBApplicationInfo::HTTP_VERSION_09;
06947 else if (t_state.hdr_info.client_request.version_get() == HTTPVersion(1, 0))
06948 t_state.host_db_info.app.http_data.http_version = HostDBApplicationInfo::HTTP_VERSION_10;
06949 else
06950 t_state.host_db_info.app.http_data.http_version = HostDBApplicationInfo::HTTP_VERSION_11;
06951
06952 t_state.dns_info.lookup_success = true;
06953
06954
06955 t_state.dns_info.os_addr_style = HttpTransact::DNSLookupInfo::OS_ADDR_TRY_CLIENT;
06956 call_transact_and_set_next_state(NULL);
06957 break;
06958 } else if (t_state.parent_result.r == PARENT_UNDEFINED && t_state.dns_info.lookup_success) {
06959
06960 ink_assert(ats_is_ip(t_state.host_db_info.ip()));
06961 DebugSM("dns", "[HttpTransact::HandleRequest] Skipping DNS lookup, provided by plugin");
06962 call_transact_and_set_next_state(NULL);
06963 break;
06964 } else if (t_state.dns_info.looking_up == HttpTransact::ORIGIN_SERVER &&
06965 t_state.http_config_param->no_dns_forward_to_parent){
06966
06967 if (t_state.cop_test_page)
06968 ats_ip_copy(t_state.host_db_info.ip(), t_state.state_machine->ua_session->get_netvc()->get_local_addr());
06969
06970 t_state.dns_info.lookup_success = true;
06971 call_transact_and_set_next_state(NULL);
06972 break;
06973 }
06974
06975 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_hostdb_lookup);
06976
06977 ink_assert(t_state.dns_info.looking_up != HttpTransact::UNDEFINED_LOOKUP);
06978 do_hostdb_lookup();
06979 break;
06980 }
06981
06982 case HttpTransact::SM_ACTION_DNS_REVERSE_LOOKUP:
06983 {
06984 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_hostdb_reverse_lookup);
06985 do_hostdb_reverse_lookup();
06986 break;
06987 }
06988
06989 case HttpTransact::SM_ACTION_CACHE_LOOKUP:
06990 {
06991 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_cache_open_read);
06992 do_cache_lookup_and_read();
06993 break;
06994 }
06995
06996 case HttpTransact::SM_ACTION_ORIGIN_SERVER_OPEN:
06997 {
06998 if (congestionControlEnabled && (t_state.congest_saved_next_action == HttpTransact::SM_ACTION_UNDEFINED)) {
06999 t_state.congest_saved_next_action = HttpTransact::SM_ACTION_ORIGIN_SERVER_OPEN;
07000 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_congestion_control_lookup);
07001 if (!do_congestion_control_lookup())
07002 break;
07003 }
07004 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_http_server_open);
07005
07006
07007 if (server_entry) {
07008 ink_assert(server_entry->vc_type == HTTP_SERVER_VC);
07009 vc_table.cleanup_entry(server_entry);
07010 server_entry = NULL;
07011 server_session = NULL;
07012 } else {
07013
07014
07015
07016
07017
07018
07019
07020
07021
07022
07023 if (ua_session && !t_state.hdr_info.request_content_length) {
07024 ua_session->get_netvc()->cancel_inactivity_timeout();
07025 }
07026 }
07027
07028 do_http_server_open();
07029 break;
07030 }
07031
07032 case HttpTransact::SM_ACTION_SERVER_PARSE_NEXT_HDR:
07033 {
07034 setup_server_read_response_header();
07035 break;
07036 }
07037
07038 case HttpTransact::SM_ACTION_INTERNAL_100_RESPONSE:
07039 {
07040 setup_100_continue_transfer();
07041 break;
07042 }
07043
07044 case HttpTransact::SM_ACTION_SERVER_READ:
07045 {
07046 t_state.source = HttpTransact::SOURCE_HTTP_ORIGIN_SERVER;
07047
07048 if (transform_info.vc) {
07049 ink_assert(t_state.hdr_info.client_response.valid() == 0);
07050 ink_assert((t_state.hdr_info.transform_response.valid()? true : false) == true);
07051 HttpTunnelProducer *p = setup_server_transfer_to_transform();
07052 perform_cache_write_action();
07053 tunnel.tunnel_run(p);
07054 } else {
07055 ink_assert((t_state.hdr_info.client_response.valid()? true : false) == true);
07056 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
07057
07058
07059 if (hooks_set && is_redirect_required() == false) {
07060 do_api_callout_internal();
07061 } else {
07062 do_redirect();
07063 handle_api_return();
07064 }
07065
07066 }
07067 break;
07068 }
07069
07070 case HttpTransact::SM_ACTION_SERVE_FROM_CACHE:
07071 {
07072 ink_assert(t_state.cache_info.action == HttpTransact::CACHE_DO_SERVE ||
07073 t_state.cache_info.action == HttpTransact::CACHE_DO_SERVE_AND_DELETE ||
07074 t_state.cache_info.action == HttpTransact::CACHE_DO_SERVE_AND_UPDATE);
07075 release_server_session(true);
07076 t_state.source = HttpTransact::SOURCE_CACHE;
07077
07078 if (transform_info.vc) {
07079 ink_assert(t_state.hdr_info.client_response.valid() == 0);
07080 ink_assert((t_state.hdr_info.transform_response.valid()? true : false) == true);
07081 t_state.hdr_info.cache_response.create(HTTP_TYPE_RESPONSE);
07082 t_state.hdr_info.cache_response.copy(&t_state.hdr_info.transform_response);
07083
07084 HttpTunnelProducer *p = setup_cache_transfer_to_transform();
07085 perform_cache_write_action();
07086 tunnel.tunnel_run(p);
07087 } else {
07088 ink_assert((t_state.hdr_info.client_response.valid()? true : false) == true);
07089 t_state.hdr_info.cache_response.create(HTTP_TYPE_RESPONSE);
07090 t_state.hdr_info.cache_response.copy(&t_state.hdr_info.client_response);
07091
07092 perform_cache_write_action();
07093 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
07094
07095
07096 if (hooks_set && is_redirect_required() == false) {
07097 do_api_callout_internal();
07098 } else {
07099 do_redirect();
07100 handle_api_return();
07101 }
07102 }
07103 break;
07104 }
07105
07106 case HttpTransact::SM_ACTION_CACHE_ISSUE_WRITE:
07107 {
07108 ink_assert(cache_sm.cache_write_vc == NULL);
07109 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_cache_open_write);
07110
07111 do_cache_prepare_write();
07112 break;
07113
07114 }
07115
07116 case HttpTransact::SM_ACTION_INTERNAL_CACHE_WRITE:
07117 {
07118 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
07119 do_api_callout();
07120 break;
07121 }
07122
07123 case HttpTransact::SM_ACTION_INTERNAL_CACHE_NOOP:
07124 {
07125 if (server_entry == NULL || server_entry->in_tunnel == false) {
07126 release_server_session();
07127 }
07128
07129
07130
07131 if (t_state.api_next_action == HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR) {
07132 handle_api_return();
07133 } else {
07134 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
07135 do_api_callout();
07136 }
07137 break;
07138 }
07139
07140 case HttpTransact::SM_ACTION_INTERNAL_CACHE_DELETE:
07141 {
07142
07143
07144 cache_sm.end_both();
07145 do_cache_delete_all_alts(NULL);
07146
07147 release_server_session();
07148 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
07149 do_api_callout();
07150 break;
07151 }
07152
07153 case HttpTransact::SM_ACTION_INTERNAL_CACHE_UPDATE_HEADERS:
07154 {
07155 issue_cache_update();
07156 cache_sm.close_read();
07157
07158 release_server_session();
07159 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
07160 do_api_callout();
07161 break;
07162
07163 }
07164
07165 case HttpTransact::SM_ACTION_SEND_ERROR_CACHE_NOOP:
07166 {
07167 setup_error_transfer();
07168 break;
07169 }
07170
07171
07172 case HttpTransact::SM_ACTION_INTERNAL_REQUEST:
07173 {
07174 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_handle_stat_page);
07175 Action *action_handle = statPagesManager.handle_http(this, &t_state.hdr_info.client_request);
07176
07177 if (action_handle != ACTION_RESULT_DONE) {
07178 pending_action = action_handle;
07179 historical_action = pending_action;
07180 }
07181
07182 break;
07183 }
07184
07185 case HttpTransact::SM_ACTION_ORIGIN_SERVER_RR_MARK_DOWN:
07186 {
07187 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_mark_os_down);
07188
07189 ink_assert(t_state.dns_info.looking_up == HttpTransact::ORIGIN_SERVER);
07190
07191
07192
07193
07194 HttpSM::do_hostdb_update_if_necessary();
07195
07196 do_hostdb_lookup();
07197 break;
07198 }
07199
07200 case HttpTransact::SM_ACTION_SSL_TUNNEL:
07201 {
07202 setup_blind_tunnel(true);
07203 break;
07204 }
07205
07206 case HttpTransact::SM_ACTION_ORIGIN_SERVER_RAW_OPEN:{
07207 if (congestionControlEnabled && (t_state.congest_saved_next_action == HttpTransact::SM_ACTION_UNDEFINED)) {
07208 t_state.congest_saved_next_action = HttpTransact::SM_ACTION_ORIGIN_SERVER_RAW_OPEN;
07209 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_congestion_control_lookup);
07210 if (!do_congestion_control_lookup())
07211 break;
07212 }
07213
07214 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_raw_http_server_open);
07215
07216 ink_assert(server_entry == NULL);
07217 do_http_server_open(true);
07218 break;
07219 }
07220
07221 case HttpTransact::SM_ACTION_ICP_QUERY:
07222 {
07223 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_icp_lookup);
07224 do_icp_lookup();
07225 break;
07226 }
07227
07228 case HttpTransact::SM_ACTION_CACHE_ISSUE_WRITE_TRANSFORM:
07229 {
07230 ink_assert(t_state.cache_info.transform_action == HttpTransact::CACHE_PREPARE_TO_WRITE);
07231
07232 if (transform_cache_sm.cache_write_vc) {
07233
07234
07235 ink_assert(cache_sm.cache_write_vc == NULL);
07236 ink_assert(t_state.api_info.cache_untransformed == false);
07237 t_state.cache_info.write_lock_state = HttpTransact::CACHE_WL_SUCCESS;
07238 call_transact_and_set_next_state(NULL);
07239 } else {
07240 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::state_cache_open_write);
07241
07242 do_cache_prepare_write_transform();
07243 }
07244 break;
07245 }
07246
07247 case HttpTransact::SM_ACTION_TRANSFORM_READ:
07248 {
07249 t_state.api_next_action = HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR;
07250 do_api_callout();
07251 break;
07252 }
07253
07254 case HttpTransact::SM_ACTION_READ_PUSH_HDR:
07255 {
07256 setup_push_read_response_header();
07257 break;
07258 }
07259
07260 case HttpTransact::SM_ACTION_STORE_PUSH_BODY:
07261 {
07262 setup_push_transfer_to_cache();
07263 tunnel.tunnel_run();
07264 break;
07265 }
07266
07267 case HttpTransact::SM_ACTION_CACHE_PREPARE_UPDATE:
07268 {
07269 ink_assert(t_state.api_update_cached_object == HttpTransact::UPDATE_CACHED_OBJECT_CONTINUE);
07270 do_cache_prepare_update();
07271 break;
07272 }
07273 case HttpTransact::SM_ACTION_CACHE_ISSUE_UPDATE:
07274 {
07275 if (t_state.api_update_cached_object == HttpTransact::UPDATE_CACHED_OBJECT_ERROR) {
07276 t_state.cache_info.object_read = NULL;
07277 cache_sm.close_read();
07278 }
07279 issue_cache_update();
07280 call_transact_and_set_next_state(NULL);
07281 break;
07282 }
07283
07284 #ifdef PROXY_DRAIN
07285 case HttpTransact::SM_ACTION_DRAIN_REQUEST_BODY:
07286 {
07287 do_drain_request_body();
07288 break;
07289 }
07290 #endif
07291
07292 case HttpTransact::SM_ACTION_CONTINUE:
07293 {
07294 ink_release_assert(!"Not implemented");
07295 }
07296
07297 default:
07298 {
07299 ink_release_assert("!Unknown next action");
07300 }
07301 }
07302 }
07303
07304
07305 void
07306 clear_http_handler_times()
07307 {
07308 }
07309
07310
07311 bool
07312 HttpSM::do_congestion_control_lookup()
07313 {
07314 ink_assert(pending_action == NULL);
07315
07316 Action *congestion_control_action_handle = get_congest_entry(this, &t_state.request_data, &t_state.pCongestionEntry);
07317 if (congestion_control_action_handle != ACTION_RESULT_DONE) {
07318 pending_action = congestion_control_action_handle;
07319 historical_action = pending_action;
07320 return false;
07321 }
07322 return true;
07323 }
07324
07325 int
07326 HttpSM::state_congestion_control_lookup(int event, void *data)
07327 {
07328 STATE_ENTER(&HttpSM::state_congestion_control_lookup, event);
07329 if (event == CONGESTION_EVENT_CONTROL_LOOKUP_DONE) {
07330 pending_action = NULL;
07331 t_state.next_action = t_state.congest_saved_next_action;
07332 t_state.transact_return_point = NULL;
07333 set_next_state();
07334 } else {
07335 if (pending_action != NULL) {
07336 pending_action->cancel();
07337 pending_action = NULL;
07338 }
07339 if (t_state.congest_saved_next_action == HttpTransact::SM_ACTION_ORIGIN_SERVER_OPEN) {
07340 return state_http_server_open(event, data);
07341 } else if (t_state.congest_saved_next_action == HttpTransact::SM_ACTION_ORIGIN_SERVER_RAW_OPEN) {
07342 return state_raw_http_server_open(event, data);
07343 }
07344 }
07345 return 0;
07346 }
07347
07348
07349
07350
07351 void
07352 HttpSM::do_redirect()
07353 {
07354 DebugSM("http_redirect", "[HttpSM::do_redirect]");
07355 if (!enable_redirection || redirection_tries >= HttpConfig::m_master.number_of_redirections) {
07356 tunnel.deallocate_redirect_postdata_buffers();
07357 return;
07358 }
07359
07360
07361 if (is_redirect_required()) {
07362 if (redirect_url != NULL || t_state.hdr_info.client_response.field_find(MIME_FIELD_LOCATION, MIME_LEN_LOCATION)) {
07363 if (Log::transaction_logging_enabled() && t_state.api_info.logging_enabled) {
07364 LogAccessHttp accessor(this);
07365 if (redirect_url == NULL) {
07366 if (t_state.squid_codes.log_code == SQUID_LOG_TCP_HIT)
07367 t_state.squid_codes.log_code = SQUID_LOG_TCP_HIT_REDIRECT;
07368 else
07369 t_state.squid_codes.log_code = SQUID_LOG_TCP_MISS_REDIRECT;
07370 } else {
07371 if (t_state.squid_codes.log_code == SQUID_LOG_TCP_HIT)
07372 t_state.squid_codes.log_code = SQUID_LOG_TCP_HIT_X_REDIRECT;
07373 else
07374 t_state.squid_codes.log_code = SQUID_LOG_TCP_MISS_X_REDIRECT;
07375 }
07376
07377 int ret = Log::access(&accessor);
07378
07379 if (ret & Log::FULL) {
07380 DebugSM("http", "[update_stats] Logging system indicates FULL.");
07381 }
07382 if (ret & Log::FAIL) {
07383 Log::error("failed to log transaction for at least one log object");
07384 }
07385 }
07386
07387 if (redirect_url != NULL) {
07388 redirect_request(redirect_url, redirect_url_len);
07389 ats_free((void*)redirect_url);
07390 redirect_url = NULL;
07391 redirect_url_len = 0;
07392 HTTP_INCREMENT_DYN_STAT(http_total_x_redirect_stat);
07393 }
07394 else {
07395
07396 int redir_len;
07397 char *redir_url =
07398 (char *) t_state.hdr_info.client_response.value_get(MIME_FIELD_LOCATION, MIME_LEN_LOCATION, &redir_len);
07399 redirect_request(redir_url, redir_len);
07400 }
07401
07402 } else {
07403 enable_redirection = false;
07404 }
07405 } else {
07406 enable_redirection = false;
07407 }
07408
07409 }
07410
07411 void
07412 HttpSM::redirect_request(const char *redirect_url, const int redirect_len)
07413 {
07414 DebugSM("http_redirect", "[HttpSM::redirect_request]");
07415
07416 HTTPHdr & clientRequestHeader = t_state.hdr_info.client_request;
07417 URL & clientUrl = *clientRequestHeader.url_get();
07418 if (!clientUrl.valid()) {
07419 return;
07420 }
07421
07422 t_state.redirect_info.redirect_in_process = true;
07423
07424
07425 URL & redirectUrl = t_state.redirect_info.redirect_url;
07426 if (!redirectUrl.valid()) {
07427 redirectUrl.create(NULL);
07428 }
07429
07430
07431 t_state.redirect_info.redirect_url.path_set(NULL, 0);
07432
07433
07434 redirectUrl.parse(redirect_url, redirect_len);
07435
07436
07437 URL & origUrl = t_state.redirect_info.original_url;
07438 if (!origUrl.valid()) {
07439 origUrl.create(NULL);
07440 origUrl.copy(&clientUrl);
07441 }
07442
07443 clientUrl.copy(&redirectUrl);
07444
07445
07446 if (t_state.hdr_info.client_response.valid()) {
07447
07448 t_state.hdr_info.client_response.destroy();
07449 }
07450
07451
07452 bool valid_origHost = true;
07453 int origHost_len, origMethod_len;
07454 char* tmpOrigHost = (char *) t_state.hdr_info.server_request.value_get(MIME_FIELD_HOST, MIME_LEN_HOST, &origHost_len);
07455 char origHost[origHost_len + 1];
07456
07457 if (tmpOrigHost)
07458 memcpy(origHost, tmpOrigHost, origHost_len);
07459 else
07460 valid_origHost = false;
07461
07462 origHost[origHost_len] = '\0';
07463 int origPort = t_state.hdr_info.server_request.port_get();
07464
07465 char *tmpOrigMethod = (char *) t_state.hdr_info.server_request.method_get(&origMethod_len);
07466 char origMethod[origMethod_len + 1];
07467
07468 if (tmpOrigMethod)
07469 memcpy(origMethod, tmpOrigMethod, origMethod_len);
07470 else
07471 valid_origHost = false;
07472
07473 int scheme = t_state.next_hop_scheme;
07474 int scheme_len = hdrtoken_index_to_length(scheme);
07475 const char* next_hop_scheme = hdrtoken_index_to_wks(scheme);
07476 char scheme_str[scheme_len+1];
07477
07478 if (next_hop_scheme)
07479 memcpy(scheme_str, next_hop_scheme, scheme_len);
07480 else
07481 valid_origHost = false;
07482
07483 t_state.hdr_info.server_request.destroy();
07484
07485 t_state.api_release_server_session = true;
07486 t_state.parent_result.r = PARENT_UNDEFINED;
07487 t_state.request_sent_time = 0;
07488 t_state.response_received_time = 0;
07489 t_state.cache_info.write_lock_state = HttpTransact::CACHE_WL_INIT;
07490 t_state.next_action = HttpTransact::SM_ACTION_REDIRECT_READ;
07491
07492 t_state.dns_info.lookup_success = false;
07493 t_state.force_dns = false;
07494
07495 bool noPortInHost = HttpConfig::m_master.redirection_host_no_port;
07496
07497
07498
07499 if (t_state.hdr_info.client_request.presence(MIME_PRESENCE_HOST)) {
07500 int host_len;
07501 const char *host = clientUrl.host_get(&host_len);
07502
07503 if (host != NULL) {
07504 int port = clientUrl.port_get();
07505 char buf[host_len + 7];
07506
07507 int redirectSchemeLen;
07508 const char* redirectScheme = clientUrl.scheme_get(&redirectSchemeLen);
07509 if (redirectScheme == NULL) {
07510 clientUrl.scheme_set(scheme_str, scheme_len);
07511 DebugSM("http_redirect", "[HttpSM::redirect_request] hsot without scheme %s", buf);
07512 }
07513
07514 if (noPortInHost) {
07515 int redirectSchemeIdx = clientUrl.scheme_get_wksidx();
07516
07517 bool defaultPort = (((redirectSchemeIdx == URL_WKSIDX_HTTP) && (port == 80)) ||
07518 ((redirectSchemeIdx == URL_WKSIDX_HTTPS) && (port == 443)));
07519
07520 if (!defaultPort) noPortInHost = false;
07521 }
07522
07523 ink_strlcpy(buf, host, host_len + 1);
07524
07525 if (!noPortInHost) {
07526 char port_buf[6];
07527 buf[host_len++] = ':';
07528
07529 host_len += ink_small_itoa(port, port_buf, sizeof(port_buf));
07530 ink_strlcat(buf, port_buf, sizeof(buf));
07531 }
07532
07533 t_state.hdr_info.client_request.m_target_cached = false;
07534 t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, host_len);
07535 } else {
07536
07537 if (valid_origHost)
07538 {
07539
07540 DebugSM("http_redirect", "[HttpSM::redirect_request] keeping client request host %s://%s", next_hop_scheme, origHost);
07541 char* origHost1 = strtok(origHost, ":");
07542 origHost_len = strlen(origHost1);
07543 int origHostPort_len = origHost_len;
07544 char buf[origHostPort_len + 7];
07545 ink_strlcpy(buf, origHost1, origHost_len + 1);
07546
07547 if (noPortInHost) {
07548 int redirectSchemeIdx = t_state.next_hop_scheme;
07549
07550 bool defaultPort = (((redirectSchemeIdx == URL_WKSIDX_HTTP) && (origPort == 80)) ||
07551 ((redirectSchemeIdx == URL_WKSIDX_HTTPS) && (origPort == 443)));
07552
07553 if (!defaultPort) noPortInHost = false;
07554 }
07555
07556 if (!noPortInHost) {
07557 char port_buf[6];
07558 buf[origHostPort_len++] = ':';
07559 origHostPort_len += ink_small_itoa(origPort, port_buf, sizeof(port_buf));
07560 ink_strlcat(buf, port_buf, sizeof(buf));
07561 }
07562
07563 url_nuke_proxy_stuff(clientUrl.m_url_impl);
07564 url_nuke_proxy_stuff(t_state.hdr_info.client_request.m_url_cached.m_url_impl);
07565 t_state.hdr_info.client_request.method_set(origMethod, origMethod_len);
07566 if (noPortInHost)
07567 t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, origHost_len);
07568 else
07569 t_state.hdr_info.client_request.value_set(MIME_FIELD_HOST, MIME_LEN_HOST, buf, origHostPort_len);
07570 t_state.hdr_info.client_request.m_target_cached = false;
07571 clientUrl.scheme_set(scheme_str, scheme_len);
07572 } else {
07573
07574 t_state.hdr_info.client_request.field_delete(MIME_FIELD_HOST, MIME_LEN_HOST);
07575 }
07576 }
07577
07578 }
07579
07580 DUMP_HEADER("http_hdrs", &t_state.hdr_info.client_request, sm_id, "Framed Client Request..checking");
07581 }
07582
07583 void
07584 HttpSM::set_http_schedule(Continuation *contp)
07585 {
07586 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::get_http_schedule);
07587 schedule_cont = contp;
07588 }
07589
07590 int
07591 HttpSM::get_http_schedule(int event, void * )
07592 {
07593 bool plugin_lock;
07594 Ptr <ProxyMutex> plugin_mutex;
07595 if (schedule_cont->mutex) {
07596 plugin_mutex = schedule_cont->mutex;
07597 plugin_lock = MUTEX_TAKE_TRY_LOCK(schedule_cont->mutex, mutex->thread_holding);
07598
07599 if (!plugin_lock) {
07600 HTTP_SM_SET_DEFAULT_HANDLER(&HttpSM::get_http_schedule);
07601 ink_assert(pending_action == NULL);
07602 pending_action = mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
07603 return 0;
07604 }
07605 } else {
07606 plugin_lock = false;
07607 }
07608
07609
07610 schedule_cont->handleEvent ( event, this);
07611 if (plugin_lock) {
07612 Mutex_unlock(plugin_mutex, mutex->thread_holding);
07613 }
07614
07615 return 0;
07616 }
07617
07618 bool
07619 HttpSM::set_server_session_private(bool private_session)
07620 {
07621 if (server_session != NULL) {
07622 server_session->private_session = private_session;
07623 return true;
07624 }
07625 return false;
07626 }
07627
07628 inline bool
07629 HttpSM::is_private()
07630 {
07631 bool res = false;
07632 if (server_session) {
07633 res = server_session->private_session;
07634 } else if (ua_session) {
07635 HttpServerSession * ss = ua_session->get_server_session();
07636 if (ss) {
07637 res = ss->private_session;
07638 }
07639 }
07640 return res;
07641 }
07642
07643
07644 inline bool
07645 HttpSM::is_redirect_required()
07646 {
07647 bool redirect_required = (enable_redirection && (redirection_tries <= HttpConfig::m_master.number_of_redirections));
07648
07649 DebugSM("http_redirect", "is_redirect_required %u", redirect_required);
07650
07651 if (redirect_required == true) {
07652 HTTPStatus status = t_state.hdr_info.client_response.status_get();
07653
07654 switch (status)
07655 {
07656 case HTTP_STATUS_MULTIPLE_CHOICES:
07657 case HTTP_STATUS_MOVED_PERMANENTLY:
07658 case HTTP_STATUS_MOVED_TEMPORARILY:
07659 case HTTP_STATUS_SEE_OTHER:
07660 case HTTP_STATUS_USE_PROXY:
07661 case HTTP_STATUS_TEMPORARY_REDIRECT:
07662 redirect_required = true;
07663 break;
07664 default:
07665 redirect_required = false;
07666 break;
07667 }
07668
07669
07670 if (redirect_url != NULL) {
07671 redirect_required = true;
07672 }
07673 }
07674 return redirect_required;
07675 }