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