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_