00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #ifndef _PREFETCH_H_
00025 #define _PREFETCH_H_
00026 
00027 #include <ts/IpMap.h>
00028 #include "TransformInternal.h"
00029 
00030 #ifdef PREFETCH
00031 
00032 #include "Update.h"
00033 #include "api/ts/experimental.h"
00034 
00035 class BlasterUrlList;
00036 class PrefetchUrlBlaster;
00037 class PrefetchBlaster;
00038 extern BlasterUrlList *multicastUrlBlaster;
00039 
00040 struct PrefetchConfiguration
00041 {
00042   int prefetch_enabled;
00043   IpMap ip_map;
00044   struct html_tag *html_tags_table;
00045   struct html_tag *html_attrs_table;
00046 
00047   int local_http_server_port;
00048   int stuffer_port;
00049 
00050   int url_buffer_size;
00051   int url_buffer_timeout;
00052 
00053   TSPrefetchBlastData default_url_blast;
00054   TSPrefetchBlastData default_data_blast;
00055 
00056   int keepalive_timeout;
00057   int push_cached_objects;
00058 
00059   unsigned int max_object_size;
00060 
00061   unsigned int max_recursion;   
00062   unsigned int redirection;     
00063 
00064   TSPrefetchHook pre_parse_hook;
00065   TSPrefetchHook embedded_url_hook;
00066   TSPrefetchHook embedded_obj_hook;
00067 
00068   PrefetchConfiguration() :
00069     prefetch_enabled(0), html_tags_table(0), html_attrs_table(0),
00070         local_http_server_port(0), stuffer_port(0), url_buffer_size(0),
00071         url_buffer_timeout(0), keepalive_timeout(0), push_cached_objects(0),
00072         max_object_size(0), max_recursion(0), redirection(0),
00073         pre_parse_hook(0), embedded_url_hook(0), embedded_obj_hook(0) {
00074   }
00075   int readConfiguration();
00076   void readHtmlTags(int fd, html_tag ** ptags, html_tag ** pattrs);
00077 };
00078 
00079 
00080 class PrefetchUrlEntry: public RefCountObj
00081 {
00082 public:
00083   PrefetchUrlEntry()
00084     : url(0), len(INT_MAX), resp_blaster(0),
00085       object_buf_status(TS_PREFETCH_OBJ_BUF_NOT_NEEDED),
00086       blaster_link(0), hash_link(0)
00087   {
00088     ink_zero(req_ip);
00089     ink_zero(child_ip);
00090     ink_zero(url_multicast_ip);
00091     ink_zero(data_multicast_ip);
00092     refcount_inc();
00093   }
00094 
00095   void init(char *str, INK_MD5 & xmd5)
00096   {
00097     len = strlen(url = str) + 1;
00098     md5 = xmd5;
00099   }
00100   void free();
00101 
00102   PrefetchUrlEntry *assign()
00103   {
00104     refcount_inc();
00105     return this;
00106   };
00107 
00108   char *url;
00109   int len;
00110   INK_MD5 md5;
00111 
00112   PrefetchBlaster *resp_blaster;
00113 
00114   int object_buf_status;
00115 
00116   IpEndpoint req_ip;     
00117   IpEndpoint child_ip;
00118   IpEndpoint url_multicast_ip;
00119   IpEndpoint data_multicast_ip;
00120 
00121   PrefetchUrlEntry *blaster_link;
00122   PrefetchUrlEntry *hash_link;
00123 
00124 private:
00125   
00126   
00127   PrefetchUrlEntry(const PrefetchUrlEntry &)
00128   {
00129   };
00130 };
00131 
00132 extern ClassAllocator<PrefetchUrlEntry> prefetchUrlEntryAllocator;
00133 
00134 inline void
00135 PrefetchUrlEntry::free()
00136 {
00137   if (refcount_dec() == 0) {
00138     ats_free(url);
00139     prefetchUrlEntryAllocator.free(this);
00140   }
00141 }
00142 
00143 class PrefetchTransform:public INKVConnInternal, public RefCountObj
00144 {
00145   enum
00146   { HASH_TABLE_LENGTH = 61   };
00147 public:
00148 
00149     PrefetchTransform(HttpSM * sm, HTTPHdr * resp);
00150    ~PrefetchTransform();
00151   void free()
00152   {
00153     if (refcount_dec() == 0)
00154       delete this;
00155   };
00156   PrefetchTransform *assign()
00157   {
00158     refcount_inc();
00159     return this;
00160   };
00161 
00162   int handle_event(int event, void *edata);
00163   int parse_data(IOBufferReader * reader);
00164   int redirect(HTTPHdr * resp);
00165 
00166   PrefetchUrlEntry *hash_add(char *url);
00167 
00168 public:
00169   MIOBuffer * m_output_buf;
00170   IOBufferReader *m_output_reader;
00171   VIO *m_output_vio;
00172 
00173   HttpSM *m_sm;
00174 
00175   char *url;
00176 
00177   HtmlParser html_parser;
00178 
00179   PrefetchUrlEntry *hash_table[HASH_TABLE_LENGTH];
00180 
00181   BlasterUrlList *udp_url_list;
00182   BlasterUrlList *tcp_url_list;
00183 
00184   const char *domain_start;
00185   const char *domain_end;
00186   const char *host_start;
00187   int host_len;
00188   bool no_dot_in_host;
00189 };
00190 
00191 extern TSPrefetchBlastData const UDP_BLAST_DATA;
00192 extern TSPrefetchBlastData const TCP_BLAST_DATA;
00193 
00194 
00195 class BlasterUrlList:public Continuation
00196 {
00197 
00198   int timeout;                  
00199   Action *action;
00200   int mtu;
00201   TSPrefetchBlastData blast;
00202 
00203   PrefetchUrlEntry *list_head;
00204   int cur_len;
00205 
00206 public:
00207   BlasterUrlList()
00208     : Continuation(), timeout(0), action(0), mtu(0), list_head(0), cur_len(0)
00209   {  }
00210 
00211   void init(TSPrefetchBlastData const& bdata = UDP_BLAST_DATA, int tout = 0, int xmtu = INT_MAX) {
00212     SET_HANDLER((int (BlasterUrlList::*)(int, void *))(&BlasterUrlList::handleEvent));
00213     mutex = new_ProxyMutex();
00214     blast = bdata;
00215     timeout = tout;
00216     mtu = xmtu;
00217   }
00218 
00219   void free();
00220 
00221   int handleEvent(int event, void *data);
00222   void invokeUrlBlaster();
00223 };
00224 
00225 extern ClassAllocator<BlasterUrlList> blasterUrlListAllocator;
00226 
00227 inline void
00228 BlasterUrlList::free()
00229 {
00230   mutex = NULL;
00231   blasterUrlListAllocator.free(this);
00232 }
00233 
00234 class PrefetchUrlBlaster:public Continuation
00235 {
00236 public:
00237   typedef int (PrefetchUrlBlaster::*EventHandler) (int, void *);
00238 
00239     PrefetchUrlBlaster()
00240   : url_head(0), action(0)
00241   {
00242     ink_zero(blast);
00243   }
00244 
00245   void init(PrefetchUrlEntry * list_head, TSPrefetchBlastData const& u_bd = UDP_BLAST_DATA);
00246 
00247   void free();
00248 
00249   PrefetchUrlEntry *url_head;
00250   TSPrefetchBlastData blast;
00251 
00252   Action *action;
00253 
00254   void writeBuffer(MIOBuffer * buf);
00255 
00256   int udpUrlBlaster(int event, void *data);
00257 
00258 };
00259 
00260 extern ClassAllocator<PrefetchUrlBlaster> prefetchUrlBlasterAllocator;
00261 
00262 void
00263 PrefetchUrlBlaster::init(PrefetchUrlEntry * list_head, TSPrefetchBlastData const& u_bd)
00264 {
00265   
00266 
00267   mutex = new_ProxyMutex();
00268 
00269   url_head = list_head;
00270   blast = u_bd;
00271 
00272   MUTEX_LOCK(lock, mutex, this_ethread());
00273 
00274   udpUrlBlaster(SIMPLE_EVENT_EVENTS_START, NULL);
00275 }
00276 
00277 inline void
00278 BlasterUrlList::invokeUrlBlaster()
00279 {
00280   PrefetchUrlBlaster *u_blaster = prefetchUrlBlasterAllocator.alloc();
00281   u_blaster->init(list_head, blast);
00282   list_head = NULL;
00283   cur_len = 0;
00284 }
00285 
00286 class PrefetchBlaster:public Continuation
00287 {
00288 
00289 public:
00290   typedef int (PrefetchBlaster::*EventHandler) (int event, void *data);
00291 
00292     PrefetchBlaster()
00293   : Continuation(), url_ent(0), transform(0), url_list(0), request(0),
00294     cache_http_info(0), buf(0), reader(0), serverVC(0), n_pkts_sent(0), seq_no(0), io_block(0)
00295   {
00296   };
00297   ~PrefetchBlaster() {
00298   };
00299 
00300   int init(PrefetchUrlEntry * entry, HTTPHdr * request, PrefetchTransform * p_trans);
00301 
00302   int handleEvent(int event, void *data);
00303   int bufferObject(int event, void *data);
00304   int blastObject(int event, void *data);
00305   int httpClient(int event, void *data);
00306 
00307   int invokeBlaster();
00308   void initCacheLookupConfig();
00309 
00310   void handleCookieHeaders(HTTPHdr * req_hdr, HTTPHdr * resp_hdr,
00311                            const char *domain_start, const char *domain_end,
00312                            const char *host_start, int host_len, bool no_dot);
00313 
00314   void free();
00315 
00316   PrefetchUrlEntry *url_ent;
00317   PrefetchTransform *transform;
00318   BlasterUrlList *url_list;
00319 
00320   HTTPHdr *request;
00321   CacheHTTPInfo *cache_http_info;
00322 
00323   MIOBuffer *buf;
00324   IOBufferReader *reader;
00325 
00326   VConnection *serverVC;
00327 
00328   TSPrefetchBlastData data_blast;
00329 
00330   CacheLookupHttpConfig cache_lookup_config;
00331 
00332   
00333   uint32_t n_pkts_sent;
00334   uint32_t seq_no;
00335   IOBufferBlock *io_block;
00336 };
00337 
00338 extern ClassAllocator<PrefetchBlaster> prefetchBlasterAllocator;
00339 
00340 
00341 
00342 #define PRELOAD_HEADER_LEN 12   //this is the new header
00343 
00344 #define PRELOAD_HDR_URL_PROMISE_FLAG (0x40000000)
00345 #define PRELOAD_HDR_RESPONSE_FLAG (0x80000000)
00346 #define PRELOAD_UDP_HEADER_LEN 12
00347 #define PRELOAD_UDP_LAST_PKT_FLAG (0x80000000)
00348 #define PRELOAD_UDP_PKT_NUM_MASK (0x7fffffff)
00349 
00350 class KeepAliveConn: public Continuation
00351 {
00352 public:
00353 
00354   KeepAliveConn()
00355     : Continuation(),  nbytes_added(0)
00356   { ink_zero(ip); }
00357 
00358   int init(IpEndpoint const& ip, MIOBuffer * buf, IOBufferReader * reader);
00359   void free();
00360 
00361   int append(IOBufferReader * reader);
00362   int handleEvent(int event, void *data);
00363 
00364   IpEndpoint ip;
00365 
00366   MIOBuffer *buf;
00367   IOBufferReader *reader;
00368 
00369   MIOBuffer *read_buf;
00370 
00371   NetVConnection *childVC;
00372   VIO *vio;
00373 
00374   KeepAliveConn *next;
00375 
00376   int64_t nbytes_added;
00377 };
00378 
00379 class KeepAliveConnTable
00380 {
00381 public:
00382 
00383   KeepAliveConnTable():arr(NULL)
00384   {
00385   };
00386 
00387   int init();
00388   void free();
00389   static int ip_hash(IpEndpoint const& ip);
00390   int append(IpEndpoint const& ip, MIOBuffer * buf, IOBufferReader * reader);
00391 
00392   typedef struct
00393   {
00394     KeepAliveConn *conn;
00395     Ptr<ProxyMutex> mutex;
00396   } conn_elem;
00397 
00398   conn_elem *arr;
00399 };
00400 extern KeepAliveConnTable *g_conn_table;
00401 
00402 class KeepAliveLockHandler: public Continuation
00403 {
00404   
00405 
00406 public:
00407   KeepAliveLockHandler()
00408     :Continuation()  {
00409     ink_zero(ip);
00410   };
00411 
00412   void init(IpEndpoint const& xip, MIOBuffer * xbuf, IOBufferReader * xreader)
00413   {
00414     mutex = g_conn_table->arr[KeepAliveConnTable::ip_hash(xip)].mutex;
00415 
00416     ats_ip_copy(&ip, &xip);
00417     buf = xbuf;
00418     reader = xreader;
00419 
00420     SET_HANDLER(&KeepAliveLockHandler::handleEvent);
00421     this_ethread()->schedule_in(this, HRTIME_MSECONDS(10));
00422   }
00423 
00424   ~KeepAliveLockHandler() {
00425     mutex = NULL;
00426   }
00427 
00428   int handleEvent(int event, void *data);
00429 
00430   IpEndpoint ip;
00431   MIOBuffer *buf;
00432   IOBufferReader *reader;
00433 };
00434 
00435 
00436 #define PREFETCH_CONFIG_UPDATE_TIMEOUT  (HRTIME_SECOND*60)
00437 
00438 #endif // PREFETCH
00439 
00440 #endif // _PREFETCH_H_