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
00026
00027
00028
00029
00030
00031
00032
00033 #ifndef _HTTP_SM_H_
00034 #define _HTTP_SM_H_
00035
00036 #include "libts.h"
00037 #include "P_EventSystem.h"
00038 #include "HttpCacheSM.h"
00039 #include "HttpTransact.h"
00040 #include "HttpTunnel.h"
00041 #include "InkAPIInternal.h"
00042 #include "StatSystem.h"
00043 #include "HttpClientSession.h"
00044 #include "HdrUtils.h"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #define LAZY_BUF_ALLOC
00059
00060 #define HTTP_API_CONTINUE (INK_API_EVENT_EVENTS_START + 0)
00061 #define HTTP_API_ERROR (INK_API_EVENT_EVENTS_START + 1)
00062
00063
00064
00065 static size_t const HTTP_HEADER_BUFFER_SIZE_INDEX = CLIENT_CONNECTION_FIRST_READ_BUFFER_SIZE_INDEX;
00066
00067
00068
00069
00070
00071
00072 static size_t const HTTP_SERVER_RESP_HDR_BUFFER_INDEX = BUFFER_SIZE_INDEX_8K;
00073
00074 class HttpServerSession;
00075 class AuthHttpAdapter;
00076
00077 class HttpSM;
00078 typedef int (HttpSM::*HttpSMHandler) (int event, void *data);
00079
00080 enum HttpVC_t
00081 { HTTP_UNKNOWN = 0, HTTP_UA_VC, HTTP_SERVER_VC,
00082 HTTP_TRANSFORM_VC, HTTP_CACHE_READ_VC,
00083 HTTP_CACHE_WRITE_VC, HTTP_RAW_SERVER_VC
00084 };
00085
00086 enum BackgroundFill_t
00087 {
00088 BACKGROUND_FILL_NONE = 0,
00089 BACKGROUND_FILL_STARTED,
00090 BACKGROUND_FILL_ABORTED,
00091 BACKGROUND_FILL_COMPLETED
00092 };
00093
00094 extern ink_mutex debug_sm_list_mutex;
00095
00096 struct HttpVCTableEntry
00097 {
00098 VConnection *vc;
00099 MIOBuffer *read_buffer;
00100 MIOBuffer *write_buffer;
00101 VIO *read_vio;
00102 VIO *write_vio;
00103 HttpSMHandler vc_handler;
00104 HttpVC_t vc_type;
00105 bool eos;
00106 bool in_tunnel;
00107 };
00108
00109 struct HttpVCTable
00110 {
00111 static const int vc_table_max_entries = 4;
00112 HttpVCTable();
00113
00114 HttpVCTableEntry *new_entry();
00115 HttpVCTableEntry *find_entry(VConnection *);
00116 HttpVCTableEntry *find_entry(VIO *);
00117 void remove_entry(HttpVCTableEntry *);
00118 void cleanup_entry(HttpVCTableEntry *);
00119 void cleanup_all();
00120 bool is_table_clear() const;
00121
00122 private:
00123 HttpVCTableEntry vc_table[vc_table_max_entries];
00124 };
00125
00126 inline bool
00127 HttpVCTable::is_table_clear() const
00128 {
00129 for (int i = 0; i < vc_table_max_entries; i++) {
00130 if (vc_table[i].vc != NULL) {
00131 return false;
00132 }
00133 }
00134 return true;
00135 }
00136
00137 struct HttpTransformInfo
00138 {
00139 HttpVCTableEntry *entry;
00140 VConnection *vc;
00141
00142 HttpTransformInfo():entry(NULL), vc(NULL)
00143 {
00144 }
00145 };
00146 #define HISTORY_SIZE 64
00147
00148 enum
00149 {
00150 HTTP_SM_MAGIC_ALIVE = 0x0000FEED,
00151 HTTP_SM_MAGIC_DEAD = 0xDEADFEED
00152 };
00153
00154 enum
00155 {
00156 HTTP_SM_POST_UNKNOWN = 0,
00157 HTTP_SM_POST_UA_FAIL = 1,
00158 HTTP_SM_POST_SERVER_FAIL = 2,
00159 HTTP_SM_POST_SUCCESS = 3
00160 };
00161
00162 enum
00163 {
00164 HTTP_SM_TRANSFORM_OPEN = 0,
00165 HTTP_SM_TRANSFORM_CLOSED = 1,
00166 HTTP_SM_TRANSFORM_FAIL = 2
00167 };
00168
00169 enum HttpApiState_t
00170 {
00171 HTTP_API_NO_CALLOUT,
00172 HTTP_API_IN_CALLOUT,
00173 HTTP_API_DEFERED_CLOSE,
00174 HTTP_API_DEFERED_SERVER_ERROR
00175 };
00176
00177
00178 enum HttpPluginTunnel_t
00179 {
00180 HTTP_NO_PLUGIN_TUNNEL = 0,
00181 HTTP_PLUGIN_AS_SERVER,
00182 HTTP_PLUGIN_AS_INTERCEPT
00183 };
00184
00185 class CoreUtils;
00186 class PluginVCCore;
00187
00188 class HttpSM: public Continuation
00189 {
00190 friend class HttpPagesHandler;
00191 friend class CoreUtils;
00192 public:
00193 HttpSM();
00194 void cleanup();
00195 virtual void destroy();
00196
00197 static HttpSM *allocate();
00198 HttpCacheSM & get_cache_sm();
00199 HttpVCTableEntry *get_ua_entry();
00200 static void _instantiate_func(HttpSM * prototype, HttpSM * new_instance);
00201 static void _make_scatter_list(HttpSM * prototype);
00202
00203 void init();
00204
00205 void attach_client_session(HttpClientSession * client_vc_arg, IOBufferReader * buffer_reader);
00206
00207
00208
00209
00210 void attach_server_session(HttpServerSession * s);
00211
00212
00213
00214
00215 void do_hostdb_update_if_necessary();
00216
00217
00218
00219
00220 void do_range_setup_if_necessary();
00221
00222 void do_range_parse(MIMEField *range_field);
00223 void calculate_output_cl(int64_t, int64_t);
00224 void parse_range_and_compare(MIMEField*, int64_t);
00225
00226
00227
00228 void set_ua_half_close_flag();
00229
00230
00231
00232
00233
00234
00235 void process_hostdb_info(HostDBInfo * r);
00236 void process_srv_info(HostDBInfo * r);
00237
00238
00239 VConnection *do_transform_open();
00240 VConnection *do_post_transform_open();
00241
00242
00243
00244 int state_api_callback(int event, void *data);
00245 int state_api_callout(int event, void *data);
00246
00247
00248 HttpTunnel *get_tunnel()
00249 {
00250 return &tunnel;
00251 };
00252
00253
00254 void dump_state_on_assert();
00255 void dump_state_hdr(HTTPHdr *h, const char *s);
00256
00257
00258 void txn_hook_append(TSHttpHookID id, INKContInternal * cont);
00259 void txn_hook_prepend(TSHttpHookID id, INKContInternal * cont);
00260 APIHook *txn_hook_get(TSHttpHookID id);
00261
00262 void add_history_entry(const char *fileline, int event, int reentrant);
00263 void add_cache_sm();
00264 bool is_private();
00265 bool is_redirect_required();
00266
00267 int64_t sm_id;
00268 unsigned int magic;
00269
00270
00271 bool enable_redirection;
00272 char *redirect_url;
00273 int redirect_url_len;
00274 int redirection_tries;
00275 int64_t transfered_bytes;
00276 bool post_failed;
00277 bool debug_on;
00278
00279
00280 HttpPluginTunnel_t plugin_tunnel_type;
00281 PluginVCCore *plugin_tunnel;
00282
00283 HttpTransact::State t_state;
00284
00285 protected:
00286 int reentrancy_count;
00287
00288 struct History
00289 {
00290 const char *fileline;
00291 unsigned short event;
00292 short reentrancy;
00293 };
00294 History history[HISTORY_SIZE];
00295 int history_pos;
00296
00297 HttpTunnel tunnel;
00298
00299 HttpVCTable vc_table;
00300
00301 HttpVCTableEntry *ua_entry;
00302 void remove_ua_entry();
00303
00304 public:
00305 HttpClientSession *ua_session;
00306 BackgroundFill_t background_fill;
00307
00308 void set_http_schedule(Continuation *);
00309 int get_http_schedule(int event, void *data);
00310
00311 protected:
00312 IOBufferReader * ua_buffer_reader;
00313 IOBufferReader * ua_raw_buffer_reader;
00314
00315 HttpVCTableEntry *server_entry;
00316 HttpServerSession *server_session;
00317 int shared_session_retries;
00318 IOBufferReader *server_buffer_reader;
00319 void remove_server_entry();
00320
00321 HttpTransformInfo transform_info;
00322 HttpTransformInfo post_transform_info;
00323
00324
00325 bool has_active_plugin_agents;
00326
00327 HttpCacheSM cache_sm;
00328 HttpCacheSM transform_cache_sm;
00329 HttpCacheSM *second_cache_sm;
00330
00331 HttpSMHandler default_handler;
00332 Action *pending_action;
00333 Action *historical_action;
00334 Continuation *schedule_cont;
00335
00336 HTTPParser http_parser;
00337 void start_sub_sm();
00338
00339 int main_handler(int event, void *data);
00340 int tunnel_handler(int event, void *data);
00341 int tunnel_handler_push(int event, void *data);
00342 int tunnel_handler_post(int event, void *data);
00343
00344
00345 int tunnel_handler_for_partial_post(int event, void *data);
00346
00347 void tunnel_handler_post_or_put(HttpTunnelProducer * p);
00348
00349 int tunnel_handler_100_continue(int event, void *data);
00350 int tunnel_handler_cache_fill(int event, void *data);
00351 #ifdef PROXY_DRAIN
00352 int state_drain_client_request_body(int event, void *data);
00353 #endif
00354 int state_read_client_request_header(int event, void *data);
00355 int state_watch_for_client_abort(int event, void *data);
00356 int state_read_push_response_header(int event, void *data);
00357 int state_srv_lookup(int event, void *data);
00358 int state_hostdb_lookup(int event, void *data);
00359 int state_hostdb_reverse_lookup(int event, void *data);
00360 int state_mark_os_down(int event, void *data);
00361 int state_handle_stat_page(int event, void *data);
00362 int state_icp_lookup(int event, void *data);
00363 int state_auth_callback(int event, void *data);
00364 int state_add_to_list(int event, void *data);
00365 int state_remove_from_list(int event, void *data);
00366 int state_congestion_control_lookup(int event, void *data);
00367
00368
00369 int state_remap_request(int event, void *data);
00370 void do_remap_request(bool);
00371
00372
00373 int state_cache_open_read(int event, void *data);
00374 int state_cache_open_write(int event, void *data);
00375
00376
00377 int state_http_server_open(int event, void *data);
00378 int state_raw_http_server_open(int event, void *data);
00379 int state_send_server_request_header(int event, void *data);
00380 int state_acquire_server_read(int event, void *data);
00381 int state_read_server_response_header(int event, void *data);
00382
00383
00384 int state_request_wait_for_transform_read(int event, void *data);
00385 int state_response_wait_for_transform_read(int event, void *data);
00386 int state_common_wait_for_transform_read(HttpTransformInfo * t_info, HttpSMHandler tunnel_handler, int event, void *data);
00387
00388
00389 int tunnel_handler_server(int event, HttpTunnelProducer * p);
00390 int tunnel_handler_ua(int event, HttpTunnelConsumer * c);
00391 int tunnel_handler_ua_push(int event, HttpTunnelProducer * p);
00392 int tunnel_handler_100_continue_ua(int event, HttpTunnelConsumer * c);
00393 int tunnel_handler_cache_write(int event, HttpTunnelConsumer * c);
00394 int tunnel_handler_cache_read(int event, HttpTunnelProducer * p);
00395 int tunnel_handler_post_ua(int event, HttpTunnelProducer * c);
00396 int tunnel_handler_post_server(int event, HttpTunnelConsumer * c);
00397 int tunnel_handler_ssl_producer(int event, HttpTunnelProducer * p);
00398 int tunnel_handler_ssl_consumer(int event, HttpTunnelConsumer * p);
00399 int tunnel_handler_transform_write(int event, HttpTunnelConsumer * c);
00400 int tunnel_handler_transform_read(int event, HttpTunnelProducer * p);
00401 int tunnel_handler_plugin_agent(int event, HttpTunnelConsumer * c);
00402
00403 void do_hostdb_lookup();
00404 void do_hostdb_reverse_lookup();
00405 void do_cache_lookup_and_read();
00406 void do_http_server_open(bool raw = false);
00407 void do_setup_post_tunnel(HttpVC_t to_vc_type);
00408 void do_cache_prepare_write();
00409 void do_cache_prepare_write_transform();
00410 void do_cache_prepare_update();
00411 void do_cache_prepare_action(HttpCacheSM * c_sm,
00412 CacheHTTPInfo * object_read_info, bool retry, bool allow_multiple = false);
00413 void do_cache_delete_all_alts(Continuation * cont);
00414 void do_icp_lookup();
00415 void do_auth_callout();
00416 void do_api_callout();
00417 void do_api_callout_internal();
00418 void do_redirect();
00419 void redirect_request(const char *redirect_url, const int redirect_len);
00420 #ifdef PROXY_DRAIN
00421 void do_drain_request_body();
00422 #endif
00423
00424 bool do_congestion_control_lookup();
00425
00426 virtual void handle_api_return();
00427 void handle_server_setup_error(int event, void *data);
00428 void handle_http_server_open();
00429 void handle_post_failure();
00430 void mark_host_failure(HostDBInfo * info, time_t time_down);
00431 void mark_server_down_on_client_abort();
00432 void release_server_session(bool serve_from_cache = false);
00433 void set_ua_abort(HttpTransact::AbortState_t ua_abort, int event);
00434 int write_header_into_buffer(HTTPHdr * h, MIOBuffer * b);
00435 int write_response_header_into_buffer(HTTPHdr * h, MIOBuffer * b);
00436 void setup_blind_tunnel_port();
00437 void setup_client_header_nca();
00438 void setup_client_read_request_header();
00439 void setup_push_read_response_header();
00440 void setup_server_read_response_header();
00441 void setup_cache_lookup_complete_api();
00442 void setup_server_send_request();
00443 void setup_server_send_request_api();
00444 void setup_server_transfer();
00445 void setup_server_transfer_to_cache_only();
00446 void setup_cache_read_transfer();
00447 void setup_internal_transfer(HttpSMHandler handler);
00448 void setup_error_transfer();
00449 void setup_100_continue_transfer();
00450 void setup_push_transfer_to_cache();
00451 void setup_transform_to_server_transfer();
00452 void setup_cache_write_transfer(HttpCacheSM * c_sm,
00453 VConnection * source_vc, HTTPInfo * store_info, int64_t skip_bytes, const char *name);
00454 void issue_cache_update();
00455 void perform_cache_write_action();
00456 void perform_transform_cache_write_action();
00457 void perform_nca_cache_action();
00458 void setup_blind_tunnel(bool send_response_hdr);
00459 HttpTunnelProducer *setup_server_transfer_to_transform();
00460 HttpTunnelProducer *setup_transfer_from_transform();
00461 HttpTunnelProducer *setup_cache_transfer_to_transform();
00462 HttpTunnelProducer *setup_transfer_from_transform_to_cache_only();
00463 void setup_plugin_agents(HttpTunnelProducer* p);
00464
00465 HttpTransact::StateMachineAction_t last_action;
00466 int (HttpSM::*m_last_state) (int event, void *data);
00467 virtual void set_next_state();
00468 void call_transact_and_set_next_state(TransactEntryFunc_t f);
00469
00470 bool is_http_server_eos_truncation(HttpTunnelProducer *);
00471 bool is_bg_fill_necessary(HttpTunnelConsumer * c);
00472 int find_server_buffer_size();
00473 int find_http_resp_buffer_size(int64_t cl);
00474 int64_t server_transfer_init(MIOBuffer * buf, int hdr_size);
00475
00476 public:
00477
00478 int client_request_hdr_bytes;
00479 int64_t client_request_body_bytes;
00480 int server_request_hdr_bytes;
00481 int64_t server_request_body_bytes;
00482 int server_response_hdr_bytes;
00483 int64_t server_response_body_bytes;
00484 int client_response_hdr_bytes;
00485 int64_t client_response_body_bytes;
00486 int cache_response_hdr_bytes;
00487 int64_t cache_response_body_bytes;
00488 int pushed_response_hdr_bytes;
00489 int64_t pushed_response_body_bytes;
00490 TransactionMilestones milestones;
00491
00492
00493
00494 char const* plugin_tag;
00495 int64_t plugin_id;
00496
00497
00498
00499
00500 bool hooks_set;
00501
00502 protected:
00503 TSHttpHookID cur_hook_id;
00504 APIHook *cur_hook;
00505
00506
00507
00508 int64_t prev_hook_start_time;
00509
00510 int cur_hooks;
00511 HttpApiState_t callout_state;
00512
00513
00514
00515
00516 HttpAPIHooks api_hooks;
00517
00518
00519
00520
00521 bool terminate_sm;
00522 bool kill_this_async_done;
00523 virtual int kill_this_async_hook(int event, void *data);
00524 void kill_this();
00525 void update_stats();
00526 void transform_cleanup(TSHttpHookID hook, HttpTransformInfo * info);
00527 bool is_transparent_passthrough_allowed();
00528 void plugin_agents_cleanup();
00529
00530 public:
00531 LINK(HttpSM, debug_link);
00532
00533 public:
00534 bool set_server_session_private(bool private_session);
00535 };
00536
00537
00538 inline HttpCacheSM &
00539 HttpSM::get_cache_sm()
00540 {
00541 return cache_sm;
00542 }
00543
00544
00545 inline HttpVCTableEntry *
00546 HttpSM::get_ua_entry()
00547 {
00548 return ua_entry;
00549 }
00550
00551 inline HttpSM *
00552 HttpSM::allocate()
00553 {
00554 extern SparseClassAllocator<HttpSM> httpSMAllocator;
00555 return httpSMAllocator.alloc();
00556 }
00557
00558 inline void
00559 HttpSM::remove_ua_entry()
00560 {
00561 vc_table.remove_entry(ua_entry);
00562 ua_entry = NULL;
00563 }
00564
00565 inline void
00566 HttpSM::remove_server_entry()
00567 {
00568 if (server_entry) {
00569 vc_table.remove_entry(server_entry);
00570 server_entry = NULL;
00571 }
00572 }
00573
00574 inline int
00575 HttpSM::write_response_header_into_buffer(HTTPHdr * h, MIOBuffer * b)
00576 {
00577 if (t_state.client_info.http_version == HTTPVersion(0, 9)) {
00578 return 0;
00579 } else {
00580 return write_header_into_buffer(h, b);
00581 }
00582 }
00583
00584 inline void
00585 HttpSM::add_history_entry(const char *fileline, int event, int reentrant)
00586 {
00587 int pos = history_pos++ % HISTORY_SIZE;
00588 history[pos].fileline = fileline;
00589 history[pos].event = (unsigned short) event;
00590 history[pos].reentrancy = (short) reentrant;
00591 }
00592
00593 inline int
00594 HttpSM::find_server_buffer_size()
00595 {
00596 return find_http_resp_buffer_size(t_state.hdr_info.response_content_length);
00597 }
00598
00599 inline void
00600 HttpSM::txn_hook_append(TSHttpHookID id, INKContInternal * cont)
00601 {
00602 api_hooks.append(id, cont);
00603 hooks_set = 1;
00604 }
00605
00606 inline void
00607 HttpSM::txn_hook_prepend(TSHttpHookID id, INKContInternal * cont)
00608 {
00609 api_hooks.prepend(id, cont);
00610 hooks_set = 1;
00611 }
00612
00613 inline APIHook *
00614 HttpSM::txn_hook_get(TSHttpHookID id)
00615 {
00616 return api_hooks.get(id);
00617 }
00618
00619 inline void
00620 HttpSM::add_cache_sm()
00621 {
00622 if (second_cache_sm == NULL) {
00623 second_cache_sm = new HttpCacheSM;
00624 second_cache_sm->init(this, mutex);
00625 second_cache_sm->set_lookup_url(cache_sm.get_lookup_url());
00626 if (t_state.cache_info.object_read != NULL) {
00627 second_cache_sm->cache_read_vc = cache_sm.cache_read_vc;
00628 cache_sm.cache_read_vc = NULL;
00629 second_cache_sm->read_locked = cache_sm.read_locked;
00630 t_state.cache_info.second_object_read = t_state.cache_info.object_read;
00631 t_state.cache_info.object_read = NULL;
00632 }
00633 }
00634 }
00635
00636 inline bool
00637 HttpSM::is_transparent_passthrough_allowed()
00638 {
00639 return (t_state.client_info.is_transparent &&
00640 ua_session->f_transparent_passthrough &&
00641 ua_session->get_transact_count() == 1);
00642 }
00643
00644 #endif